flaska/benchmark/promise.mjs

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