Files
zen/benchmark/compare.mjs
T
stefan-gorules a4cafd0346 chore: add benchmarks (#459)
* chore: add benchmarks for tier 1 languages

* improve fixtures

* fix cargo fmt
2026-06-25 13:38:33 +02:00

55 lines
2.4 KiB
JavaScript

import { execSync, execFileSync } from 'node:child_process';
import { readFileSync, mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const dir = path.dirname(fileURLToPath(import.meta.url));
const root = path.join(dir, '..');
const manifest = JSON.parse(readFileSync(path.join(dir, 'manifest.json'), 'utf8'));
const rowNames = manifest.flatMap((e) => [`${e.name} (${e.kind})`, `${e.name} (${e.kind}) +trace`]);
const langs = [
{ key: 'rust', build: 'build-rust', cmd: path.join(root, 'target', 'release', 'zen-benchmark'), args: ['manifest.json'] },
{ key: 'node', build: 'build-node', cmd: process.execPath, args: [path.join(dir, 'node', 'bench.mjs')] },
{ key: 'python', build: 'build-python', cmd: path.join(dir, '.venv', 'bin', 'python'), args: [path.join(dir, 'python', 'bench.py')] },
];
const tmp = mkdtempSync(path.join(tmpdir(), 'zen-bench-'));
const values = {};
for (const lang of langs) {
try {
execSync(`make ${lang.build}`, { cwd: dir, stdio: 'inherit', env: process.env });
const out = path.join(tmp, `${lang.key}.json`);
execFileSync(lang.cmd, [...lang.args, out], { cwd: dir, stdio: ['ignore', 'ignore', 'inherit'], env: process.env });
const arr = JSON.parse(readFileSync(out, 'utf8'));
values[lang.key] = Object.fromEntries(arr.map((e) => [e.name, e.value]));
} catch (err) {
console.error(`! skipping ${lang.key}: ${err.message}`);
values[lang.key] = null;
}
}
rmSync(tmp, { recursive: true, force: true });
const NAME_W = 52;
const COL_W = 22;
const get = (key, name) => (values[key] ? values[key][name] : undefined);
const cell = (v, base) => {
if (v == null) return 'n/a'.padStart(COL_W);
const ns = `${Math.round(v)} ns`;
if (base == null) return ns.padStart(COL_W);
const mult = base === 0 ? '' : `${(v / base).toFixed(2)}x`;
return `${ns} ${mult}`.padStart(COL_W);
};
const header = `${'fixture'.padEnd(NAME_W)}${['rust', 'node', 'python'].map((l) => l.padStart(COL_W)).join('')}`;
console.log('');
console.log(header);
console.log('-'.repeat(header.length));
for (const name of rowNames) {
const r = get('rust', name);
console.log(`${name.padEnd(NAME_W)}${cell(r, null)}${cell(get('node', name), r)}${cell(get('python', name), r)}`);
}
console.log('');
console.log('x = slowdown vs rust (rust is the baseline floor; lower is better)');