221 lines
No EOL
7.7 KiB
JavaScript
221 lines
No EOL
7.7 KiB
JavaScript
import { summary, run, bench } from 'mitata';
|
|
|
|
// Warmup (de-optimize `bench()` calls)
|
|
bench('noop', () => { });
|
|
bench('noop2', () => { });
|
|
|
|
// Example benchmark
|
|
/*summary(() => {
|
|
const fn = () => null
|
|
const fnAlt = function() {}
|
|
function fnBasic() {}
|
|
const fnAltWithReturn = function() { return null }
|
|
function fnBasicWithReturn() { return null }
|
|
|
|
bench('Reject with uncached error handler', async () => await Promise.reject().catch(() => null));
|
|
bench('Reject with cached error handler', async () => await Promise.reject().catch(fn));
|
|
|
|
bench('TT Reject with uncached error handler', () => Promise.reject().catch(() => null));
|
|
bench('TT Reject with cached error handler', () => Promise.reject().catch(fnAlt));
|
|
bench('TT Reject with cached basic error handler', () => Promise.reject().catch(fnBasic));
|
|
bench('TT Reject with cached error handler with return', () => Promise.reject().catch(fnAltWithReturn));
|
|
bench('TT Reject with cached basic error handler with return ', () => Promise.reject().catch(fnBasicWithReturn));
|
|
});*/
|
|
|
|
/*
|
|
summary(() => {
|
|
function triple () {
|
|
const bla = Math.round(Math.random()) ? true : null
|
|
return bla === null
|
|
}
|
|
function doubleNull () {
|
|
const bla = Math.round(Math.random()) ? true : null
|
|
return bla == null
|
|
}
|
|
function doubleUndefined () {
|
|
const bla = Math.round(Math.random()) ? true : undefined
|
|
return bla == null
|
|
}
|
|
bench('null === null', triple);
|
|
bench('null == null', doubleNull);
|
|
bench('undefined == null', doubleUndefined);
|
|
|
|
bench('2x null === null', triple);
|
|
bench('2x null == null', doubleNull);
|
|
bench('2x undefined == null', doubleUndefined);
|
|
})
|
|
|
|
|
|
summary(() => {
|
|
function triple () {
|
|
const bla = false ? true : null
|
|
return bla === null
|
|
}
|
|
function doubleNull () {
|
|
const bla = false ? true : null
|
|
return bla == null
|
|
}
|
|
function doubleUndefined () {
|
|
const bla = false ? true : undefined
|
|
return bla == null
|
|
}
|
|
bench('const null === null', triple);
|
|
bench('const null == null', doubleNull);
|
|
bench('const undefined == null', doubleUndefined);
|
|
|
|
bench('const 2x null === null', triple);
|
|
bench('const 2x null == null', doubleNull);
|
|
bench('const 2x undefined == null', doubleUndefined);
|
|
})*/
|
|
|
|
function printCurrentStatus(fn) {
|
|
let opt = %GetOptimizationStatus(fn)
|
|
console.log(`${fn.toString()}
|
|
${opt.toString(2).padStart(12, '0').split('').join(' ')}`)
|
|
}
|
|
function printTree() {
|
|
console.log(`┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬
|
|
│ │ │ │ │ │ │ │ │ │ │ └─╸ is function
|
|
│ │ │ │ │ │ │ │ │ │ └───╸ is never optimized
|
|
│ │ │ │ │ │ │ │ │ └─────╸ is always optimized
|
|
│ │ │ │ │ │ │ │ └───────╸ is maybe deoptimized
|
|
│ │ │ │ │ │ │ └─────────╸ is optimized
|
|
│ │ │ │ │ │ └───────────╸ is optimized by TurboFan
|
|
│ │ │ │ │ └─────────────╸ is interpreted
|
|
│ │ │ │ └───────────────╸ is marked for optimization
|
|
│ │ │ └─────────────────╸ is marked for concurrent optimization
|
|
│ │ └───────────────────╸ is optimizing concurrently
|
|
│ └─────────────────────╸ is executing
|
|
└───────────────────────╸ topmost frame is turbo fanned`)
|
|
}
|
|
|
|
let func1
|
|
let func2
|
|
let func3
|
|
|
|
await (async function () {
|
|
return
|
|
const fn1 = async () => await Promise.reject().catch(() => null) === null ? 1 : 0;
|
|
const fn2 = async () => await Promise.reject().catch(() => {}) == null ? 1 : 0;
|
|
const fn3 = async () => await Promise.reject().catch(() => null) == null ? 1 : 0;
|
|
const noop = () => null;
|
|
const fn4 = async () => await Promise.reject().catch(noop) == null ? 1 : 0;
|
|
const fn5 = async () => await Promise.reject().catch(noop) === null ? 1 : 0;
|
|
|
|
|
|
const fn6 = () => Promise.reject().catch(() => null).then(x => x === null ? 1 : 0);
|
|
const fn7 = () => Promise.reject().catch(() => {}).then(x => x == null ? 1 : 0);
|
|
const fn8 = () => Promise.reject().catch(() => null).then(x => x == null ? 1 : 0);
|
|
const fn9 = () => Promise.reject().catch(noop).then(x => x == null ? 1 : 0);
|
|
const fn10 = () => Promise.reject().catch(noop).then(x => x === null ? 1 : 0);
|
|
|
|
func1 = [fn1, fn2, fn3, fn4, fn5, fn6, fn7, fn8, fn9, fn10];
|
|
for (let fun of func1) {
|
|
%OptimizeFunctionOnNextCall(fun);
|
|
}
|
|
for (var i = 0; i < 100000; i++) {
|
|
for (let fun of func1) {
|
|
await fun()
|
|
}
|
|
}
|
|
for (let fun of func1) {
|
|
printCurrentStatus(fun);
|
|
}
|
|
printTree()
|
|
|
|
summary(() => {
|
|
bench('Null with ===', fn1);
|
|
bench('Undefined with ==', fn2);
|
|
bench('Null with ==', fn3);
|
|
bench('Cached Null with ==', fn4);
|
|
bench('Cached Null with ===', fn5);
|
|
|
|
|
|
bench('[sync] Null with ===', fn6);
|
|
bench('[sync] Undefined with ==', fn7);
|
|
bench('[sync] Null with ==', fn8);
|
|
bench('[sync] Cached Null with ==', fn9);
|
|
bench('[sync] Cached Null with ===', fn10);
|
|
});
|
|
})
|
|
|
|
|
|
await (async function () {
|
|
const alt1 = function () { (Math.round(Math.random()) ? null : 1) ?? 0 };
|
|
const alt2 = function () { (Math.round(Math.random()) ? null : 1) || 0 };
|
|
const alt3 = function () { (Math.round(Math.random()) ? undefined : 1) ?? 0 };
|
|
const alt4 = function () { (Math.round(Math.random()) ? undefined : 1) || 0 };
|
|
|
|
let check = new Array(100).fill(0).map(() => Math.round(Math.random()) ? null : 1)
|
|
let check2 = new Array(100).fill(0).map(() => Math.round(Math.random()) ? undefined : 1)
|
|
|
|
const alt5 = function () { let out = 0; for (let x of check) { out += x ?? 0 } return out };
|
|
const alt6 = function () { let out = 0; for (let x of check) { out += x || 0 } return out };
|
|
const alt7 = function () { let out = 0; for (let x of check2) { out += x ?? 0 } return out };
|
|
const alt8 = function () { let out = 0; for (let x of check2) { out += x || 0 } return out };
|
|
|
|
func2 = [alt1, alt2, alt3, alt4, alt5, alt6, alt7, alt8];
|
|
for (let fun of func2) {
|
|
%OptimizeFunctionOnNextCall(fun);
|
|
}
|
|
for (var i = 0; i < 100000; i++) {
|
|
for (let fun of func2) {
|
|
fun()
|
|
}
|
|
}
|
|
for (let fun of func2) {
|
|
printCurrentStatus(fun);
|
|
}
|
|
printTree()
|
|
|
|
summary(() => {
|
|
bench('null/1 ?? 0', alt1);
|
|
bench('null/1 || 0', alt2);
|
|
bench('undefined/1 ?? 0', alt3);
|
|
bench('undefined/1 || 0', alt4);
|
|
});
|
|
|
|
summary(() => {
|
|
bench('arr null/1 ?? null', alt5);
|
|
bench('arr null/1 || null', alt6);
|
|
bench('arr und/1 ?? null', alt7);
|
|
bench('arr und/1 || null', alt8);
|
|
});
|
|
})()
|
|
|
|
|
|
await (async function () {
|
|
const alt1 = function () { let out = 0; for (let x = 0; x < 100; x++) { out += (Math.round(Math.random()) ? null : 1) ?? 0 } return out };
|
|
const alt2 = function () { let out = 0; for (let x = 0; x < 100; x++) { out += (Math.round(Math.random()) ? null : 1) || 0 } return out };
|
|
const alt3 = function () { let out = 0; for (let x = 0; x < 100; x++) { out += (Math.round(Math.random()) ? undefined : 1) ?? 0 } return out };
|
|
const alt4 = function () { let out = 0; for (let x = 0; x < 100; x++) { out += (Math.round(Math.random()) ? undefined : 1) || 0 } return out };
|
|
|
|
func3 = [alt1, alt2, alt3, alt4];
|
|
for (let fun of func3) {
|
|
%OptimizeFunctionOnNextCall(fun);
|
|
}
|
|
for (var i = 0; i < 100000; i++) {
|
|
for (let fun of func3) {
|
|
fun()
|
|
}
|
|
}
|
|
for (let fun of func3) {
|
|
printCurrentStatus(fun);
|
|
}
|
|
printTree()
|
|
|
|
summary(() => {
|
|
bench('loop null/1 ?? 0', alt1);
|
|
bench('loop null/1 || 0', alt2);
|
|
bench('loop und/1 ?? 0', alt3);
|
|
bench('loop und/1 || 0', alt4);
|
|
});
|
|
})()
|
|
|
|
// Start the benchmark
|
|
run().then(() => {
|
|
for (let fun of func3) {
|
|
printCurrentStatus(fun);
|
|
}
|
|
printTree()
|
|
}); |