[VM] Deopt code
const COUNT = Number.parseInt(process.argv[2] || "10");
console.log(`Running ${COUNT} iterations.`);
let value = 0;
export function benchA() {
value = value === 0 ? 0 : 1;
}
export function benchB() {
value = value === 0 ? 0 : 2;
}
export function benchC() {
value = value === 0 ? 0 : 3;
}
export function benchD() {
value = value === 0 ? 0 : 4;
}
//benchmark('-------------------------- IGNORE --------------------------', benchA);
if (require.main === module) {
benchmark("A", benchA);
benchmark("B", benchB);
benchmark("C", benchC);
benchmark("D", benchD);
}
/////////////////////
function benchmark(name: string, fn: () => void) {
console.log("Starting:", name, "...");
const start = performance.now();
for (let i = 0; i < COUNT; i++) {
fn();
}
const duration = performance.now() - start;
console.log(
" ",
name,
Number((duration / COUNT) * 1000 * 1000).toFixed(3),
"us"
);
}
For the code above, we got result that benchmark("A", benchA);
runs twice as faster than others.
The reason is that modern CPU and Javascript engines helps to optimize the code. It tries to do Branch predicition: it sees that value === 0 ? 0 : 1
happens everytimes and it is easily predicatable.
This allow CPU to inlnie the function to make it run faster
for (let i = 0; i < COUNT; i++) {
// fn(); // before inline
value = 0 // after inline
}
But when it comes to run B,C, D benchmark, JS engine see the assumption it made before was wrong, now the has changed. So that it performe deopt operation :
for (let i = 0; i < COUNT; i++) {
// value = 0 // inline
fn(); // deopt
}
that's why, in the end, benchmark A run faster than B,C & D.
Fix the deopt issue:
import { createBenchmark } from "./benchmark";
import { benchA, benchB, benchC, benchD } from "./deopt";
const benchmark = createBenchmark("example2");
let timeA = benchmark("A");
while (timeA()) {
benchA();
}
let timeB = benchmark("B");
while (timeB()) {
benchB();
}
let timeC = benchmark("C");
while (timeC()) {
benchC();
}
let timeD = benchmark("D");
while (timeD()) {
benchD();
}
benchmark.report();
Doing benchmark in four different while loop, so that each while loop can have its own inline function, each they are equaliy fast.