quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

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);