microbench.js (29068B)
1 /* 2 * Javascript Micro benchmark 3 * 4 * Copyright (c) 2017-2019 Fabrice Bellard 5 * Copyright (c) 2017-2019 Charlie Gordon 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 if (typeof require !== 'undefined') { 27 var fs = require('fs'); 28 } 29 30 function pad(str, n) { 31 str += ""; 32 while (str.length < n) 33 str += " "; 34 return str; 35 } 36 37 function pad_left(str, n) { 38 str += ""; 39 while (str.length < n) 40 str = " " + str; 41 return str; 42 } 43 44 function pad_center(str, n) { 45 str += ""; 46 while (str.length < n) { 47 if ((n - str.length) & 1) 48 str = str + " "; 49 else 50 str = " " + str; 51 } 52 return str; 53 } 54 55 function toPrec(n, prec) { 56 var i, s; 57 for (i = 0; i < prec; i++) 58 n *= 10; 59 s = "" + Math.round(n); 60 for (i = s.length - prec; i <= 0; i++) 61 s = "0" + s; 62 if (prec > 0) 63 s = s.substring(0, i) + "." + s.substring(i); 64 return s; 65 } 66 67 var ref_data; 68 var log_data; 69 70 var heads = [ "TEST", "N", "TIME (ns)", "REF (ns)", "SCORE (1000)" ]; 71 var widths = [ 22, 10, 9, 9, 9 ]; 72 var precs = [ 0, 0, 2, 2, 0 ]; 73 var total = [ 0, 0, 0, 0, 0 ]; 74 var total_score = 0; 75 var total_scale = 0; 76 77 function log_line() { 78 var i, n, s, a; 79 s = ""; 80 for (i = 0, n = arguments.length; i < n; i++) { 81 if (i > 0) 82 s += " "; 83 a = arguments[i]; 84 if (typeof a === "number") { 85 total[i] += a; 86 a = toPrec(a, precs[i]); 87 s += pad_left(a, widths[i]); 88 } else { 89 s += pad_left(a, widths[i]); 90 } 91 } 92 console.log(s); 93 } 94 95 var clocks_per_sec = 1000; 96 var max_iterations = 100; 97 var clock_threshold = 2; /* favoring short measuring spans */ 98 var min_n_argument = 1; 99 var get_clock; 100 if (typeof performance !== "undefined") { 101 // use more precise clock on NodeJS 102 // need a method call on performance object 103 get_clock = () => performance.now(); 104 } else 105 if (typeof os !== "undefined") { 106 // use more precise clock on QuickJS 107 get_clock = os.now; 108 } else { 109 // use Date.now and round up to the next millisecond 110 get_clock = () => { 111 var t0 = Date.now(); 112 var t; 113 while ((t = Date.now()) == t0) 114 continue; 115 return t; 116 } 117 } 118 119 function log_one(text, n, ti) { 120 var ref; 121 122 if (ref_data) 123 ref = ref_data[text]; 124 else 125 ref = null; 126 127 ti = Math.round(ti * 100) / 100; 128 log_data[text] = ti; 129 if (typeof ref === "number") { 130 log_line(text, n, ti, ref, Math.round(ref * 1000 / ti)); 131 total_score += ti * 100 / ref; 132 total_scale += 100; 133 } else { 134 log_line(text, n, ti); 135 total_score += 100; 136 total_scale += 100; 137 } 138 } 139 140 function bench(f, text) 141 { 142 var i, j, n, t, ti, nb_its, ref, ti_n, ti_n1; 143 144 nb_its = n = 1; 145 if (f.bench) { 146 ti_n = f(text); 147 } else { 148 // measure ti_n: the shortest time for an individual operation 149 ti_n = 1000000000; 150 for(i = 0; i < 30; i++) { 151 // measure ti: the shortest time for max_iterations iterations 152 ti = 1000000000; 153 for (j = 0; j < max_iterations; j++) { 154 t = get_clock(); 155 nb_its = f(n); 156 t = get_clock() - t; 157 if (nb_its < 0) 158 return; // test failure 159 if (ti > t) 160 ti = t; 161 } 162 if (ti >= clock_threshold / 10) { 163 ti_n1 = ti / nb_its; 164 if (ti_n > ti_n1) 165 ti_n = ti_n1; 166 } 167 if (ti >= clock_threshold && n >= min_n_argument) 168 break; 169 170 n = n * [ 2, 2.5, 2 ][i % 3]; 171 } 172 // to use only the best timing from the last loop, uncomment below 173 //ti_n = ti / nb_its; 174 } 175 /* nano seconds per iteration */ 176 log_one(text, n, ti_n * 1e9 / clocks_per_sec); 177 } 178 179 var global_res; /* to be sure the code is not optimized */ 180 181 function empty_loop(n) { 182 var j; 183 for(j = 0; j < n; j++) { 184 } 185 return n; 186 } 187 188 function empty_down_loop(n) { 189 var j; 190 for(j = n; j > 0; j--) { 191 } 192 return n; 193 } 194 195 function empty_down_loop2(n) { 196 var j; 197 for(j = n; j --> 0;) { 198 } 199 return n; 200 } 201 202 function empty_do_loop(n) { 203 var j = n; 204 do { } while (--j > 0); 205 return n; 206 } 207 208 function date_now(n) { 209 var j; 210 for(j = 0; j < n; j++) { 211 Date.now(); 212 } 213 return n; 214 } 215 216 function date_parse(n) { 217 var x0 = 0, dx = 0; 218 var j; 219 for(j = 0; j < n; j++) { 220 var x1 = x0 - x0 % 1000; 221 var x2 = -x0; 222 var x3 = -x1; 223 var d0 = new Date(x0); 224 var d1 = new Date(x1); 225 var d2 = new Date(x2); 226 var d3 = new Date(x3); 227 if (Date.parse(d0.toISOString()) != x0 228 || Date.parse(d1.toGMTString()) != x1 229 || Date.parse(d1.toString()) != x1 230 || Date.parse(d2.toISOString()) != x2 231 || Date.parse(d3.toGMTString()) != x3 232 || Date.parse(d3.toString()) != x3) { 233 console.log("Date.parse error for " + x0); 234 return -1; 235 } 236 dx = (dx * 1.1 + 1) >> 0; 237 x0 = (x0 + dx) % 8.64e15; 238 } 239 return n * 6; 240 } 241 242 function prop_read(n) 243 { 244 var obj, sum, j; 245 obj = {a: 1, b: 2, c:3, d:4 }; 246 sum = 0; 247 for(j = 0; j < n; j++) { 248 sum += obj.a; 249 sum += obj.b; 250 sum += obj.c; 251 sum += obj.d; 252 } 253 global_res = sum; 254 return n * 4; 255 } 256 257 function prop_write(n) 258 { 259 var obj, j; 260 obj = {a: 1, b: 2, c:3, d:4 }; 261 for(j = 0; j < n; j++) { 262 obj.a = j; 263 obj.b = j; 264 obj.c = j; 265 obj.d = j; 266 } 267 return n * 4; 268 } 269 270 function prop_update(n) 271 { 272 var obj, j; 273 obj = {a: 1, b: 2, c:3, d:4 }; 274 for(j = 0; j < n; j++) { 275 obj.a += j; 276 obj.b += j; 277 obj.c += j; 278 obj.d += j; 279 } 280 return n * 4; 281 } 282 283 function prop_create(n) 284 { 285 var obj, i, j; 286 for(j = 0; j < n; j++) { 287 obj = {}; 288 obj.a = 1; 289 obj.b = 2; 290 obj.c = 3; 291 obj.d = 4; 292 obj.e = 5; 293 obj.f = 6; 294 obj.g = 7; 295 obj.h = 8; 296 obj.i = 9; 297 obj.j = 10; 298 for(i = 0; i < 10; i++) { 299 obj[i] = i; 300 } 301 } 302 return n * 20; 303 } 304 305 function prop_clone(n) 306 { 307 var ref, obj, j, k; 308 ref = { a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8, i:9, j:10 }; 309 for(k = 0; k < 10; k++) { 310 ref[k] = k; 311 } 312 for (j = 0; j < n; j++) { 313 global_res = { ...ref }; 314 } 315 return n * 20; 316 } 317 318 function prop_delete(n) 319 { 320 var ref, obj, j, k; 321 ref = { a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8, i:9, j:10 }; 322 for(k = 0; k < 10; k++) { 323 ref[k] = k; 324 } 325 for (j = 0; j < n; j++) { 326 obj = { ...ref }; 327 delete obj.a; 328 delete obj.b; 329 delete obj.c; 330 delete obj.d; 331 delete obj.e; 332 delete obj.f; 333 delete obj.g; 334 delete obj.h; 335 delete obj.i; 336 delete obj.j; 337 for(k = 0; k < 10; k++) { 338 delete obj[k]; 339 } 340 } 341 return n * 20; 342 } 343 344 function array_read(n) 345 { 346 var tab, len, sum, i, j; 347 tab = []; 348 len = 10; 349 for(i = 0; i < len; i++) 350 tab[i] = i; 351 sum = 0; 352 for(j = 0; j < n; j++) { 353 sum += tab[0]; 354 sum += tab[1]; 355 sum += tab[2]; 356 sum += tab[3]; 357 sum += tab[4]; 358 sum += tab[5]; 359 sum += tab[6]; 360 sum += tab[7]; 361 sum += tab[8]; 362 sum += tab[9]; 363 } 364 global_res = sum; 365 return len * n; 366 } 367 368 function array_write(n) 369 { 370 var tab, len, i, j; 371 tab = []; 372 len = 10; 373 for(i = 0; i < len; i++) 374 tab[i] = i; 375 for(j = 0; j < n; j++) { 376 tab[0] = j; 377 tab[1] = j; 378 tab[2] = j; 379 tab[3] = j; 380 tab[4] = j; 381 tab[5] = j; 382 tab[6] = j; 383 tab[7] = j; 384 tab[8] = j; 385 tab[9] = j; 386 } 387 return len * n; 388 } 389 390 function array_prop_create(n) 391 { 392 var tab, i, j, len; 393 len = 1000; 394 for(j = 0; j < n; j++) { 395 tab = []; 396 for(i = 0; i < len; i++) 397 tab[i] = i; 398 } 399 return len * n; 400 } 401 402 function array_slice(n) 403 { 404 var ref, a, i, j, len; 405 len = 1000; 406 ref = []; 407 for(i = 0; i < len; i++) 408 ref[i] = i; 409 for(j = 0; j < n; j++) { 410 ref[0] = j; 411 a = ref.slice(); 412 a[0] = 0; 413 global_res = a; 414 } 415 return len * n; 416 } 417 418 function array_length_decr(n) 419 { 420 var tab, ref, i, j, len; 421 len = 1000; 422 ref = []; 423 for(i = 0; i < len; i++) 424 ref[i] = i; 425 for(j = 0; j < n; j++) { 426 tab = ref.slice(); 427 for(i = len; i --> 0;) 428 tab.length = i; 429 } 430 return len * n; 431 } 432 433 function array_hole_length_decr(n) 434 { 435 var tab, ref, i, j, len; 436 len = 1000; 437 ref = []; 438 for(i = 0; i < len; i++) { 439 if (i % 10 == 9) 440 ref[i] = i; 441 } 442 for(j = 0; j < n; j++) { 443 tab = ref.slice(); 444 for(i = len; i --> 0;) 445 tab.length = i; 446 } 447 return len * n; 448 } 449 450 function array_push(n) 451 { 452 var tab, i, j, len; 453 len = 500; 454 for(j = 0; j < n; j++) { 455 tab = []; 456 for(i = 0; i < len; i++) 457 tab.push(i); 458 } 459 return len * n; 460 } 461 462 function array_pop(n) 463 { 464 var tab, ref, i, j, len, sum; 465 len = 500; 466 ref = []; 467 for(i = 0; i < len; i++) 468 ref[i] = i; 469 for(j = 0; j < n; j++) { 470 tab = ref.slice(); 471 sum = 0; 472 for(i = 0; i < len; i++) 473 sum += tab.pop(); 474 global_res = sum; 475 } 476 return len * n; 477 } 478 479 function typed_array_read(n) 480 { 481 var tab, len, sum, i, j; 482 len = 10; 483 tab = new Int32Array(len); 484 for(i = 0; i < len; i++) 485 tab[i] = i; 486 sum = 0; 487 for(j = 0; j < n; j++) { 488 sum += tab[0]; 489 sum += tab[1]; 490 sum += tab[2]; 491 sum += tab[3]; 492 sum += tab[4]; 493 sum += tab[5]; 494 sum += tab[6]; 495 sum += tab[7]; 496 sum += tab[8]; 497 sum += tab[9]; 498 } 499 global_res = sum; 500 return len * n; 501 } 502 503 function typed_array_write(n) 504 { 505 var tab, len, i, j; 506 len = 10; 507 tab = new Int32Array(len); 508 for(i = 0; i < len; i++) 509 tab[i] = i; 510 for(j = 0; j < n; j++) { 511 tab[0] = j; 512 tab[1] = j; 513 tab[2] = j; 514 tab[3] = j; 515 tab[4] = j; 516 tab[5] = j; 517 tab[6] = j; 518 tab[7] = j; 519 tab[8] = j; 520 tab[9] = j; 521 } 522 return len * n; 523 } 524 525 var global_var0; 526 527 function global_read(n) 528 { 529 var sum, j; 530 global_var0 = 0; 531 sum = 0; 532 for(j = 0; j < n; j++) { 533 sum += global_var0; 534 sum += global_var0; 535 sum += global_var0; 536 sum += global_var0; 537 } 538 global_res = sum; 539 return n * 4; 540 } 541 542 // non strict version 543 var global_write = 544 (1, eval)(`(function global_write(n) 545 { 546 var j; 547 for(j = 0; j < n; j++) { 548 global_var0 = j; 549 global_var0 = j; 550 global_var0 = j; 551 global_var0 = j; 552 } 553 return n * 4; 554 })`); 555 556 function global_write_strict(n) 557 { 558 var j; 559 for(j = 0; j < n; j++) { 560 global_var0 = j; 561 global_var0 = j; 562 global_var0 = j; 563 global_var0 = j; 564 } 565 return n * 4; 566 } 567 568 function local_destruct(n) 569 { 570 var j, v1, v2, v3, v4; 571 var array = [ 1, 2, 3, 4, 5]; 572 var o = { a:1, b:2, c:3, d:4 }; 573 var a, b, c, d; 574 for(j = 0; j < n; j++) { 575 [ v1, v2,, v3, ...v4] = array; 576 ({ a, b, c, d } = o); 577 ({ a: a, b: b, c: c, d: d } = o); 578 } 579 return n * 12; 580 } 581 582 var global_v1, global_v2, global_v3, global_v4; 583 var global_a, global_b, global_c, global_d; 584 585 // non strict version 586 var global_destruct = 587 (1, eval)(`(function global_destruct(n) 588 { 589 var j, v1, v2, v3, v4; 590 var array = [ 1, 2, 3, 4, 5 ]; 591 var o = { a:1, b:2, c:3, d:4 }; 592 var a, b, c, d; 593 for(j = 0; j < n; j++) { 594 [ global_v1, global_v2,, global_v3, ...global_v4] = array; 595 ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); 596 } 597 return n * 8; 598 })`); 599 600 function global_destruct_strict(n) 601 { 602 var j, v1, v2, v3, v4; 603 var array = [ 1, 2, 3, 4, 5 ]; 604 var o = { a:1, b:2, c:3, d:4 }; 605 var a, b, c, d; 606 for(j = 0; j < n; j++) { 607 [ global_v1, global_v2,, global_v3, ...global_v4] = array; 608 ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); 609 } 610 return n * 8; 611 } 612 613 function g(a) 614 { 615 return 1; 616 } 617 618 function global_func_call(n) 619 { 620 var j, sum; 621 sum = 0; 622 for(j = 0; j < n; j++) { 623 sum += g(j); 624 sum += g(j); 625 sum += g(j); 626 sum += g(j); 627 } 628 global_res = sum; 629 return n * 4; 630 } 631 632 function func_call(n) 633 { 634 function f(a) 635 { 636 return 1; 637 } 638 639 var j, sum; 640 sum = 0; 641 for(j = 0; j < n; j++) { 642 sum += f(j); 643 sum += f(j); 644 sum += f(j); 645 sum += f(j); 646 } 647 global_res = sum; 648 return n * 4; 649 } 650 651 function func_closure_call(n) 652 { 653 function f(a) 654 { 655 sum++; 656 } 657 658 var j, sum; 659 sum = 0; 660 for(j = 0; j < n; j++) { 661 f(j); 662 f(j); 663 f(j); 664 f(j); 665 } 666 global_res = sum; 667 return n * 4; 668 } 669 670 function int_arith(n) 671 { 672 var i, j, sum; 673 global_res = 0; 674 for(j = 0; j < n; j++) { 675 sum = 0; 676 for(i = 0; i < 1000; i++) { 677 sum += i * i; 678 } 679 global_res += sum; 680 } 681 return n * 1000; 682 } 683 684 function float_arith(n) 685 { 686 var i, j, sum, a, incr, a0; 687 global_res = 0; 688 a0 = 0.1; 689 incr = 1.1; 690 for(j = 0; j < n; j++) { 691 sum = 0; 692 a = a0; 693 for(i = 0; i < 1000; i++) { 694 sum += a * a; 695 a += incr; 696 } 697 global_res += sum; 698 } 699 return n * 1000; 700 } 701 702 function bigfloat_arith(n) 703 { 704 var i, j, sum, a, incr, a0; 705 global_res = 0; 706 a0 = BigFloat("0.1"); 707 incr = BigFloat("1.1"); 708 for(j = 0; j < n; j++) { 709 sum = 0; 710 a = a0; 711 for(i = 0; i < 1000; i++) { 712 sum += a * a; 713 a += incr; 714 } 715 global_res += sum; 716 } 717 return n * 1000; 718 } 719 720 function float256_arith(n) 721 { 722 return BigFloatEnv.setPrec(bigfloat_arith.bind(null, n), 237, 19); 723 } 724 725 function bigint_arith(n, bits) 726 { 727 var i, j, sum, a, incr, a0, sum0; 728 sum0 = global_res = BigInt(0); 729 a0 = BigInt(1) << BigInt(Math.floor((bits - 10) * 0.5)); 730 incr = BigInt(1); 731 for(j = 0; j < n; j++) { 732 sum = sum0; 733 a = a0; 734 for(i = 0; i < 1000; i++) { 735 sum += a * a; 736 a += incr; 737 } 738 global_res += sum; 739 } 740 return n * 1000; 741 } 742 743 function bigint64_arith(n) 744 { 745 return bigint_arith(n, 64); 746 } 747 748 function bigint256_arith(n) 749 { 750 return bigint_arith(n, 256); 751 } 752 753 function set_collection_add(n) 754 { 755 var s, i, j, len = 100; 756 for(j = 0; j < n; j++) { 757 s = new Set(); 758 for(i = 0; i < len; i++) { 759 s.add(String(i), i); 760 } 761 for(i = 0; i < len; i++) { 762 if (!s.has(String(i))) 763 throw Error("bug in Set"); 764 } 765 } 766 return n * len; 767 } 768 769 function array_for(n) 770 { 771 var r, i, j, sum, len = 100; 772 r = []; 773 for(i = 0; i < len; i++) 774 r[i] = i; 775 for(j = 0; j < n; j++) { 776 sum = 0; 777 for(i = 0; i < len; i++) { 778 sum += r[i]; 779 } 780 global_res = sum; 781 } 782 return n * len; 783 } 784 785 function array_for_in(n) 786 { 787 var r, i, j, sum, len = 100; 788 r = []; 789 for(i = 0; i < len; i++) 790 r[i] = i; 791 for(j = 0; j < n; j++) { 792 sum = 0; 793 for(i in r) { 794 sum += r[i]; 795 } 796 global_res = sum; 797 } 798 return n * len; 799 } 800 801 function array_for_of(n) 802 { 803 var r, i, j, sum, len = 100; 804 r = []; 805 for(i = 0; i < len; i++) 806 r[i] = i; 807 for(j = 0; j < n; j++) { 808 sum = 0; 809 for(i of r) { 810 sum += i; 811 } 812 global_res = sum; 813 } 814 return n * len; 815 } 816 817 function math_min(n) 818 { 819 var i, j, r; 820 r = 0; 821 for(j = 0; j < n; j++) { 822 for(i = 0; i < 1000; i++) 823 r = Math.min(i, 500); 824 global_res = r; 825 } 826 return n * 1000; 827 } 828 829 function regexp_ascii(n) 830 { 831 var i, j, r, s; 832 s = "the quick brown fox jumped over the lazy dog" 833 for(j = 0; j < n; j++) { 834 for(i = 0; i < 1000; i++) 835 r = /the quick brown fox/.exec(s) 836 global_res = r; 837 } 838 return n * 1000; 839 } 840 841 function regexp_utf16(n) 842 { 843 var i, j, r, s; 844 s = "the quick brown ᶠᵒˣ jumped over the lazy ᵈᵒᵍ" 845 for(j = 0; j < n; j++) { 846 for(i = 0; i < 1000; i++) 847 r = /the quick brown ᶠᵒˣ/.exec(s) 848 global_res = r; 849 } 850 return n * 1000; 851 } 852 853 /* incremental string contruction as local var */ 854 function string_build1(n) 855 { 856 var i, j, r; 857 for(j = 0; j < n; j++) { 858 r = ""; 859 for(i = 0; i < 1000; i++) 860 r += "x"; 861 global_res = r; 862 } 863 return n * 1000; 864 } 865 866 /* incremental string contruction using + */ 867 function string_build1x(n) 868 { 869 var i, j, r; 870 for(j = 0; j < n; j++) { 871 r = ""; 872 for(i = 0; i < 1000; i++) 873 r = r + "x"; 874 global_res = r; 875 } 876 return n * 1000; 877 } 878 879 /* incremental string contruction using +2c */ 880 function string_build2c(n) 881 { 882 var i, j; 883 for(j = 0; j < n; j++) { 884 var r = ""; 885 for(i = 0; i < 1000; i++) 886 r += "xy"; 887 global_res = r; 888 } 889 return n * 1000; 890 } 891 892 /* incremental string contruction as arg */ 893 function string_build2(n, r) 894 { 895 var i, j; 896 for(j = 0; j < n; j++) { 897 r = ""; 898 for(i = 0; i < 1000; i++) 899 r += "x"; 900 global_res = r; 901 } 902 return n * 1000; 903 } 904 905 /* incremental string contruction by prepending */ 906 function string_build3(n) 907 { 908 var i, j, r; 909 for(j = 0; j < n; j++) { 910 r = ""; 911 for(i = 0; i < 1000; i++) 912 r = "x" + r; 913 global_res = r; 914 } 915 return n * 1000; 916 } 917 918 /* incremental string contruction with multiple reference */ 919 function string_build4(n) 920 { 921 var i, j, r, s; 922 for(j = 0; j < n; j++) { 923 r = ""; 924 for(i = 0; i < 1000; i++) { 925 s = r; 926 r += "x"; 927 } 928 global_res = r; 929 } 930 return n * 1000; 931 } 932 933 /* sort bench */ 934 935 function sort_bench(text) { 936 function random(arr, n, def) { 937 for (var i = 0; i < n; i++) 938 arr[i] = def[(Math.random() * n) >> 0]; 939 } 940 function random8(arr, n, def) { 941 for (var i = 0; i < n; i++) 942 arr[i] = def[(Math.random() * 256) >> 0]; 943 } 944 function random1(arr, n, def) { 945 for (var i = 0; i < n; i++) 946 arr[i] = def[(Math.random() * 2) >> 0]; 947 } 948 function hill(arr, n, def) { 949 var mid = n >> 1; 950 for (var i = 0; i < mid; i++) 951 arr[i] = def[i]; 952 for (var i = mid; i < n; i++) 953 arr[i] = def[n - i]; 954 } 955 function comb(arr, n, def) { 956 for (var i = 0; i < n; i++) 957 arr[i] = def[(i & 1) * i]; 958 } 959 function crisscross(arr, n, def) { 960 for (var i = 0; i < n; i++) 961 arr[i] = def[(i & 1) ? n - i : i]; 962 } 963 function zero(arr, n, def) { 964 for (var i = 0; i < n; i++) 965 arr[i] = def[0]; 966 } 967 function increasing(arr, n, def) { 968 for (var i = 0; i < n; i++) 969 arr[i] = def[i]; 970 } 971 function decreasing(arr, n, def) { 972 for (var i = 0; i < n; i++) 973 arr[i] = def[n - 1 - i]; 974 } 975 function alternate(arr, n, def) { 976 for (var i = 0; i < n; i++) 977 arr[i] = def[i ^ 1]; 978 } 979 function jigsaw(arr, n, def) { 980 for (var i = 0; i < n; i++) 981 arr[i] = def[i % (n >> 4)]; 982 } 983 function incbutone(arr, n, def) { 984 for (var i = 0; i < n; i++) 985 arr[i] = def[i]; 986 if (n > 0) 987 arr[n >> 2] = def[n]; 988 } 989 function incbutfirst(arr, n, def) { 990 if (n > 0) 991 arr[0] = def[n]; 992 for (var i = 1; i < n; i++) 993 arr[i] = def[i]; 994 } 995 function incbutlast(arr, n, def) { 996 for (var i = 0; i < n - 1; i++) 997 arr[i] = def[i + 1]; 998 if (n > 0) 999 arr[n - 1] = def[0]; 1000 } 1001 1002 var sort_cases = [ random, random8, random1, jigsaw, hill, comb, 1003 crisscross, zero, increasing, decreasing, alternate, 1004 incbutone, incbutlast, incbutfirst ]; 1005 1006 var n = sort_bench.array_size || 10000; 1007 var array_type = sort_bench.array_type || Array; 1008 var def, arr; 1009 var i, j, x, y; 1010 var total = 0; 1011 1012 var save_total_score = total_score; 1013 var save_total_scale = total_scale; 1014 1015 // initialize default sorted array (n + 1 elements) 1016 def = new array_type(n + 1); 1017 if (array_type == Array) { 1018 for (i = 0; i <= n; i++) { 1019 def[i] = i + ""; 1020 } 1021 } else { 1022 for (i = 0; i <= n; i++) { 1023 def[i] = i; 1024 } 1025 } 1026 def.sort(); 1027 for (var f of sort_cases) { 1028 var ti = 0, tx = 0; 1029 for (j = 0; j < 100; j++) { 1030 arr = new array_type(n); 1031 f(arr, n, def); 1032 var t1 = get_clock(); 1033 arr.sort(); 1034 t1 = get_clock() - t1; 1035 tx += t1; 1036 if (!ti || ti > t1) 1037 ti = t1; 1038 if (tx >= clocks_per_sec) 1039 break; 1040 } 1041 total += ti; 1042 1043 i = 0; 1044 x = arr[0]; 1045 if (x !== void 0) { 1046 for (i = 1; i < n; i++) { 1047 y = arr[i]; 1048 if (y === void 0) 1049 break; 1050 if (x > y) 1051 break; 1052 x = y; 1053 } 1054 } 1055 while (i < n && arr[i] === void 0) 1056 i++; 1057 if (i < n) { 1058 console.log("sort_bench: out of order error for " + f.name + 1059 " at offset " + (i - 1) + 1060 ": " + arr[i - 1] + " > " + arr[i]); 1061 } 1062 if (sort_bench.verbose) 1063 log_one("sort_" + f.name, 1, ti / 100); 1064 } 1065 total_score = save_total_score; 1066 total_scale = save_total_scale; 1067 return total / n / 100; 1068 } 1069 sort_bench.bench = true; 1070 sort_bench.verbose = false; 1071 1072 function int_to_string(n) 1073 { 1074 var s, j; 1075 for(j = 0; j < n; j++) { 1076 s = (j % 1000).toString(); 1077 s = (1234000 + j % 1000).toString(); 1078 } 1079 global_res = s; 1080 return n * 2; 1081 } 1082 1083 function float_to_string(n) 1084 { 1085 var s, j; 1086 for(j = 0; j < n; j++) { 1087 s = (j + 0.1).toString(); 1088 } 1089 global_res = s; 1090 return n; 1091 } 1092 1093 function string_to_int(n) 1094 { 1095 var s, r, j; 1096 r = 0; 1097 s = "12345"; 1098 for(j = 0; j < n; j++) { 1099 r += (s | 0); 1100 } 1101 global_res = r; 1102 return n; 1103 } 1104 1105 function string_to_float(n) 1106 { 1107 var s, r, j; 1108 r = 0; 1109 s = "12345.6"; 1110 for(j = 0; j < n; j++) { 1111 r -= s; 1112 } 1113 global_res = r; 1114 return n; 1115 } 1116 1117 function load_result(filename) 1118 { 1119 var has_filename = filename; 1120 var has_error = false; 1121 var str, res; 1122 1123 if (!filename) 1124 filename = "microbench.txt"; 1125 1126 if (typeof fs !== "undefined") { 1127 // read the file in Node.js 1128 try { 1129 str = fs.readFileSync(filename, { encoding: "utf8" }); 1130 } catch { 1131 has_error = true; 1132 } 1133 } else 1134 if (typeof std !== "undefined") { 1135 // read the file in QuickJS 1136 var f = std.open(filename, "r"); 1137 if (f) { 1138 str = f.readAsString(); 1139 f.close(); 1140 } else { 1141 has_error = true; 1142 } 1143 } else { 1144 return null; 1145 } 1146 if (has_error) { 1147 if (has_filename) { 1148 // Should throw exception? 1149 console.log("cannot load " + filename); 1150 } 1151 return null; 1152 } 1153 res = JSON.parse(str); 1154 return res; 1155 } 1156 1157 function save_result(filename, obj) 1158 { 1159 var str = JSON.stringify(obj, null, 2) + "\n"; 1160 var has_error = false; 1161 1162 if (typeof fs !== "undefined") { 1163 // save the file in Node.js 1164 try { 1165 str = fs.writeFileSync(filename, str, { encoding: "utf8" }); 1166 } catch { 1167 has_error = true; 1168 } 1169 } else 1170 if (typeof std !== "undefined") { 1171 // save the file in QuickJS 1172 var f = std.open(filename, "w"); 1173 if (f) { 1174 f.puts(str); 1175 f.close(); 1176 } else { 1177 has_error = 'true'; 1178 } 1179 } else { 1180 return; 1181 } 1182 if (has_error) 1183 console.log("cannot save " + filename); 1184 } 1185 1186 function main(argc, argv, g) 1187 { 1188 var test_list = [ 1189 empty_loop, 1190 empty_down_loop, 1191 empty_down_loop2, 1192 empty_do_loop, 1193 date_now, 1194 date_parse, 1195 prop_read, 1196 prop_write, 1197 prop_update, 1198 prop_create, 1199 prop_clone, 1200 prop_delete, 1201 array_read, 1202 array_write, 1203 array_prop_create, 1204 array_slice, 1205 array_length_decr, 1206 array_hole_length_decr, 1207 array_push, 1208 array_pop, 1209 typed_array_read, 1210 typed_array_write, 1211 global_read, 1212 global_write, 1213 global_write_strict, 1214 local_destruct, 1215 global_destruct, 1216 global_destruct_strict, 1217 global_func_call, 1218 func_call, 1219 func_closure_call, 1220 int_arith, 1221 float_arith, 1222 set_collection_add, 1223 array_for, 1224 array_for_in, 1225 array_for_of, 1226 math_min, 1227 regexp_ascii, 1228 regexp_utf16, 1229 string_build1, 1230 string_build1x, 1231 string_build2c, 1232 string_build2, 1233 string_build3, 1234 string_build4, 1235 int_to_string, 1236 float_to_string, 1237 string_to_int, 1238 string_to_float, 1239 ]; 1240 var tests = []; 1241 var i, j, n, f, name, found; 1242 var ref_file, new_ref_file = "microbench-new.txt"; 1243 1244 if (typeof BigInt === "function") { 1245 /* BigInt test */ 1246 test_list.push(bigint64_arith); 1247 test_list.push(bigint256_arith); 1248 } 1249 if (typeof BigFloat === "function") { 1250 /* BigFloat test */ 1251 test_list.push(float256_arith); 1252 } 1253 test_list.push(sort_bench); 1254 1255 for (i = 1; i < argc;) { 1256 name = argv[i++]; 1257 if (name == "-a") { 1258 sort_bench.verbose = true; 1259 continue; 1260 } 1261 if (name == "-t") { 1262 name = argv[i++]; 1263 sort_bench.array_type = g[name]; 1264 if (typeof sort_bench.array_type !== "function") { 1265 console.log("unknown array type: " + name); 1266 return 1; 1267 } 1268 continue; 1269 } 1270 if (name == "-n") { 1271 sort_bench.array_size = +argv[i++]; 1272 continue; 1273 } 1274 if (name == "-r") { 1275 ref_file = argv[i++]; 1276 continue; 1277 } 1278 if (name == "-s") { 1279 new_ref_file = argv[i++]; 1280 continue; 1281 } 1282 for (j = 0, found = false; j < test_list.length; j++) { 1283 f = test_list[j]; 1284 if (f.name.startsWith(name)) { 1285 tests.push(f); 1286 found = true; 1287 } 1288 } 1289 if (!found) { 1290 console.log("unknown benchmark: " + name); 1291 return 1; 1292 } 1293 } 1294 if (tests.length == 0) 1295 tests = test_list; 1296 1297 ref_data = load_result(ref_file); 1298 log_data = {}; 1299 log_line.apply(null, heads); 1300 n = 0; 1301 1302 for(i = 0; i < tests.length; i++) { 1303 f = tests[i]; 1304 bench(f, f.name, ref_data, log_data); 1305 if (ref_data && ref_data[f.name]) 1306 n++; 1307 } 1308 if (ref_data) 1309 log_line("total", "", total[2], total[3], Math.round(total_scale * 1000 / total_score)); 1310 else 1311 log_line("total", "", total[2]); 1312 1313 if (tests == test_list && new_ref_file) 1314 save_result(new_ref_file, log_data); 1315 } 1316 1317 if (typeof scriptArgs === "undefined") { 1318 scriptArgs = []; 1319 if (typeof process.argv === "object") 1320 scriptArgs = process.argv.slice(1); 1321 } 1322 main(scriptArgs.length, scriptArgs, this);