quickjs-tart

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

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