Page MenuHomePhorge

bench_jit_method_inlining.js
No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None

bench_jit_method_inlining.js

function nowMs() {
if (typeof performance !== "undefined" && performance && typeof performance.now === "function")
return performance.now();
return Date.now();
}
function parseScale() {
if (typeof process === "undefined" || !process || !process.argv) return 1;
const raw = Number(process.argv[2]);
return Number.isFinite(raw) && raw > 0 ? raw : 1;
}
function sortNumbers(values) {
const out = values.slice();
for (let i = 1; i < out.length; i++) {
const v = out[i];
let j = i - 1;
while (j >= 0 && out[j] > v) {
out[j + 1] = out[j];
j--;
}
out[j + 1] = v;
}
return out;
}
function median(values) {
const sorted = sortNumbers(values);
return sorted[(sorted.length / 2) | 0];
}
const SCALE = parseScale();
const RUNS = 7;
let sink = 0;
function bench(label, iterations, fn) {
for (let i = 0; i < 3; i++) sink ^= fn(Math.max(1, (iterations / 10) | 0)) | 0;
const samples = [];
let result = 0;
for (let i = 0; i < RUNS; i++) {
const t0 = nowMs();
result = fn(iterations);
samples.push(nowMs() - t0);
}
sink ^= result | 0;
const med = median(samples);
const opsPerMs = med > 0 ? (iterations / med).toFixed(2) : "inf";
console.log(label + ": " + med.toFixed(3) + "ms, " + opsPerMs + " ops/ms, result=" + result);
return med;
}
function Sequence(start) {
this.item = start;
}
Sequence.prototype.next = function() {
const old = this.item;
this.item = old + 2;
return old;
};
function runInlineableMethod(n) {
const seq = new Sequence(1);
let out = 0;
for (let i = 0; i < n; i++) out = seq.next();
return out + seq.item;
}
function runManualEquivalent(n) {
const seq = new Sequence(1);
let out = 0;
for (let i = 0; i < n; i++) {
out = seq.item;
seq.item = out + 2;
}
return out + seq.item;
}
function PolyA(start) {
this.item = start;
}
function PolyB(start) {
this.padding = 1;
this.item = start;
}
PolyA.prototype.next = Sequence.prototype.next;
PolyB.prototype.next = Sequence.prototype.next;
function callPoly(obj) {
return obj.next();
}
function runPolymorphicMethod(n) {
const a = new PolyA(1);
const b = new PolyB(1);
let out = 0;
for (let i = 0; i < n; i++) out = callPoly((i & 1) === 0 ? a : b);
return out + a.item + b.item;
}
function Vec2(x, y) {
this.x = x;
this.y = y;
}
Vec2.prototype.sumAndBump = function(dx, dy) {
const old = this.x + this.y;
this.x = this.x + dx;
this.y = this.y + dy;
return old;
};
function runInlineableArgs(n) {
const v = new Vec2(1, 2);
let out = 0;
for (let i = 0; i < n; i++) out = v.sumAndBump(1, 2);
return out + v.x + v.y;
}
function runManualArgs(n) {
const v = new Vec2(1, 2);
let out = 0;
for (let i = 0; i < n; i++) {
out = v.x + v.y;
v.x = v.x + 1;
v.y = v.y + 2;
}
return out + v.x + v.y;
}
function LargeMethod(start) {
this.item = start;
this.flag = false;
}
LargeMethod.prototype.next = function() {
const old = this.item;
this.item = old + 2;
if (this.flag) {
let sum = 0;
sum = sum + old;
sum = sum + this.item;
sum = sum + old;
sum = sum + this.item;
return sum;
}
return old;
};
function runOverBudgetMethod(n) {
const seq = new LargeMethod(1);
let out = 0;
for (let i = 0; i < n; i++) out = seq.next();
return out + seq.item;
}
const iterations = Math.max(100000, Math.floor(1000000 * SCALE));
console.log("method inlining benchmark");
console.log("scale: " + SCALE);
console.log("iterations: " + iterations);
const manual = bench("manual slot loop", iterations, runManualEquivalent);
const inlineable = bench("inlineable method next()", iterations, runInlineableMethod);
const poly = bench("polymorphic method fallback", iterations, runPolymorphicMethod);
const manualArgs = bench("manual arg slot loop", iterations, runManualArgs);
const inlineArgs = bench("inlineable method with args", iterations, runInlineableArgs);
const overBudget = bench("over-budget method", iterations, runOverBudgetMethod);
console.log("next()/manual: " + (inlineable / manual).toFixed(2) + "x");
console.log("polymorphic/inlineable: " + (poly / inlineable).toFixed(2) + "x");
console.log("args/manual: " + (inlineArgs / manualArgs).toFixed(2) + "x");
console.log("over-budget/inlineable: " + (overBudget / inlineable).toFixed(2) + "x");
console.log("sink: " + sink);

File Metadata

Mime Type
application/javascript
Expires
Fri, May 1, 11:39 PM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
543613
Default Alt Text
bench_jit_method_inlining.js (4 KB)

Event Timeline