|
3 | 3 | const benchmark = {}; |
4 | 4 | module.exports = benchmark; |
5 | 5 |
|
6 | | -benchmark.do = (count, retry, tests) => { |
| 6 | +const PRE_COUNT = 1000; |
7 | 7 |
|
8 | | - let k; |
9 | | - for (k = 0; k < retry; k++) { |
10 | | - tests.map(test); |
11 | | - console.log(); |
12 | | - if (global.gc) gc(); |
13 | | - } |
| 8 | +const OPT_STATUS = [ |
| 9 | + /*0*/ '?', // unknown |
| 10 | + /*1*/ '+', // optimized |
| 11 | + /*2*/ '-', // not optimized |
| 12 | + /*3*/ 'a', // always optimized |
| 13 | + /*4*/ 'n', // never optimized |
| 14 | + /*5*/ '?', // unknown, |
| 15 | + /*6*/ 'm', // maybe deoptimized |
| 16 | + /*7*/ 't' // turbofan optimized |
| 17 | +]; |
14 | 18 |
|
15 | | - function test(fn) { |
16 | | - const begin = process.hrtime(); |
17 | | - const a = []; |
| 19 | +const opt = fn => OPT_STATUS[%GetOptimizationStatus(fn)]; |
| 20 | +const optCount = fn => %GetOptimizationCount(fn); |
| 21 | +const optimize = fn => %OptimizeFunctionOnNextCall(fn); |
| 22 | + |
| 23 | +const rpad = (s, char, count) => (s + char.repeat(count - s.length)); |
| 24 | +const lpad = (s, char, count) => (char.repeat(count - s.length) + s); |
| 25 | + |
| 26 | +console.log('\nname (heat) time opt after: define opt heat loop\n'); |
| 27 | + |
| 28 | +benchmark.do = (count, tests) => { |
| 29 | + const times = tests.map((fn) => { |
| 30 | + const result = []; |
18 | 31 | let i; |
19 | | - for (i = 0; i < count; i++) { |
20 | | - a.push(fn()); |
21 | | - } |
| 32 | + const optBefore = opt(fn); |
| 33 | + optimize(fn); |
| 34 | + fn(); |
| 35 | + const optAfter = opt(fn); |
| 36 | + for (i = 0; i < PRE_COUNT; i++) result.push(fn()); |
| 37 | + const optAfterHeat = opt(fn); |
| 38 | + const begin = process.hrtime(); |
| 39 | + for (i = 0; i < count; i++) result.push(fn()); |
22 | 40 | const end = process.hrtime(begin); |
| 41 | + const optAfterLoop = opt(fn); |
23 | 42 | const diff = end[0] * 1e9 + end[1]; |
24 | | - const prefix = '.'.repeat(35 - (diff + fn.name).length); |
25 | | - console.log(fn.name + prefix + diff + ' nanoseconds'); |
26 | | - } |
| 43 | + const time = lpad(diff.toString(), '.', 15); |
| 44 | + const name = rpad(fn.name, '.', 25); |
| 45 | + console.log( |
| 46 | + name + '(' + (result.length - PRE_COUNT) + ')' + |
| 47 | + time + ' nanoseconds ' + optCount(fn) + ' ' + |
| 48 | + optBefore + ' ' + optAfter + ' ' + |
| 49 | + optAfterHeat + ' ' + optAfterLoop |
| 50 | + ); |
| 51 | + return { name, time: diff }; |
| 52 | + }); |
| 53 | + console.log(); |
| 54 | + const top = times.sort((t1, t2) => (t1.time - t2.time)); |
| 55 | + const best = top[0].time; |
| 56 | + const relative = (time) => (time * 100 / best); |
| 57 | + top.forEach((test) => { |
| 58 | + test.percent = Math.round(Math.round(relative(test.time) * 100) / 100) - 100; |
| 59 | + const time = lpad(test.time.toString(), '.', 15); |
| 60 | + const percent = lpad(( |
| 61 | + test.percent === 0 ? 'min' : '+' + test.percent + '%' |
| 62 | + ), '.', 10); |
| 63 | + console.log(test.name + time + percent); |
| 64 | + }); |
27 | 65 | }; |
0 commit comments