/* * Javascript Micro benchmark * * Copyright (c) 2017-2019 Fabrice Bellard * Copyright (c) 2017-2019 Charlie Gordon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ if (typeof require !== 'undefined') { var fs = require('fs'); } function pad(str, n) { str += ""; while (str.length < n) str += " "; return str; } function pad_left(str, n) { str += ""; while (str.length < n) str = " " + str; return str; } function pad_center(str, n) { str += ""; while (str.length < n) { if ((n - str.length) & 1) str = str + " "; else str = " " + str; } return str; } function toPrec(n, prec) { var i, s; for (i = 0; i < prec; i++) n *= 10; s = "" + Math.round(n); for (i = s.length - prec; i <= 0; i++) s = "0" + s; if (prec > 0) s = s.substring(0, i) + "." + s.substring(i); return s; } var ref_data; var log_data; var heads = [ "TEST", "N", "TIME (ns)", "REF (ns)", "SCORE (1000)" ]; var widths = [ 22, 10, 9, 9, 9 ]; var precs = [ 0, 0, 2, 2, 0 ]; var total = [ 0, 0, 0, 0, 0 ]; var total_score = 0; var total_scale = 0; function log_line() { var i, n, s, a; s = ""; for (i = 0, n = arguments.length; i < n; i++) { if (i > 0) s += " "; a = arguments[i]; if (typeof a === "number") { total[i] += a; a = toPrec(a, precs[i]); s += pad_left(a, widths[i]); } else { s += pad_left(a, widths[i]); } } console.log(s); } var clocks_per_sec = 1000; var max_iterations = 100; var clock_threshold = 2; /* favoring short measuring spans */ var min_n_argument = 1; var get_clock; if (typeof performance !== "undefined") { // use more precise clock on NodeJS // need a method call on performance object get_clock = () => performance.now(); } else if (typeof os !== "undefined") { // use more precise clock on QuickJS get_clock = os.now; } else { // use Date.now and round up to the next millisecond get_clock = () => { var t0 = Date.now(); var t; while ((t = Date.now()) == t0) continue; return t; } } function log_one(text, n, ti) { var ref; if (ref_data) ref = ref_data[text]; else ref = null; ti = Math.round(ti * 100) / 100; log_data[text] = ti; if (typeof ref === "number") { log_line(text, n, ti, ref, Math.round(ref * 1000 / ti)); total_score += ti * 100 / ref; total_scale += 100; } else { log_line(text, n, ti); total_score += 100; total_scale += 100; } } function bench(f, text) { var i, j, n, t, ti, nb_its, ref, ti_n, ti_n1; nb_its = n = 1; if (f.bench) { ti_n = f(text); } else { // measure ti_n: the shortest time for an individual operation ti_n = 1000000000; for(i = 0; i < 30; i++) { // measure ti: the shortest time for max_iterations iterations ti = 1000000000; for (j = 0; j < max_iterations; j++) { t = get_clock(); nb_its = f(n); t = get_clock() - t; if (nb_its < 0) return; // test failure if (ti > t) ti = t; } if (ti >= clock_threshold / 10) { ti_n1 = ti / nb_its; if (ti_n > ti_n1) ti_n = ti_n1; } if (ti >= clock_threshold && n >= min_n_argument) break; n = n * [ 2, 2.5, 2 ][i % 3]; } // to use only the best timing from the last loop, uncomment below //ti_n = ti / nb_its; } /* nano seconds per iteration */ log_one(text, n, ti_n * 1e9 / clocks_per_sec); } var global_res; /* to be sure the code is not optimized */ function empty_loop(n) { var j; for(j = 0; j < n; j++) { } return n; } function empty_down_loop(n) { var j; for(j = n; j > 0; j--) { } return n; } function empty_down_loop2(n) { var j; for(j = n; j --> 0;) { } return n; } function empty_do_loop(n) { var j = n; do { } while (--j > 0); return n; } function date_now(n) { var j; for(j = 0; j < n; j++) { Date.now(); } return n; } function date_parse(n) { var x0 = 0, dx = 0; var j; for(j = 0; j < n; j++) { var x1 = x0 - x0 % 1000; var x2 = -x0; var x3 = -x1; var d0 = new Date(x0); var d1 = new Date(x1); var d2 = new Date(x2); var d3 = new Date(x3); if (Date.parse(d0.toISOString()) != x0 || Date.parse(d1.toGMTString()) != x1 || Date.parse(d1.toString()) != x1 || Date.parse(d2.toISOString()) != x2 || Date.parse(d3.toGMTString()) != x3 || Date.parse(d3.toString()) != x3) { console.log("Date.parse error for " + x0); return -1; } dx = (dx * 1.1 + 1) >> 0; x0 = (x0 + dx) % 8.64e15; } return n * 6; } function prop_read(n) { var obj, sum, j; obj = {a: 1, b: 2, c:3, d:4 }; sum = 0; for(j = 0; j < n; j++) { sum += obj.a; sum += obj.b; sum += obj.c; sum += obj.d; } global_res = sum; return n * 4; } function prop_write(n) { var obj, j; obj = {a: 1, b: 2, c:3, d:4 }; for(j = 0; j < n; j++) { obj.a = j; obj.b = j; obj.c = j; obj.d = j; } return n * 4; } function prop_update(n) { var obj, j; obj = {a: 1, b: 2, c:3, d:4 }; for(j = 0; j < n; j++) { obj.a += j; obj.b += j; obj.c += j; obj.d += j; } return n * 4; } function prop_create(n) { var obj, i, j; for(j = 0; j < n; j++) { obj = {}; obj.a = 1; obj.b = 2; obj.c = 3; obj.d = 4; obj.e = 5; obj.f = 6; obj.g = 7; obj.h = 8; obj.i = 9; obj.j = 10; for(i = 0; i < 10; i++) { obj[i] = i; } } return n * 20; } function prop_clone(n) { var ref, obj, j, k; ref = { a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8, i:9, j:10 }; for(k = 0; k < 10; k++) { ref[k] = k; } for (j = 0; j < n; j++) { global_res = { ...ref }; } return n * 20; } function prop_delete(n) { var ref, obj, j, k; ref = { a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8, i:9, j:10 }; for(k = 0; k < 10; k++) { ref[k] = k; } for (j = 0; j < n; j++) { obj = { ...ref }; delete obj.a; delete obj.b; delete obj.c; delete obj.d; delete obj.e; delete obj.f; delete obj.g; delete obj.h; delete obj.i; delete obj.j; for(k = 0; k < 10; k++) { delete obj[k]; } } return n * 20; } function array_read(n) { var tab, len, sum, i, j; tab = []; len = 10; for(i = 0; i < len; i++) tab[i] = i; sum = 0; for(j = 0; j < n; j++) { sum += tab[0]; sum += tab[1]; sum += tab[2]; sum += tab[3]; sum += tab[4]; sum += tab[5]; sum += tab[6]; sum += tab[7]; sum += tab[8]; sum += tab[9]; } global_res = sum; return len * n; } function array_write(n) { var tab, len, i, j; tab = []; len = 10; for(i = 0; i < len; i++) tab[i] = i; for(j = 0; j < n; j++) { tab[0] = j; tab[1] = j; tab[2] = j; tab[3] = j; tab[4] = j; tab[5] = j; tab[6] = j; tab[7] = j; tab[8] = j; tab[9] = j; } return len * n; } function array_prop_create(n) { var tab, i, j, len; len = 1000; for(j = 0; j < n; j++) { tab = []; for(i = 0; i < len; i++) tab[i] = i; } return len * n; } function array_slice(n) { var ref, a, i, j, len; len = 1000; ref = []; for(i = 0; i < len; i++) ref[i] = i; for(j = 0; j < n; j++) { ref[0] = j; a = ref.slice(); a[0] = 0; global_res = a; } return len * n; } function array_length_decr(n) { var tab, ref, i, j, len; len = 1000; ref = []; for(i = 0; i < len; i++) ref[i] = i; for(j = 0; j < n; j++) { tab = ref.slice(); for(i = len; i --> 0;) tab.length = i; } return len * n; } function array_hole_length_decr(n) { var tab, ref, i, j, len; len = 1000; ref = []; for(i = 0; i < len; i++) { if (i % 10 == 9) ref[i] = i; } for(j = 0; j < n; j++) { tab = ref.slice(); for(i = len; i --> 0;) tab.length = i; } return len * n; } function array_push(n) { var tab, i, j, len; len = 500; for(j = 0; j < n; j++) { tab = []; for(i = 0; i < len; i++) tab.push(i); } return len * n; } function array_pop(n) { var tab, ref, i, j, len, sum; len = 500; ref = []; for(i = 0; i < len; i++) ref[i] = i; for(j = 0; j < n; j++) { tab = ref.slice(); sum = 0; for(i = 0; i < len; i++) sum += tab.pop(); global_res = sum; } return len * n; } function typed_array_read(n) { var tab, len, sum, i, j; len = 10; tab = new Int32Array(len); for(i = 0; i < len; i++) tab[i] = i; sum = 0; for(j = 0; j < n; j++) { sum += tab[0]; sum += tab[1]; sum += tab[2]; sum += tab[3]; sum += tab[4]; sum += tab[5]; sum += tab[6]; sum += tab[7]; sum += tab[8]; sum += tab[9]; } global_res = sum; return len * n; } function typed_array_write(n) { var tab, len, i, j; len = 10; tab = new Int32Array(len); for(i = 0; i < len; i++) tab[i] = i; for(j = 0; j < n; j++) { tab[0] = j; tab[1] = j; tab[2] = j; tab[3] = j; tab[4] = j; tab[5] = j; tab[6] = j; tab[7] = j; tab[8] = j; tab[9] = j; } return len * n; } var global_var0; function global_read(n) { var sum, j; global_var0 = 0; sum = 0; for(j = 0; j < n; j++) { sum += global_var0; sum += global_var0; sum += global_var0; sum += global_var0; } global_res = sum; return n * 4; } // non strict version var global_write = (1, eval)(`(function global_write(n) { var j; for(j = 0; j < n; j++) { global_var0 = j; global_var0 = j; global_var0 = j; global_var0 = j; } return n * 4; })`); function global_write_strict(n) { var j; for(j = 0; j < n; j++) { global_var0 = j; global_var0 = j; global_var0 = j; global_var0 = j; } return n * 4; } function local_destruct(n) { var j, v1, v2, v3, v4; var array = [ 1, 2, 3, 4, 5]; var o = { a:1, b:2, c:3, d:4 }; var a, b, c, d; for(j = 0; j < n; j++) { [ v1, v2,, v3, ...v4] = array; ({ a, b, c, d } = o); ({ a: a, b: b, c: c, d: d } = o); } return n * 12; } var global_v1, global_v2, global_v3, global_v4; var global_a, global_b, global_c, global_d; // non strict version var global_destruct = (1, eval)(`(function global_destruct(n) { var j, v1, v2, v3, v4; var array = [ 1, 2, 3, 4, 5 ]; var o = { a:1, b:2, c:3, d:4 }; var a, b, c, d; for(j = 0; j < n; j++) { [ global_v1, global_v2,, global_v3, ...global_v4] = array; ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); } return n * 8; })`); function global_destruct_strict(n) { var j, v1, v2, v3, v4; var array = [ 1, 2, 3, 4, 5 ]; var o = { a:1, b:2, c:3, d:4 }; var a, b, c, d; for(j = 0; j < n; j++) { [ global_v1, global_v2,, global_v3, ...global_v4] = array; ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); } return n * 8; } function g(a) { return 1; } function global_func_call(n) { var j, sum; sum = 0; for(j = 0; j < n; j++) { sum += g(j); sum += g(j); sum += g(j); sum += g(j); } global_res = sum; return n * 4; } function func_call(n) { function f(a) { return 1; } var j, sum; sum = 0; for(j = 0; j < n; j++) { sum += f(j); sum += f(j); sum += f(j); sum += f(j); } global_res = sum; return n * 4; } function func_closure_call(n) { function f(a) { sum++; } var j, sum; sum = 0; for(j = 0; j < n; j++) { f(j); f(j); f(j); f(j); } global_res = sum; return n * 4; } function int_arith(n) { var i, j, sum; global_res = 0; for(j = 0; j < n; j++) { sum = 0; for(i = 0; i < 1000; i++) { sum += i * i; } global_res += sum; } return n * 1000; } function float_arith(n) { var i, j, sum, a, incr, a0; global_res = 0; a0 = 0.1; incr = 1.1; for(j = 0; j < n; j++) { sum = 0; a = a0; for(i = 0; i < 1000; i++) { sum += a * a; a += incr; } global_res += sum; } return n * 1000; } function bigfloat_arith(n) { var i, j, sum, a, incr, a0; global_res = 0; a0 = BigFloat("0.1"); incr = BigFloat("1.1"); for(j = 0; j < n; j++) { sum = 0; a = a0; for(i = 0; i < 1000; i++) { sum += a * a; a += incr; } global_res += sum; } return n * 1000; } function float256_arith(n) { return BigFloatEnv.setPrec(bigfloat_arith.bind(null, n), 237, 19); } function bigint_arith(n, bits) { var i, j, sum, a, incr, a0, sum0; sum0 = global_res = BigInt(0); a0 = BigInt(1) << BigInt(Math.floor((bits - 10) * 0.5)); incr = BigInt(1); for(j = 0; j < n; j++) { sum = sum0; a = a0; for(i = 0; i < 1000; i++) { sum += a * a; a += incr; } global_res += sum; } return n * 1000; } function bigint64_arith(n) { return bigint_arith(n, 64); } function bigint256_arith(n) { return bigint_arith(n, 256); } function set_collection_add(n) { var s, i, j, len = 100; for(j = 0; j < n; j++) { s = new Set(); for(i = 0; i < len; i++) { s.add(String(i), i); } for(i = 0; i < len; i++) { if (!s.has(String(i))) throw Error("bug in Set"); } } return n * len; } function array_for(n) { var r, i, j, sum, len = 100; r = []; for(i = 0; i < len; i++) r[i] = i; for(j = 0; j < n; j++) { sum = 0; for(i = 0; i < len; i++) { sum += r[i]; } global_res = sum; } return n * len; } function array_for_in(n) { var r, i, j, sum, len = 100; r = []; for(i = 0; i < len; i++) r[i] = i; for(j = 0; j < n; j++) { sum = 0; for(i in r) { sum += r[i]; } global_res = sum; } return n * len; } function array_for_of(n) { var r, i, j, sum, len = 100; r = []; for(i = 0; i < len; i++) r[i] = i; for(j = 0; j < n; j++) { sum = 0; for(i of r) { sum += i; } global_res = sum; } return n * len; } function math_min(n) { var i, j, r; r = 0; for(j = 0; j < n; j++) { for(i = 0; i < 1000; i++) r = Math.min(i, 500); global_res = r; } return n * 1000; } function regexp_ascii(n) { var i, j, r, s; s = "the quick brown fox jumped over the lazy dog" for(j = 0; j < n; j++) { for(i = 0; i < 1000; i++) r = /the quick brown fox/.exec(s) global_res = r; } return n * 1000; } function regexp_utf16(n) { var i, j, r, s; s = "the quick brown ᶠᵒˣ jumped over the lazy ᵈᵒᵍ" for(j = 0; j < n; j++) { for(i = 0; i < 1000; i++) r = /the quick brown ᶠᵒˣ/.exec(s) global_res = r; } return n * 1000; } /* incremental string contruction as local var */ function string_build1(n) { var i, j, r; for(j = 0; j < n; j++) { r = ""; for(i = 0; i < 1000; i++) r += "x"; global_res = r; } return n * 1000; } /* incremental string contruction using + */ function string_build1x(n) { var i, j, r; for(j = 0; j < n; j++) { r = ""; for(i = 0; i < 1000; i++) r = r + "x"; global_res = r; } return n * 1000; } /* incremental string contruction using +2c */ function string_build2c(n) { var i, j; for(j = 0; j < n; j++) { var r = ""; for(i = 0; i < 1000; i++) r += "xy"; global_res = r; } return n * 1000; } /* incremental string contruction as arg */ function string_build2(n, r) { var i, j; for(j = 0; j < n; j++) { r = ""; for(i = 0; i < 1000; i++) r += "x"; global_res = r; } return n * 1000; } /* incremental string contruction by prepending */ function string_build3(n) { var i, j, r; for(j = 0; j < n; j++) { r = ""; for(i = 0; i < 1000; i++) r = "x" + r; global_res = r; } return n * 1000; } /* incremental string contruction with multiple reference */ function string_build4(n) { var i, j, r, s; for(j = 0; j < n; j++) { r = ""; for(i = 0; i < 1000; i++) { s = r; r += "x"; } global_res = r; } return n * 1000; } /* sort bench */ function sort_bench(text) { function random(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[(Math.random() * n) >> 0]; } function random8(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[(Math.random() * 256) >> 0]; } function random1(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[(Math.random() * 2) >> 0]; } function hill(arr, n, def) { var mid = n >> 1; for (var i = 0; i < mid; i++) arr[i] = def[i]; for (var i = mid; i < n; i++) arr[i] = def[n - i]; } function comb(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[(i & 1) * i]; } function crisscross(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[(i & 1) ? n - i : i]; } function zero(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[0]; } function increasing(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[i]; } function decreasing(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[n - 1 - i]; } function alternate(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[i ^ 1]; } function jigsaw(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[i % (n >> 4)]; } function incbutone(arr, n, def) { for (var i = 0; i < n; i++) arr[i] = def[i]; if (n > 0) arr[n >> 2] = def[n]; } function incbutfirst(arr, n, def) { if (n > 0) arr[0] = def[n]; for (var i = 1; i < n; i++) arr[i] = def[i]; } function incbutlast(arr, n, def) { for (var i = 0; i < n - 1; i++) arr[i] = def[i + 1]; if (n > 0) arr[n - 1] = def[0]; } var sort_cases = [ random, random8, random1, jigsaw, hill, comb, crisscross, zero, increasing, decreasing, alternate, incbutone, incbutlast, incbutfirst ]; var n = sort_bench.array_size || 10000; var array_type = sort_bench.array_type || Array; var def, arr; var i, j, x, y; var total = 0; var save_total_score = total_score; var save_total_scale = total_scale; // initialize default sorted array (n + 1 elements) def = new array_type(n + 1); if (array_type == Array) { for (i = 0; i <= n; i++) { def[i] = i + ""; } } else { for (i = 0; i <= n; i++) { def[i] = i; } } def.sort(); for (var f of sort_cases) { var ti = 0, tx = 0; for (j = 0; j < 100; j++) { arr = new array_type(n); f(arr, n, def); var t1 = get_clock(); arr.sort(); t1 = get_clock() - t1; tx += t1; if (!ti || ti > t1) ti = t1; if (tx >= clocks_per_sec) break; } total += ti; i = 0; x = arr[0]; if (x !== void 0) { for (i = 1; i < n; i++) { y = arr[i]; if (y === void 0) break; if (x > y) break; x = y; } } while (i < n && arr[i] === void 0) i++; if (i < n) { console.log("sort_bench: out of order error for " + f.name + " at offset " + (i - 1) + ": " + arr[i - 1] + " > " + arr[i]); } if (sort_bench.verbose) log_one("sort_" + f.name, 1, ti / 100); } total_score = save_total_score; total_scale = save_total_scale; return total / n / 100; } sort_bench.bench = true; sort_bench.verbose = false; function int_to_string(n) { var s, j; for(j = 0; j < n; j++) { s = (j % 1000).toString(); s = (1234000 + j % 1000).toString(); } global_res = s; return n * 2; } function float_to_string(n) { var s, j; for(j = 0; j < n; j++) { s = (j + 0.1).toString(); } global_res = s; return n; } function string_to_int(n) { var s, r, j; r = 0; s = "12345"; for(j = 0; j < n; j++) { r += (s | 0); } global_res = r; return n; } function string_to_float(n) { var s, r, j; r = 0; s = "12345.6"; for(j = 0; j < n; j++) { r -= s; } global_res = r; return n; } function load_result(filename) { var has_filename = filename; var has_error = false; var str, res; if (!filename) filename = "microbench.txt"; if (typeof fs !== "undefined") { // read the file in Node.js try { str = fs.readFileSync(filename, { encoding: "utf8" }); } catch { has_error = true; } } else if (typeof std !== "undefined") { // read the file in QuickJS var f = std.open(filename, "r"); if (f) { str = f.readAsString(); f.close(); } else { has_error = true; } } else { return null; } if (has_error) { if (has_filename) { // Should throw exception? console.log("cannot load " + filename); } return null; } res = JSON.parse(str); return res; } function save_result(filename, obj) { var str = JSON.stringify(obj, null, 2) + "\n"; var has_error = false; if (typeof fs !== "undefined") { // save the file in Node.js try { str = fs.writeFileSync(filename, str, { encoding: "utf8" }); } catch { has_error = true; } } else if (typeof std !== "undefined") { // save the file in QuickJS var f = std.open(filename, "w"); if (f) { f.puts(str); f.close(); } else { has_error = 'true'; } } else { return; } if (has_error) console.log("cannot save " + filename); } function main(argc, argv, g) { var test_list = [ empty_loop, empty_down_loop, empty_down_loop2, empty_do_loop, date_now, date_parse, prop_read, prop_write, prop_update, prop_create, prop_clone, prop_delete, array_read, array_write, array_prop_create, array_slice, array_length_decr, array_hole_length_decr, array_push, array_pop, typed_array_read, typed_array_write, global_read, global_write, global_write_strict, local_destruct, global_destruct, global_destruct_strict, global_func_call, func_call, func_closure_call, int_arith, float_arith, set_collection_add, array_for, array_for_in, array_for_of, math_min, regexp_ascii, regexp_utf16, string_build1, string_build1x, string_build2c, string_build2, string_build3, string_build4, int_to_string, float_to_string, string_to_int, string_to_float, ]; var tests = []; var i, j, n, f, name, found; var ref_file, new_ref_file = "microbench-new.txt"; if (typeof BigInt === "function") { /* BigInt test */ test_list.push(bigint64_arith); test_list.push(bigint256_arith); } if (typeof BigFloat === "function") { /* BigFloat test */ test_list.push(float256_arith); } test_list.push(sort_bench); for (i = 1; i < argc;) { name = argv[i++]; if (name == "-a") { sort_bench.verbose = true; continue; } if (name == "-t") { name = argv[i++]; sort_bench.array_type = g[name]; if (typeof sort_bench.array_type !== "function") { console.log("unknown array type: " + name); return 1; } continue; } if (name == "-n") { sort_bench.array_size = +argv[i++]; continue; } if (name == "-r") { ref_file = argv[i++]; continue; } if (name == "-s") { new_ref_file = argv[i++]; continue; } for (j = 0, found = false; j < test_list.length; j++) { f = test_list[j]; if (f.name.startsWith(name)) { tests.push(f); found = true; } } if (!found) { console.log("unknown benchmark: " + name); return 1; } } if (tests.length == 0) tests = test_list; ref_data = load_result(ref_file); log_data = {}; log_line.apply(null, heads); n = 0; for(i = 0; i < tests.length; i++) { f = tests[i]; bench(f, f.name, ref_data, log_data); if (ref_data && ref_data[f.name]) n++; } if (ref_data) log_line("total", "", total[2], total[3], Math.round(total_scale * 1000 / total_score)); else log_line("total", "", total[2]); if (tests == test_list && new_ref_file) save_result(new_ref_file, log_data); } if (typeof scriptArgs === "undefined") { scriptArgs = []; if (typeof process.argv === "object") scriptArgs = process.argv.slice(1); } main(scriptArgs.length, scriptArgs, this);