microbench.js (34056B)
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 var ref_data; 56 var log_data; 57 58 var heads = [ "TEST", "N", "TIME (ns)", "REF (ns)", "SCORE (1000)" ]; 59 var widths = [ 22, 10, 9, 9, 9 ]; 60 var precs = [ 0, 0, 2, 2, 0 ]; 61 var total = [ 0, 0, 0, 0, 0 ]; 62 var total_score = 0; 63 var total_scale = 0; 64 65 function log_line() { 66 var i, n, s, a; 67 s = ""; 68 for (i = 0, n = arguments.length; i < n; i++) { 69 if (i > 0) 70 s += " "; 71 a = arguments[i]; 72 if (typeof a === "number") { 73 total[i] += a; 74 a = a.toFixed(precs[i]); 75 s += pad_left(a, widths[i]); 76 } else { 77 s += pad_left(a, widths[i]); 78 } 79 } 80 console.log(s); 81 } 82 83 var clocks_per_sec = 1000; 84 var max_iterations = 100; 85 var clock_threshold = 2; /* favoring short measuring spans */ 86 var min_n_argument = 1; 87 var get_clock; 88 if (typeof performance !== "undefined") { 89 // use more precise clock on NodeJS 90 // need a method call on performance object 91 get_clock = () => performance.now(); 92 } else 93 if (typeof os !== "undefined") { 94 // use more precise clock on QuickJS 95 get_clock = os.now; 96 } else { 97 // use Date.now and round up to the next millisecond 98 get_clock = () => { 99 var t0 = Date.now(); 100 var t; 101 while ((t = Date.now()) == t0) 102 continue; 103 return t; 104 } 105 } 106 107 function log_one(text, n, ti) { 108 var ref; 109 110 if (ref_data) 111 ref = ref_data[text]; 112 else 113 ref = null; 114 115 ti = Math.round(ti * 100) / 100; 116 log_data[text] = ti; 117 if (typeof ref === "number") { 118 log_line(text, n, ti, ref, Math.round(ref * 1000 / ti)); 119 total_score += ti * 100 / ref; 120 total_scale += 100; 121 } else { 122 log_line(text, n, ti); 123 total_score += 100; 124 total_scale += 100; 125 } 126 } 127 128 function bench(f, text) 129 { 130 var i, j, n, t, ti, nb_its, ref, ti_n, ti_n1; 131 132 nb_its = n = 1; 133 if (f.bench) { 134 ti_n = f(text); 135 } else { 136 // measure ti_n: the shortest time for an individual operation 137 ti_n = 1000000000; 138 for(i = 0; i < 30; i++) { 139 // measure ti: the shortest time for max_iterations iterations 140 ti = 1000000000; 141 for (j = 0; j < max_iterations; j++) { 142 t = get_clock(); 143 nb_its = f(n); 144 t = get_clock() - t; 145 if (nb_its < 0) 146 return; // test failure 147 if (ti > t) 148 ti = t; 149 } 150 if (ti >= clock_threshold / 10) { 151 ti_n1 = ti / nb_its; 152 if (ti_n > ti_n1) 153 ti_n = ti_n1; 154 } 155 if (ti >= clock_threshold && n >= min_n_argument) 156 break; 157 158 n = n * [ 2, 2.5, 2 ][i % 3]; 159 } 160 // to use only the best timing from the last loop, uncomment below 161 //ti_n = ti / nb_its; 162 } 163 /* nano seconds per iteration */ 164 log_one(text, n, ti_n * 1e9 / clocks_per_sec); 165 } 166 167 var global_res; /* to be sure the code is not optimized */ 168 169 function empty_loop(n) { 170 var j; 171 for(j = 0; j < n; j++) { 172 } 173 return n; 174 } 175 176 function empty_down_loop(n) { 177 var j; 178 for(j = n; j > 0; j--) { 179 } 180 return n; 181 } 182 183 function empty_down_loop2(n) { 184 var j; 185 for(j = n; j --> 0;) { 186 } 187 return n; 188 } 189 190 function empty_do_loop(n) { 191 var j = n; 192 do { } while (--j > 0); 193 return n; 194 } 195 196 function date_now(n) { 197 var j; 198 for(j = 0; j < n; j++) { 199 Date.now(); 200 } 201 return n; 202 } 203 204 function date_parse(n) { 205 var x0 = 0, dx = 0; 206 var j; 207 for(j = 0; j < n; j++) { 208 var x1 = x0 - x0 % 1000; 209 var x2 = -x0; 210 var x3 = -x1; 211 var d0 = new Date(x0); 212 var d1 = new Date(x1); 213 var d2 = new Date(x2); 214 var d3 = new Date(x3); 215 if (Date.parse(d0.toISOString()) != x0 216 || Date.parse(d1.toGMTString()) != x1 217 || Date.parse(d1.toString()) != x1 218 || Date.parse(d2.toISOString()) != x2 219 || Date.parse(d3.toGMTString()) != x3 220 || Date.parse(d3.toString()) != x3) { 221 console.log("Date.parse error for " + x0); 222 return -1; 223 } 224 dx = (dx * 1.1 + 1) >> 0; 225 x0 = (x0 + dx) % 8.64e15; 226 } 227 return n * 6; 228 } 229 230 function prop_read(n) 231 { 232 var obj, sum, j; 233 obj = {a: 1, b: 2, c:3, d:4 }; 234 sum = 0; 235 for(j = 0; j < n; j++) { 236 sum += obj.a; 237 sum += obj.b; 238 sum += obj.c; 239 sum += obj.d; 240 } 241 global_res = sum; 242 return n * 4; 243 } 244 245 function prop_write(n) 246 { 247 var obj, j; 248 obj = {a: 1, b: 2, c:3, d:4 }; 249 for(j = 0; j < n; j++) { 250 obj.a = j; 251 obj.b = j; 252 obj.c = j; 253 obj.d = j; 254 } 255 return n * 4; 256 } 257 258 function prop_update(n) 259 { 260 var obj, j; 261 obj = {a: 1, b: 2, c:3, d:4 }; 262 for(j = 0; j < n; j++) { 263 obj.a += j; 264 obj.b += j; 265 obj.c += j; 266 obj.d += j; 267 } 268 return n * 4; 269 } 270 271 function prop_create(n) 272 { 273 var obj, i, j; 274 for(j = 0; j < n; j++) { 275 obj = {}; 276 obj.a = 1; 277 obj.b = 2; 278 obj.c = 3; 279 obj.d = 4; 280 obj.e = 5; 281 obj.f = 6; 282 obj.g = 7; 283 obj.h = 8; 284 obj.i = 9; 285 obj.j = 10; 286 for(i = 0; i < 10; i++) { 287 obj[i] = i; 288 } 289 } 290 return n * 20; 291 } 292 293 function prop_clone(n) 294 { 295 var ref, obj, j, k; 296 ref = { a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8, i:9, j:10 }; 297 for(k = 0; k < 10; k++) { 298 ref[k] = k; 299 } 300 for (j = 0; j < n; j++) { 301 global_res = { ...ref }; 302 } 303 return n * 20; 304 } 305 306 function prop_delete(n) 307 { 308 var ref, obj, j, k; 309 ref = { a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8, i:9, j:10 }; 310 for(k = 0; k < 10; k++) { 311 ref[k] = k; 312 } 313 for (j = 0; j < n; j++) { 314 obj = { ...ref }; 315 delete obj.a; 316 delete obj.b; 317 delete obj.c; 318 delete obj.d; 319 delete obj.e; 320 delete obj.f; 321 delete obj.g; 322 delete obj.h; 323 delete obj.i; 324 delete obj.j; 325 for(k = 0; k < 10; k++) { 326 delete obj[k]; 327 } 328 } 329 return n * 20; 330 } 331 332 function array_read(n) 333 { 334 var tab, len, sum, i, j; 335 tab = []; 336 len = 10; 337 for(i = 0; i < len; i++) 338 tab[i] = i; 339 sum = 0; 340 for(j = 0; j < n; j++) { 341 sum += tab[0]; 342 sum += tab[1]; 343 sum += tab[2]; 344 sum += tab[3]; 345 sum += tab[4]; 346 sum += tab[5]; 347 sum += tab[6]; 348 sum += tab[7]; 349 sum += tab[8]; 350 sum += tab[9]; 351 } 352 global_res = sum; 353 return len * n; 354 } 355 356 function array_write(n) 357 { 358 var tab, len, i, j; 359 tab = []; 360 len = 10; 361 for(i = 0; i < len; i++) 362 tab[i] = i; 363 for(j = 0; j < n; j++) { 364 tab[0] = j; 365 tab[1] = j; 366 tab[2] = j; 367 tab[3] = j; 368 tab[4] = j; 369 tab[5] = j; 370 tab[6] = j; 371 tab[7] = j; 372 tab[8] = j; 373 tab[9] = j; 374 } 375 return len * n; 376 } 377 378 function array_update(n) 379 { 380 var tab, len, i, j; 381 tab = []; 382 len = 10; 383 for(i = 0; i < len; i++) 384 tab[i] = i; 385 for(j = 0; j < n; j++) { 386 tab[0] += j; 387 tab[1] += j; 388 tab[2] += j; 389 tab[3] += j; 390 tab[4] += j; 391 tab[5] += j; 392 tab[6] += j; 393 tab[7] += j; 394 tab[8] += j; 395 tab[9] += j; 396 } 397 return len * n; 398 } 399 400 function array_prop_create(n) 401 { 402 var tab, i, j, len; 403 len = 1000; 404 for(j = 0; j < n; j++) { 405 tab = []; 406 for(i = 0; i < len; i++) 407 tab[i] = i; 408 } 409 return len * n; 410 } 411 412 function array_slice(n) 413 { 414 var ref, a, i, j, len; 415 len = 1000; 416 ref = []; 417 for(i = 0; i < len; i++) 418 ref[i] = i; 419 for(j = 0; j < n; j++) { 420 ref[0] = j; 421 a = ref.slice(); 422 a[0] = 0; 423 global_res = a; 424 } 425 return len * n; 426 } 427 428 function array_length_read(n) 429 { 430 var tab, sum, j; 431 tab = [1, 2, 3]; 432 sum = 0; 433 for(j = 0; j < n; j++) { 434 sum += tab.length; 435 sum += tab.length; 436 sum += tab.length; 437 sum += tab.length; 438 } 439 global_res = sum; 440 return n * 4; 441 } 442 443 function array_length_decr(n) 444 { 445 var tab, ref, i, j, len; 446 len = 1000; 447 ref = []; 448 for(i = 0; i < len; i++) 449 ref[i] = i; 450 for(j = 0; j < n; j++) { 451 tab = ref.slice(); 452 for(i = len; i --> 0;) 453 tab.length = i; 454 } 455 return len * n; 456 } 457 458 function array_hole_length_decr(n) 459 { 460 var tab, ref, i, j, len; 461 len = 1000; 462 ref = []; 463 for(i = 0; i < len; i++) { 464 if (i % 10 == 9) 465 ref[i] = i; 466 } 467 for(j = 0; j < n; j++) { 468 tab = ref.slice(); 469 for(i = len; i --> 0;) 470 tab.length = i; 471 } 472 return len * n; 473 } 474 475 function array_push(n) 476 { 477 var tab, i, j, len; 478 len = 500; 479 for(j = 0; j < n; j++) { 480 tab = []; 481 for(i = 0; i < len; i++) 482 tab.push(i); 483 } 484 return len * n; 485 } 486 487 function array_pop(n) 488 { 489 var tab, ref, i, j, len, sum; 490 len = 500; 491 ref = []; 492 for(i = 0; i < len; i++) 493 ref[i] = i; 494 for(j = 0; j < n; j++) { 495 tab = ref.slice(); 496 sum = 0; 497 for(i = 0; i < len; i++) 498 sum += tab.pop(); 499 global_res = sum; 500 } 501 return len * n; 502 } 503 504 function typed_array_read(n) 505 { 506 var tab, len, sum, i, j; 507 len = 10; 508 tab = new Int32Array(len); 509 for(i = 0; i < len; i++) 510 tab[i] = i; 511 sum = 0; 512 for(j = 0; j < n; j++) { 513 sum += tab[0]; 514 sum += tab[1]; 515 sum += tab[2]; 516 sum += tab[3]; 517 sum += tab[4]; 518 sum += tab[5]; 519 sum += tab[6]; 520 sum += tab[7]; 521 sum += tab[8]; 522 sum += tab[9]; 523 } 524 global_res = sum; 525 return len * n; 526 } 527 528 function typed_array_write(n) 529 { 530 var tab, len, i, j; 531 len = 10; 532 tab = new Int32Array(len); 533 for(i = 0; i < len; i++) 534 tab[i] = i; 535 for(j = 0; j < n; j++) { 536 tab[0] = j; 537 tab[1] = j; 538 tab[2] = j; 539 tab[3] = j; 540 tab[4] = j; 541 tab[5] = j; 542 tab[6] = j; 543 tab[7] = j; 544 tab[8] = j; 545 tab[9] = j; 546 } 547 return len * n; 548 } 549 550 function arguments_test() 551 { 552 return arguments[0] + arguments[1] + arguments[2]; 553 } 554 555 function arguments_read(n) 556 { 557 sum = 0; 558 for(j = 0; j < n; j++) { 559 sum += arguments_test(j, j, j); 560 sum += arguments_test(j, j, j); 561 sum += arguments_test(j, j, j); 562 sum += arguments_test(j, j, j); 563 } 564 global_res = sum; 565 return n * 4; 566 } 567 568 function arguments_strict_test() 569 { 570 "use strict"; 571 return arguments[0] + arguments[1] + arguments[2]; 572 } 573 574 function arguments_strict_read(n) 575 { 576 sum = 0; 577 for(j = 0; j < n; j++) { 578 sum += arguments_strict_test(j, j, j); 579 sum += arguments_strict_test(j, j, j); 580 sum += arguments_strict_test(j, j, j); 581 sum += arguments_strict_test(j, j, j); 582 } 583 global_res = sum; 584 return n * 4; 585 } 586 587 var global_var0; 588 589 function global_read(n) 590 { 591 var sum, j; 592 global_var0 = 0; 593 sum = 0; 594 for(j = 0; j < n; j++) { 595 sum += global_var0; 596 sum += global_var0; 597 sum += global_var0; 598 sum += global_var0; 599 } 600 global_res = sum; 601 return n * 4; 602 } 603 604 function global_write(n) 605 { 606 var j; 607 for(j = 0; j < n; j++) { 608 global_var0 = j; 609 global_var0 = j; 610 global_var0 = j; 611 global_var0 = j; 612 } 613 return n * 4; 614 } 615 616 function global_write_strict(n) 617 { 618 "use strict"; 619 var j; 620 for(j = 0; j < n; j++) { 621 global_var0 = j; 622 global_var0 = j; 623 global_var0 = j; 624 global_var0 = j; 625 } 626 return n * 4; 627 } 628 629 function local_destruct(n) 630 { 631 var j, v1, v2, v3, v4; 632 var array = [ 1, 2, 3, 4, 5]; 633 var o = { a:1, b:2, c:3, d:4 }; 634 var a, b, c, d; 635 for(j = 0; j < n; j++) { 636 [ v1, v2,, v3, ...v4] = array; 637 ({ a, b, c, d } = o); 638 ({ a: a, b: b, c: c, d: d } = o); 639 } 640 return n * 12; 641 } 642 643 var global_v1, global_v2, global_v3, global_v4; 644 var global_a, global_b, global_c, global_d; 645 646 function global_destruct(n) 647 { 648 var j, v1, v2, v3, v4; 649 var array = [ 1, 2, 3, 4, 5 ]; 650 var o = { a:1, b:2, c:3, d:4 }; 651 var a, b, c, d; 652 for(j = 0; j < n; j++) { 653 [ global_v1, global_v2,, global_v3, ...global_v4] = array; 654 ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); 655 } 656 return n * 8; 657 } 658 659 function global_destruct_strict(n) 660 { 661 "use strict"; 662 var j, v1, v2, v3, v4; 663 var array = [ 1, 2, 3, 4, 5 ]; 664 var o = { a:1, b:2, c:3, d:4 }; 665 var a, b, c, d; 666 for(j = 0; j < n; j++) { 667 [ global_v1, global_v2,, global_v3, ...global_v4] = array; 668 ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); 669 } 670 return n * 8; 671 } 672 673 function g(a) 674 { 675 return 1; 676 } 677 678 function global_func_call(n) 679 { 680 var j, sum; 681 sum = 0; 682 for(j = 0; j < n; j++) { 683 sum += g(j); 684 sum += g(j); 685 sum += g(j); 686 sum += g(j); 687 } 688 global_res = sum; 689 return n * 4; 690 } 691 692 function func_call(n) 693 { 694 function f(a) 695 { 696 return 1; 697 } 698 699 var j, sum; 700 sum = 0; 701 for(j = 0; j < n; j++) { 702 sum += f(j); 703 sum += f(j); 704 sum += f(j); 705 sum += f(j); 706 } 707 global_res = sum; 708 return n * 4; 709 } 710 711 function func_closure_call(n) 712 { 713 function f(a) 714 { 715 sum++; 716 } 717 718 var j, sum; 719 sum = 0; 720 for(j = 0; j < n; j++) { 721 f(j); 722 f(j); 723 f(j); 724 f(j); 725 } 726 global_res = sum; 727 return n * 4; 728 } 729 730 function int_arith(n) 731 { 732 var i, j, sum; 733 global_res = 0; 734 for(j = 0; j < n; j++) { 735 sum = 0; 736 for(i = 0; i < 1000; i++) { 737 sum += i * i; 738 } 739 global_res += sum; 740 } 741 return n * 1000; 742 } 743 744 function float_arith(n) 745 { 746 var i, j, sum, a, incr, a0; 747 global_res = 0; 748 a0 = 0.1; 749 incr = 1.1; 750 for(j = 0; j < n; j++) { 751 sum = 0; 752 a = a0; 753 for(i = 0; i < 1000; i++) { 754 sum += a * a; 755 a += incr; 756 } 757 global_res += sum; 758 } 759 return n * 1000; 760 } 761 762 function bigint_arith(n, bits) 763 { 764 var i, j, sum, a, incr, a0, sum0; 765 sum0 = global_res = BigInt(0); 766 a0 = BigInt(1) << BigInt(Math.floor((bits - 10) * 0.5)); 767 incr = BigInt(1); 768 for(j = 0; j < n; j++) { 769 sum = sum0; 770 a = a0; 771 for(i = 0; i < 1000; i++) { 772 sum += a * a; 773 a += incr; 774 } 775 global_res += sum; 776 } 777 return n * 1000; 778 } 779 780 function bigint32_arith(n) 781 { 782 return bigint_arith(n, 32); 783 } 784 785 function bigint64_arith(n) 786 { 787 return bigint_arith(n, 64); 788 } 789 790 function bigint256_arith(n) 791 { 792 return bigint_arith(n, 256); 793 } 794 795 function map_set_string(n) 796 { 797 var s, i, j, len = 1000; 798 for(j = 0; j < n; j++) { 799 s = new Map(); 800 for(i = 0; i < len; i++) { 801 s.set(String(i), i); 802 } 803 for(i = 0; i < len; i++) { 804 if (!s.has(String(i))) 805 throw Error("bug in Map"); 806 } 807 } 808 return n * len; 809 } 810 811 function map_set_int(n) 812 { 813 var s, i, j, len = 1000; 814 for(j = 0; j < n; j++) { 815 s = new Map(); 816 for(i = 0; i < len; i++) { 817 s.set(i, i); 818 } 819 for(i = 0; i < len; i++) { 820 if (!s.has(i)) 821 throw Error("bug in Map"); 822 } 823 } 824 return n * len; 825 } 826 827 function map_set_bigint(n) 828 { 829 var s, i, j, len = 1000; 830 for(j = 0; j < n; j++) { 831 s = new Map(); 832 for(i = 0; i < len; i++) { 833 s.set(BigInt(i), i); 834 } 835 for(i = 0; i < len; i++) { 836 if (!s.has(BigInt(i))) 837 throw Error("bug in Map"); 838 } 839 } 840 return n * len; 841 } 842 843 function map_delete(n) 844 { 845 var a, i, j; 846 847 len = 1000; 848 for(j = 0; j < n; j++) { 849 a = new Map(); 850 for(i = 0; i < len; i++) { 851 a.set(String(i), i); 852 } 853 for(i = 0; i < len; i++) { 854 a.delete(String(i)); 855 } 856 } 857 return len * n; 858 } 859 860 function weak_map_set(n) 861 { 862 var a, i, j, tab; 863 864 len = 1000; 865 tab = []; 866 for(i = 0; i < len; i++) { 867 tab.push({ key: i }); 868 } 869 for(j = 0; j < n; j++) { 870 a = new WeakMap(); 871 for(i = 0; i < len; i++) { 872 a.set(tab[i], i); 873 } 874 } 875 return len * n; 876 } 877 878 function weak_map_delete(n) 879 { 880 var a, i, j, tab; 881 882 len = 1000; 883 for(j = 0; j < n; j++) { 884 tab = []; 885 for(i = 0; i < len; i++) { 886 tab.push({ key: i }); 887 } 888 a = new WeakMap(); 889 for(i = 0; i < len; i++) { 890 a.set(tab[i], i); 891 } 892 for(i = 0; i < len; i++) { 893 tab[i] = null; 894 } 895 } 896 return len * n; 897 } 898 899 900 function array_for(n) 901 { 902 var r, i, j, sum, len = 100; 903 r = []; 904 for(i = 0; i < len; i++) 905 r[i] = i; 906 for(j = 0; j < n; j++) { 907 sum = 0; 908 for(i = 0; i < len; i++) { 909 sum += r[i]; 910 } 911 global_res = sum; 912 } 913 return n * len; 914 } 915 916 function array_for_in(n) 917 { 918 var r, i, j, sum, len = 100; 919 r = []; 920 for(i = 0; i < len; i++) 921 r[i] = i; 922 for(j = 0; j < n; j++) { 923 sum = 0; 924 for(i in r) { 925 sum += r[i]; 926 } 927 global_res = sum; 928 } 929 return n * len; 930 } 931 932 function array_for_of(n) 933 { 934 var r, i, j, sum, len = 100; 935 r = []; 936 for(i = 0; i < len; i++) 937 r[i] = i; 938 for(j = 0; j < n; j++) { 939 sum = 0; 940 for(i of r) { 941 sum += i; 942 } 943 global_res = sum; 944 } 945 return n * len; 946 } 947 948 function math_min(n) 949 { 950 var i, j, r; 951 r = 0; 952 for(j = 0; j < n; j++) { 953 for(i = 0; i < 1000; i++) 954 r = Math.min(i, 500); 955 global_res = r; 956 } 957 return n * 1000; 958 } 959 960 function regexp_ascii(n) 961 { 962 var i, j, r, s; 963 s = "the quick brown fox jumped over the lazy dog" 964 for(j = 0; j < n; j++) { 965 for(i = 0; i < 1000; i++) 966 r = /the quick brown fox/.exec(s) 967 global_res = r; 968 } 969 return n * 1000; 970 } 971 972 function regexp_utf16(n) 973 { 974 var i, j, r, s; 975 s = "the quick brown ᶠᵒˣ jumped over the lazy ᵈᵒᵍ" 976 for(j = 0; j < n; j++) { 977 for(i = 0; i < 1000; i++) 978 r = /the quick brown ᶠᵒˣ/.exec(s) 979 global_res = r; 980 } 981 return n * 1000; 982 } 983 984 function regexp_replace(n) 985 { 986 var i, j, r, s; 987 s = "the quick abc brown fox jumped abc over the lazy dog" 988 for(j = 0; j < n; j++) { 989 for(i = 0; i < 1000; i++) 990 r = s.replace(/abc /g, "-"); 991 global_res = r; 992 } 993 return n * 1000; 994 } 995 996 function string_length(n) 997 { 998 var str, sum, j; 999 str = "abcde"; 1000 sum = 0; 1001 for(j = 0; j < n; j++) { 1002 sum += str.length; 1003 sum += str.length; 1004 sum += str.length; 1005 sum += str.length; 1006 } 1007 global_res = sum; 1008 return n * 4; 1009 } 1010 1011 /* incremental string contruction as local var */ 1012 function string_build1(n) 1013 { 1014 var i, j, r; 1015 for(j = 0; j < n; j++) { 1016 r = ""; 1017 for(i = 0; i < 1000; i++) 1018 r += "x"; 1019 global_res = r; 1020 } 1021 return n * 1000; 1022 } 1023 1024 /* incremental string contruction using + */ 1025 function string_build1x(n) 1026 { 1027 var i, j, r; 1028 for(j = 0; j < n; j++) { 1029 r = ""; 1030 for(i = 0; i < 1000; i++) 1031 r = r + "x"; 1032 global_res = r; 1033 } 1034 return n * 1000; 1035 } 1036 1037 /* incremental string contruction using +2c */ 1038 function string_build2c(n) 1039 { 1040 var i, j; 1041 for(j = 0; j < n; j++) { 1042 var r = ""; 1043 for(i = 0; i < 1000; i++) 1044 r += "xy"; 1045 global_res = r; 1046 } 1047 return n * 1000; 1048 } 1049 1050 /* incremental string contruction as arg */ 1051 function string_build2(n, r) 1052 { 1053 var i, j; 1054 for(j = 0; j < n; j++) { 1055 r = ""; 1056 for(i = 0; i < 1000; i++) 1057 r += "x"; 1058 global_res = r; 1059 } 1060 return n * 1000; 1061 } 1062 1063 /* incremental string contruction by prepending */ 1064 function string_build3(n) 1065 { 1066 var i, j, r; 1067 for(j = 0; j < n; j++) { 1068 r = ""; 1069 for(i = 0; i < 1000; i++) 1070 r = "x" + r; 1071 global_res = r; 1072 } 1073 return n * 1000; 1074 } 1075 1076 /* incremental string contruction with multiple reference */ 1077 function string_build4(n) 1078 { 1079 var i, j, r, s; 1080 for(j = 0; j < n; j++) { 1081 r = ""; 1082 for(i = 0; i < 1000; i++) { 1083 s = r; 1084 r += "x"; 1085 } 1086 global_res = r; 1087 } 1088 return n * 1000; 1089 } 1090 1091 /* append */ 1092 function string_build_large1(n) 1093 { 1094 var i, j, r, len = 20000; 1095 for(j = 0; j < n; j++) { 1096 r = ""; 1097 for(i = 0; i < len; i++) 1098 r += "abcdef"; 1099 global_res = r; 1100 } 1101 return n * len; 1102 } 1103 1104 /* prepend */ 1105 function string_build_large2(n) 1106 { 1107 var i, j, r, len = 20000; 1108 for(j = 0; j < n; j++) { 1109 r = ""; 1110 for(i = 0; i < len; i++) 1111 r = "abcdef" + r; 1112 global_res = r; 1113 } 1114 return n * len; 1115 } 1116 1117 /* sort bench */ 1118 1119 function sort_bench(text) { 1120 function random(arr, n, def) { 1121 for (var i = 0; i < n; i++) 1122 arr[i] = def[(Math.random() * n) >> 0]; 1123 } 1124 function random8(arr, n, def) { 1125 for (var i = 0; i < n; i++) 1126 arr[i] = def[(Math.random() * 256) >> 0]; 1127 } 1128 function random1(arr, n, def) { 1129 for (var i = 0; i < n; i++) 1130 arr[i] = def[(Math.random() * 2) >> 0]; 1131 } 1132 function hill(arr, n, def) { 1133 var mid = n >> 1; 1134 for (var i = 0; i < mid; i++) 1135 arr[i] = def[i]; 1136 for (var i = mid; i < n; i++) 1137 arr[i] = def[n - i]; 1138 } 1139 function comb(arr, n, def) { 1140 for (var i = 0; i < n; i++) 1141 arr[i] = def[(i & 1) * i]; 1142 } 1143 function crisscross(arr, n, def) { 1144 for (var i = 0; i < n; i++) 1145 arr[i] = def[(i & 1) ? n - i : i]; 1146 } 1147 function zero(arr, n, def) { 1148 for (var i = 0; i < n; i++) 1149 arr[i] = def[0]; 1150 } 1151 function increasing(arr, n, def) { 1152 for (var i = 0; i < n; i++) 1153 arr[i] = def[i]; 1154 } 1155 function decreasing(arr, n, def) { 1156 for (var i = 0; i < n; i++) 1157 arr[i] = def[n - 1 - i]; 1158 } 1159 function alternate(arr, n, def) { 1160 for (var i = 0; i < n; i++) 1161 arr[i] = def[i ^ 1]; 1162 } 1163 function jigsaw(arr, n, def) { 1164 for (var i = 0; i < n; i++) 1165 arr[i] = def[i % (n >> 4)]; 1166 } 1167 function incbutone(arr, n, def) { 1168 for (var i = 0; i < n; i++) 1169 arr[i] = def[i]; 1170 if (n > 0) 1171 arr[n >> 2] = def[n]; 1172 } 1173 function incbutfirst(arr, n, def) { 1174 if (n > 0) 1175 arr[0] = def[n]; 1176 for (var i = 1; i < n; i++) 1177 arr[i] = def[i]; 1178 } 1179 function incbutlast(arr, n, def) { 1180 for (var i = 0; i < n - 1; i++) 1181 arr[i] = def[i + 1]; 1182 if (n > 0) 1183 arr[n - 1] = def[0]; 1184 } 1185 1186 var sort_cases = [ random, random8, random1, jigsaw, hill, comb, 1187 crisscross, zero, increasing, decreasing, alternate, 1188 incbutone, incbutlast, incbutfirst ]; 1189 1190 var n = sort_bench.array_size || 10000; 1191 var array_type = sort_bench.array_type || Array; 1192 var def, arr; 1193 var i, j, x, y; 1194 var total = 0; 1195 1196 var save_total_score = total_score; 1197 var save_total_scale = total_scale; 1198 1199 // initialize default sorted array (n + 1 elements) 1200 def = new array_type(n + 1); 1201 if (array_type == Array) { 1202 for (i = 0; i <= n; i++) { 1203 def[i] = i + ""; 1204 } 1205 } else { 1206 for (i = 0; i <= n; i++) { 1207 def[i] = i; 1208 } 1209 } 1210 def.sort(); 1211 for (var f of sort_cases) { 1212 var ti = 0, tx = 0; 1213 for (j = 0; j < 100; j++) { 1214 arr = new array_type(n); 1215 f(arr, n, def); 1216 var t1 = get_clock(); 1217 arr.sort(); 1218 t1 = get_clock() - t1; 1219 tx += t1; 1220 if (!ti || ti > t1) 1221 ti = t1; 1222 if (tx >= clocks_per_sec) 1223 break; 1224 } 1225 total += ti; 1226 1227 i = 0; 1228 x = arr[0]; 1229 if (x !== void 0) { 1230 for (i = 1; i < n; i++) { 1231 y = arr[i]; 1232 if (y === void 0) 1233 break; 1234 if (x > y) 1235 break; 1236 x = y; 1237 } 1238 } 1239 while (i < n && arr[i] === void 0) 1240 i++; 1241 if (i < n) { 1242 console.log("sort_bench: out of order error for " + f.name + 1243 " at offset " + (i - 1) + 1244 ": " + arr[i - 1] + " > " + arr[i]); 1245 } 1246 if (sort_bench.verbose) 1247 log_one("sort_" + f.name, 1, ti / 100); 1248 } 1249 total_score = save_total_score; 1250 total_scale = save_total_scale; 1251 return total / n / 100; 1252 } 1253 sort_bench.bench = true; 1254 sort_bench.verbose = false; 1255 1256 function int_to_string(n) 1257 { 1258 var s, r, j; 1259 r = 0; 1260 for(j = 0; j < n; j++) { 1261 s = (j % 10) + ''; 1262 s = (j % 100) + ''; 1263 s = (j) + ''; 1264 } 1265 return n * 3; 1266 } 1267 1268 function int_toString(n) 1269 { 1270 var s, r, j; 1271 r = 0; 1272 for(j = 0; j < n; j++) { 1273 s = (j % 10).toString(); 1274 s = (j % 100).toString(); 1275 s = (j).toString(); 1276 } 1277 return n * 3; 1278 } 1279 1280 function float_to_string(n) 1281 { 1282 var s, r, j; 1283 r = 0; 1284 for(j = 0; j < n; j++) { 1285 s = (j % 10 + 0.1) + ''; 1286 s = (j + 0.1) + ''; 1287 s = (j * 12345678 + 0.1) + ''; 1288 } 1289 return n * 3; 1290 } 1291 1292 function float_toString(n) 1293 { 1294 var s, r, j; 1295 r = 0; 1296 for(j = 0; j < n; j++) { 1297 s = (j % 10 + 0.1).toString(); 1298 s = (j + 0.1).toString(); 1299 s = (j * 12345678 + 0.1).toString(); 1300 } 1301 return n * 3; 1302 } 1303 1304 function float_toFixed(n) 1305 { 1306 var s, r, j; 1307 r = 0; 1308 for(j = 0; j < n; j++) { 1309 s = (j % 10 + 0.1).toFixed(j % 16); 1310 s = (j + 0.1).toFixed(j % 16); 1311 s = (j * 12345678 + 0.1).toFixed(j % 16); 1312 } 1313 return n * 3; 1314 } 1315 1316 function float_toPrecision(n) 1317 { 1318 var s, r, j; 1319 r = 0; 1320 for(j = 0; j < n; j++) { 1321 s = (j % 10 + 0.1).toPrecision(j % 16 + 1); 1322 s = (j + 0.1).toPrecision(j % 16 + 1); 1323 s = (j * 12345678 + 0.1).toPrecision(j % 16 + 1); 1324 } 1325 return n * 3; 1326 } 1327 1328 function float_toExponential(n) 1329 { 1330 var s, r, j; 1331 r = 0; 1332 for(j = 0; j < n; j++) { 1333 s = (j % 10 + 0.1).toExponential(j % 16); 1334 s = (j + 0.1).toExponential(j % 16); 1335 s = (j * 12345678 + 0.1).toExponential(j % 16); 1336 } 1337 return n * 3; 1338 } 1339 1340 function string_to_int(n) 1341 { 1342 var s, r, j; 1343 r = 0; 1344 s = "12345"; 1345 for(j = 0; j < n; j++) { 1346 r += (s | 0); 1347 } 1348 global_res = r; 1349 return n; 1350 } 1351 1352 function string_to_float(n) 1353 { 1354 var s, r, j; 1355 r = 0; 1356 s = "12345.6"; 1357 for(j = 0; j < n; j++) { 1358 r -= s; 1359 } 1360 global_res = r; 1361 return n; 1362 } 1363 1364 function load_result(filename) 1365 { 1366 var has_filename = filename; 1367 var has_error = false; 1368 var str, res; 1369 1370 if (!filename) 1371 filename = "microbench.txt"; 1372 1373 if (typeof fs !== "undefined") { 1374 // read the file in Node.js 1375 try { 1376 str = fs.readFileSync(filename, { encoding: "utf8" }); 1377 } catch { 1378 has_error = true; 1379 } 1380 } else 1381 if (typeof std !== "undefined") { 1382 // read the file in QuickJS 1383 var f = std.open(filename, "r"); 1384 if (f) { 1385 str = f.readAsString(); 1386 f.close(); 1387 } else { 1388 has_error = true; 1389 } 1390 } else { 1391 return null; 1392 } 1393 if (has_error) { 1394 if (has_filename) { 1395 // Should throw exception? 1396 console.log("cannot load " + filename); 1397 } 1398 return null; 1399 } 1400 res = JSON.parse(str); 1401 return res; 1402 } 1403 1404 function save_result(filename, obj) 1405 { 1406 var str = JSON.stringify(obj, null, 2) + "\n"; 1407 var has_error = false; 1408 1409 if (typeof fs !== "undefined") { 1410 // save the file in Node.js 1411 try { 1412 str = fs.writeFileSync(filename, str, { encoding: "utf8" }); 1413 } catch { 1414 has_error = true; 1415 } 1416 } else 1417 if (typeof std !== "undefined") { 1418 // save the file in QuickJS 1419 var f = std.open(filename, "w"); 1420 if (f) { 1421 f.puts(str); 1422 f.close(); 1423 } else { 1424 has_error = 'true'; 1425 } 1426 } else { 1427 return; 1428 } 1429 if (has_error) 1430 console.log("cannot save " + filename); 1431 } 1432 1433 function main(argc, argv, g) 1434 { 1435 var test_list = [ 1436 empty_loop, 1437 empty_down_loop, 1438 empty_down_loop2, 1439 empty_do_loop, 1440 date_now, 1441 date_parse, 1442 prop_read, 1443 prop_write, 1444 prop_update, 1445 prop_create, 1446 prop_clone, 1447 prop_delete, 1448 array_read, 1449 array_write, 1450 array_update, 1451 array_prop_create, 1452 array_slice, 1453 array_length_read, 1454 array_length_decr, 1455 array_hole_length_decr, 1456 array_push, 1457 array_pop, 1458 typed_array_read, 1459 typed_array_write, 1460 arguments_read, 1461 arguments_strict_read, 1462 global_read, 1463 global_write, 1464 global_write_strict, 1465 local_destruct, 1466 global_destruct, 1467 global_destruct_strict, 1468 global_func_call, 1469 func_call, 1470 func_closure_call, 1471 int_arith, 1472 float_arith, 1473 map_set_string, 1474 map_set_int, 1475 map_set_bigint, 1476 map_delete, 1477 weak_map_set, 1478 weak_map_delete, 1479 array_for, 1480 array_for_in, 1481 array_for_of, 1482 math_min, 1483 regexp_ascii, 1484 regexp_utf16, 1485 regexp_replace, 1486 string_length, 1487 string_build1, 1488 string_build1x, 1489 string_build2c, 1490 string_build2, 1491 string_build3, 1492 string_build4, 1493 string_build_large1, 1494 string_build_large2, 1495 int_to_string, 1496 int_toString, 1497 float_to_string, 1498 float_toString, 1499 float_toFixed, 1500 float_toPrecision, 1501 float_toExponential, 1502 string_to_int, 1503 string_to_float, 1504 ]; 1505 var tests = []; 1506 var i, j, n, f, name, found; 1507 var ref_file, new_ref_file = "microbench-new.txt"; 1508 1509 if (typeof BigInt === "function") { 1510 /* BigInt test */ 1511 test_list.push(bigint32_arith); 1512 test_list.push(bigint64_arith); 1513 test_list.push(bigint256_arith); 1514 } 1515 test_list.push(sort_bench); 1516 1517 for (i = 1; i < argc;) { 1518 name = argv[i++]; 1519 if (name == "-a") { 1520 sort_bench.verbose = true; 1521 continue; 1522 } 1523 if (name == "-t") { 1524 name = argv[i++]; 1525 sort_bench.array_type = g[name]; 1526 if (typeof sort_bench.array_type !== "function") { 1527 console.log("unknown array type: " + name); 1528 return 1; 1529 } 1530 continue; 1531 } 1532 if (name == "-n") { 1533 sort_bench.array_size = +argv[i++]; 1534 continue; 1535 } 1536 if (name == "-r") { 1537 ref_file = argv[i++]; 1538 continue; 1539 } 1540 if (name == "-s") { 1541 new_ref_file = argv[i++]; 1542 continue; 1543 } 1544 for (j = 0, found = false; j < test_list.length; j++) { 1545 f = test_list[j]; 1546 if (f.name.startsWith(name)) { 1547 tests.push(f); 1548 found = true; 1549 } 1550 } 1551 if (!found) { 1552 console.log("unknown benchmark: " + name); 1553 return 1; 1554 } 1555 } 1556 if (tests.length == 0) 1557 tests = test_list; 1558 1559 ref_data = load_result(ref_file); 1560 log_data = {}; 1561 log_line.apply(null, heads); 1562 n = 0; 1563 1564 for(i = 0; i < tests.length; i++) { 1565 f = tests[i]; 1566 bench(f, f.name, ref_data, log_data); 1567 if (ref_data && ref_data[f.name]) 1568 n++; 1569 } 1570 if (ref_data) 1571 log_line("total", "", total[2], total[3], Math.round(total_scale * 1000 / total_score)); 1572 else 1573 log_line("total", "", total[2]); 1574 1575 if (tests == test_list && new_ref_file) 1576 save_result(new_ref_file, log_data); 1577 } 1578 1579 if (typeof scriptArgs === "undefined") { 1580 if (typeof process !== "undefined" && typeof process.argv === "object") { 1581 /* node case */ 1582 scriptArgs = process.argv.slice(1); 1583 } else if (typeof arguments !== "undefined") { 1584 /* d8 case */ 1585 scriptArgs = arguments; 1586 } else { 1587 scriptArgs = []; 1588 } 1589 } 1590 main(scriptArgs.length, scriptArgs, this);