Skip to content

Instantly share code, notes, and snippets.

@billywhizz
Last active February 28, 2026 02:49
Show Gist options
  • Select an option

  • Save billywhizz/e8275a3a90504b0549de3c075bd5a278 to your computer and use it in GitHub Desktop.

Select an option

Save billywhizz/e8275a3a90504b0549de3c075bd5a278 to your computer and use it in GitHub Desktop.
  • Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
  • #100~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC x86_64 GNU/Linux
$ node async-bench.js 
node_v24.13.1    sync time            time     1537 rate     19514068 rate/core     19514068 ns/iter        51.24 rss     58302464 usr 100.00 sys   0.00 tot 100.00
node_v24.13.1    sync time            time     1514 rate     19814339 rate/core     19814339 ns/iter        50.46 rss     58937344 usr 100.00 sys   0.00 tot 100.00
node_v24.13.1    sync time            time     1473 rate     20361091 rate/core     20361091 ns/iter        49.11 rss     58937344 usr 100.00 sys   0.00 tot 100.00
node_v24.13.1    sync time            time     1451 rate     20674993 rate/core     20883832 ns/iter        48.36 rss     58937344 usr  99.00 sys   0.00 tot  99.00
node_v24.13.1    sync time            time     1479 rate     20270737 rate/core     20270737 ns/iter        49.33 rss     58937344 usr 100.00 sys   0.00 tot 100.00
node_v24.13.1    async time           time     4235 rate      7082929 rate/core      7082929 ns/iter       141.18 rss     61296640 usr 100.00 sys   0.00 tot 100.00
node_v24.13.1    async time           time     4331 rate      6925612 rate/core      6995567 ns/iter       144.39 rss     61640704 usr  99.00 sys   0.00 tot  99.00
node_v24.13.1    async time           time     4226 rate      7097514 rate/core      7097514 ns/iter       140.89 rss     62033920 usr 100.00 sys   0.00 tot 100.00
node_v24.13.1    async time           time     4391 rate      6830713 rate/core      6899710 ns/iter       146.39 rss     66490368 usr  99.00 sys   0.00 tot  99.00
node_v24.13.1    async time           time     4151 rate      7225685 rate/core      7298671 ns/iter       138.39 rss     66883584 usr  99.00 sys   0.00 tot  99.00
$ deno -A async-bench.js 
deno_2.6.9       sync time            time     1948 rate     15393719 rate/core     15393719 ns/iter        64.96 rss     68653056 usr 100.00 sys   0.00 tot 100.00
deno_2.6.9       sync time            time     1957 rate     15329260 rate/core     15329260 ns/iter        65.23 rss     69701632 usr 100.00 sys   0.00 tot 100.00
deno_2.6.9       sync time            time     1949 rate     15390332 rate/core     15390332 ns/iter        64.97 rss     69832704 usr 100.00 sys   0.00 tot 100.00
deno_2.6.9       sync time            time     1950 rate     15382328 rate/core     15382328 ns/iter        65.00 rss     69832704 usr 100.00 sys   0.00 tot 100.00
deno_2.6.9       sync time            time     1979 rate     15154244 rate/core     15154244 ns/iter        65.98 rss     69832704 usr 100.00 sys   0.00 tot 100.00
deno_2.6.9       async time           time     4204 rate      7135745 rate/core      7135745 ns/iter       140.13 rss     70356992 usr 100.00 sys   0.00 tot 100.00
deno_2.6.9       async time           time     4228 rate      7094745 rate/core      7094745 ns/iter       140.94 rss     70750208 usr 100.00 sys   0.00 tot 100.00
deno_2.6.9       async time           time     4152 rate      7224444 rate/core      7297419 ns/iter       138.41 rss     73109504 usr  99.00 sys   0.00 tot  99.00
deno_2.6.9       async time           time     4178 rate      7179852 rate/core      7179852 ns/iter       139.27 rss     73240576 usr 100.00 sys   0.00 tot 100.00
deno_2.6.9       async time           time     4156 rate      7218456 rate/core      7218456 ns/iter       138.53 rss     73502720 usr 100.00 sys   0.00 tot 100.00
$ bun async-bench.js 
bun_1.3.9        sync time            time      935 rate     32079314 rate/core     31761697 ns/iter        31.17 rss     52297728 usr 100.00 sys   1.00 tot 101.00
bun_1.3.9        sync time            time      960 rate     31243256 rate/core     31243256 ns/iter        32.00 rss     53350400 usr 100.00 sys   0.00 tot 100.00
bun_1.3.9        sync time            time      927 rate     32355038 rate/core     32355038 ns/iter        30.90 rss     53194752 usr 100.00 sys   0.00 tot 100.00
bun_1.3.9        sync time            time      928 rate     32315024 rate/core     32315024 ns/iter        30.94 rss     53194752 usr 100.00 sys   0.00 tot 100.00
bun_1.3.9        sync time            time      933 rate     32147317 rate/core     32472037 ns/iter        31.10 rss     53194752 usr  99.00 sys   0.00 tot  99.00
bun_1.3.9        async time           time     4880 rate      6147382 rate/core      6209477 ns/iter       162.67 rss     88887296 usr  99.00 sys   0.00 tot  99.00
bun_1.3.9        async time           time     4931 rate      6083100 rate/core      6083100 ns/iter       164.38 rss     88449024 usr 100.00 sys   0.00 tot 100.00
bun_1.3.9        async time           time     4961 rate      6046070 rate/core      6107142 ns/iter       165.39 rss     85786624 usr  99.00 sys   0.00 tot  99.00
bun_1.3.9        async time           time     4838 rate      6199965 rate/core      6262591 ns/iter       161.29 rss     85786624 usr  99.00 sys   0.00 tot  99.00
bun_1.3.9        async time           time     4836 rate      6202244 rate/core      6202244 ns/iter       161.23 rss     85786624 usr 100.00 sys   0.00 tot 100.00
import { Bench } from './bench.js'
const bench = new Bench()
const iter = 5
function time() {
return performance.now()
}
{
const runs = 30000000
for (let i = 0; i < iter; i++) {
bench.start('sync time')
for (let j = 0; j < runs; j++) {
assert(time())
}
bench.end(runs)
}
}
{
const runs = 30000000
for (let i = 0; i < iter; i++) {
bench.start('async time')
for (let j = 0; j < runs; j++) {
assert((await time()))
}
bench.end(runs)
}
}
/*
this runs on bun/lo/deno/node on macos and linux
need to test on windows
*/
function is_a_tty(fd = 1) {
if (globalThis.Deno) return Deno.isatty(fd);
if (globalThis.lo) return lo.core.isatty(fd);
if (fd === 1) return process.stdout.isTTY;
if (fd === 2) return process.stderr.isTTY;
return process.stdin.isTTY;
}
const isatty = is_a_tty();
const AD = isatty ? "\u001b[0m" : ""; // ANSI Default
const A0 = isatty ? "\u001b[30m" : ""; // ANSI Black
const AR = isatty ? "\u001b[31m" : ""; // ANSI Red
const AG = isatty ? "\u001b[32m" : ""; // ANSI Green
const AY = isatty ? "\u001b[33m" : ""; // ANSI Yellow
const AB = isatty ? "\u001b[34m" : ""; // ANSI Blue
const AM = isatty ? "\u001b[35m" : ""; // ANSI Magenta
const AC = isatty ? "\u001b[36m" : ""; // ANSI Cyan
const AW = isatty ? "\u001b[37m" : ""; // ANSI White
const colors = { AD, AG, AY, AM, AD, AR, AB, AC, AW, A0 };
const decoder = new TextDecoder();
const encoder = new TextEncoder();
class Stats {
recv = 0;
send = 0;
conn = 0;
rps = 0;
log() {
const { send, recv, conn, rps } = this;
const [usr, sys] = cputime();
const rps_per_core = Math.floor(rps / ((usr + sys) / 100))
console.log(
`${AC}send${AD} ${to_size_string(send)} ${AC}recv${AD} ${to_size_string(recv)} ${AC}rps${AD} ${rps.toString().padStart(10, ' ')} ${AM}rps/core${AD} ${rps_per_core.toString().padStart(10, ' ')} ${AC}rss${AD} ${mem().toString().padStart(12, ' ')} ${AC}con${AD} ${conn} ${AY}usr${AD} ${usr.toString().padStart(3, " ")} ${AY}sys${AD} ${sys.toString().padStart(3, " ")} ${AY}tot${AD} ${(usr + sys).toString().padStart(3, " ")}`,
);
this.send = this.recv = this.rps = 0;
}
get runtime() {
return lo.hrtime() - lo.start;
}
}
function pad(v, size, precision = 0) {
return v.toFixed(precision).padStart(size, " ");
}
function memory_usage(buf) {
return Math.floor(Number(decoder.decode(buf).split(" ")[23]) * 4096);
}
let lastusr = 0;
let lastsys = 0;
let last_time = Date.now();
function cpu_usage(bytes) {
const str = decoder.decode(bytes);
const parts = str.split(" ");``
const elapsed = Date.now() - last_time;
const usr = Number(parts[13]);
const sys = Number(parts[14]);
const res = [(((usr - lastusr) * 10) / elapsed) * 100, (((sys - lastsys) * 10) / elapsed) * 100].map(v => Math.floor(v))
lastusr = usr;
lastsys = sys;
last_time = Date.now();
return res;
}
async function wrap_mem_usage() {
if (globalThis.Deno) {
if (Deno.build.os === "linux") {
const mem = () => memory_usage(Deno.readFileSync("/proc/self/stat"));
const cputime = () => cpu_usage(Deno.readFileSync("/proc/self/stat"));
cputime();
return { mem, cputime };
}
const mem = () => Deno.memoryUsage().rss;
const _SC_CLK_TCK = 3;
const api = Deno.dlopen("libc.dylib", {
sysconf: { parameters: ["i32"], result: "i32" },
times: { parameters: ["buffer"], result: "i32" },
}).symbols;
const { sysconf, times } = api;
const clock_ticks_per_second = sysconf(_SC_CLK_TCK);
const last = new Int32Array(5);
const current = new Int32Array(6);
current[5] = clock_ticks_per_second;
const time32 = new Uint32Array(9);
const _cputime = () => {
time32[4] = times(time32);
for (let i = 0; i < 5; i++) {
current[i] = time32[i] - last[i];
last[i] = time32[i];
}
return current;
};
_cputime();
return {
mem,
cputime: () => {
const time = _cputime();
const usr = time[0] / (time[4] / time[5]);
const sys = time[2] / (time[4] / time[5]);
return [usr, sys];
},
};
}
if (globalThis.process && !globalThis.lo) {
const os = await import("os");
if (os.platform() === "linux") {
const fs = await import("fs");
const mem = () => memory_usage(fs.readFileSync("/proc/self/stat"));
const cputime = () => cpu_usage(fs.readFileSync("/proc/self/stat"));
cputime();
return { mem, cputime };
}
let prev = process.cpuUsage();
let since = Date.now();
return {
mem: () => process.memoryUsage().rss,
cputime: () => {
const now = Date.now();
const elapsed_ms = now - since;
const cpu = process.cpuUsage();
const user = cpu.user - prev.user;
const system = cpu.system - prev.system;
prev = cpu;
const usr = (user / 1000 / elapsed_ms) * 100;
const sys = (system / 1000 / elapsed_ms) * 100;
since = Date.now();
return [usr, sys];
},
};
}
if (globalThis.lo) {
const proc = await import("lib/proc.js");
proc.cputime();
const cputime = () => {
const time = proc.cputime();
const usr = time[0] / (time[4] / time[5]);
const sys = time[2] / (time[4] / time[5]);
return [usr, sys];
};
return { mem: proc.mem, cputime };
}
}
function to_size_string(bytes) {
if (bytes < 1000) {
return `${bytes.toFixed(2).padStart(8, " ")} ${AY} Bps${AD}`;
} else if (bytes < 1000 * 1000) {
return `${(Math.floor((bytes / 1000) * 100) / 100).toFixed(2).padStart(8, " ")} ${AY}KBps${AD}`;
} else if (bytes < 1000 * 1000 * 1000) {
return `${(Math.floor((bytes / (1000 * 1000)) * 100) / 100).toFixed(2).padStart(8, " ")} ${AY}MBps${AD}`;
}
return `${(Math.floor((bytes / (1000 * 1000 * 1000)) * 100) / 100).toFixed(2).padStart(8, " ")} ${AY}GBps${AD}`;
}
function formatNanos(nanos) {
if (nanos >= 1000000000) return `${AY}sec/iter${AD} ${pad(nanos / 1000000000, 10, 2)}`;
if (nanos >= 1000000) return `${AY}ms/iter${AD} ${pad(nanos / 1000000, 10, 2)}`;
if (nanos >= 1000) return `${AY}μs/iter${AD} ${pad(nanos / 1000, 10, 2)}`;
return `${AY}ns/iter${AD} ${pad(nanos, 10, 2)}`;
}
function bench(name, fn, count, after = noop) {
const start = performance.now();
for (let i = 0; i < count; i++) fn();
const elapsed = performance.now() - start;
const rate = Math.floor(count / (elapsed / 1000));
const nanos = 1000000000 / rate;
const rss = mem();
console.log(
`${name.slice(0, 32).padEnd(17, " ")} ${pad(Math.floor(elapsed), 6)} ms ${AG}rate${AD} ${pad(rate, 10)} ${formatNanos(nanos)} ${AG}rss${AD} ${rss}`,
);
after();
return { name, count, elapsed, rate, nanos, rss, runtime };
}
async function benchAsync(name, fn, count, after = noop) {
const start = performance.now();
for (let i = 0; i < count; i++) await fn();
const elapsed = performance.now() - start;
const rate = Math.floor((count / (elapsed / 1000)) * 100) / 100;
const nanos = 1000000000 / rate;
const rss = mem();
console.log(
`${name.slice(0, 32).padEnd(17, " ")} ${pad(Math.floor(elapsed), 6)} ms ${AG}rate${AD} ${pad(rate, 10)} ${formatNanos(nanos)} ${AG}rss${AD} ${rss}`,
);
after();
return { name, count, elapsed, rate, nanos, rss, runtime };
}
const runAsync = async (name, fn, count, repeat = 10, after = () => {}) => {
const runs = [];
for (let i = 0; i < repeat; i++) {
runs.push(await benchAsync(name, fn, count, after));
}
return runs;
};
const run = (name, fn, count, repeat = 10, after = () => {}) => {
const runs = [];
for (let i = 0; i < repeat; i++) {
runs.push(bench(name, fn, count, after));
}
return runs;
};
function arrayEquals(a, b) {
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((val, index) => val === b[index]);
}
class Bench {
#start = 0;
#end = 0;
#name = "bench";
#display = true;
#name_width = 20;
#runtime = "";
constructor(display = true) {
this.#display = display;
this.#runtime = `${runtime.name}_${runtime.version}`
}
set name_width(len) {
this.#name_width = len;
}
start(name = "bench") {
this.#name = name.slice(0, 32).padEnd(32, " ");
this.#start = performance.now();
}
end(count = 0, size = 0) {
this.#end = performance.now();
const elapsed = this.#end - this.#start;
const nanos = Math.floor(elapsed * 1000000);
const seconds = nanos / 1000000000;
let rate = count / seconds;
const rss = mem();
const [usr, sys] = cputime();
const total = usr + sys;
const rate_pc_f = rate / (total / 100);
const rate_pc = rate_pc_f > 100 ? Math.ceil(rate_pc_f) : Math.ceil(rate_pc_f * 100) / 100;
const ns_iter = Math.floor((nanos / count) * 100) / 100;
rate = rate > 100 ? Math.ceil(rate) : Math.ceil(rate * 100) / 100;
if (this.#display) {
if (size) {
console.log(
`${AC}${this.#runtime.padEnd(16, " ")}${AD} ${AM}${this.#name.trim().padEnd(this.#name_width, " ")}${AD} ${AY}time${AD} ${Math.floor(elapsed).toString().padStart(8, " ")} ${AY}rate${AD} ${rate.toString().padStart(12, " ")} ${AM}rate/core${AD} ${rate_pc.toString().padStart(12, " ")} ${AG}ns/iter${AD} ${ns_iter.toFixed(2).padStart(12, " ")} ${AG}rss${AD} ${rss.toString().padStart(12, " ")} ${AG}usr${AD} ${usr.toFixed(2).padStart(6, " ")} ${AR}sys${AD} ${sys.toFixed(2).padStart(6, " ")} ${AY}tot${AD} ${total.toFixed(2).padStart(6, " ")} ${AG}thru${AD} ${to_size_string(rate_pc * size).padStart(12, " ")}`,
);
} else {
console.log(
`${AC}${this.#runtime.padEnd(16, " ")}${AD} ${AM}${this.#name.trim().padEnd(this.#name_width, " ")}${AD} ${AY}time${AD} ${Math.floor(elapsed).toString().padStart(8, " ")} ${AY}rate${AD} ${rate.toString().padStart(12, " ")} ${AM}rate/core${AD} ${rate_pc.toString().padStart(12, " ")} ${AG}ns/iter${AD} ${ns_iter.toFixed(2).padStart(12, " ")} ${AG}rss${AD} ${rss.toString().padStart(12, " ")} ${AG}usr${AD} ${usr.toFixed(2).padStart(6, " ")} ${AR}sys${AD} ${sys.toFixed(2).padStart(6, " ")} ${AY}tot${AD} ${total.toFixed(2).padStart(6, " ")}`,
);
}
}
return { name: this.#name.trim(), count, elapsed, rate, nanos, rss, runtime, usr, sys, rate_pc, ns_iter, seconds };
}
}
const runtime = { name: "", version: "" };
if (globalThis.Deno) {
globalThis.args = Deno.args;
runtime.name = "deno";
runtime.version = Deno.version.deno;
runtime.v8 = Deno.version.v8;
globalThis.readFileAsText = async fn => decoder.decode(Deno.readFileSync(fn));
globalThis.readFileAsBytes = async fn => Deno.readFileSync(fn);
globalThis.writeFileAsText = async (fn, str) => Deno.writeFileSync(fn, encoder.encode(str));
globalThis.writeFileAsBytes = async (fn, u8) => Deno.writeFileSync(fn, u8);
const fs = await import("node:fs");
globalThis.openSync = fs.openSync;
globalThis.readSync = fs.readSync;
globalThis.closeSync = fs.closeSync;
globalThis.readFileSync = fs.readFileSync;
globalThis.process = await import('node:process')
const { Buffer } = await import('node:buffer')
globalThis.Buffer = Buffer
} else if (globalThis.lo) {
globalThis.performance = { now: () => lo.hrtime() / 1000000 };
globalThis.assert = lo.assert;
globalThis.args = lo.args.slice(2);
runtime.name = "lo";
runtime.version = lo.version.lo;
runtime.v8 = lo.version.v8;
const { readFile, writeFile } = lo.core;
const { close, open, read, O_RDONLY } = lo.core;
globalThis.readFileAsText = async fn => decoder.decode(readFile(fn));
globalThis.readFileAsBytes = async fn => readFile(fn);
globalThis.writeFileAsText = async (fn, str) => writeFile(fn, encoder.encode(str));
globalThis.writeFileAsBytes = async (fn, u8) => writeFile(fn, u8);
globalThis.openSync = file_name => open(file_name, O_RDONLY);
globalThis.readSync = (fd, buf) => read(fd, buf, buf.length);
globalThis.closeSync = fd => close(fd);
globalThis.readFileSync = readFile;
globalThis.process = { argv: lo.args }
} else if (globalThis.Bun) {
globalThis.args = Bun.argv.slice(2);
runtime.name = "bun";
runtime.version = Bun.version;
globalThis.readFileAsText = async fn => await Bun.file(fn).text();
globalThis.readFileAsBytes = async fn => await Bun.file(fn).bytes();
globalThis.writeFileAsText = async (fn, str) => Bun.write(fn, str);
globalThis.writeFileAsBytes = async (fn, u8) => Bun.write(fn, u8);
const fs = await import("node:fs");
globalThis.openSync = fs.openSync;
globalThis.readSync = fs.readSync;
globalThis.closeSync = fs.closeSync;
globalThis.readFileSync = fs.readFileSync;
} else if (globalThis.process) {
globalThis.args = process.argv.slice(2);
runtime.name = "node";
runtime.version = process.version;
runtime.v8 = process.versions.v8;
const fs = await import("fs");
globalThis.readFileAsText = async fn => decoder.decode(fs.readFileSync(fn));
globalThis.readFileAsBytes = async fn => fs.readFileSync(fn);
globalThis.writeFileAsText = async (fn, str) => fs.writeFileSync(fn, encoder.encode(str));
globalThis.writeFileAsBytes = async (fn, u8) => fs.writeFileSync(fn, u8);
globalThis.openSync = fs.openSync;
globalThis.readSync = fs.readSync;
globalThis.closeSync = fs.closeSync;
globalThis.readFileSync = fs.readFileSync;
}
globalThis.colors = colors;
globalThis.arrayEquals = arrayEquals;
const noop = () => {};
const { mem, cputime } = await wrap_mem_usage();
if (!globalThis.assert) {
function fix_stack (err) {
err.stack = err.stack.split('\n')
.filter(line => !line.match(/\s+at assert \(main\.js.+/))
.join('\n')
}
function assert (condition, message, ErrorType = Error) {
if (!condition) {
if (message && message.constructor.name === 'Function') {
const err = new ErrorType(message(condition))
fix_stack(err)
throw(err)
}
const err = new ErrorType(message || "Assertion failed")
fix_stack(err)
throw(err)
}
return condition
}
globalThis.assert = assert;
}
const measure = {
start: (name = 'bench') => {
cputime();
let start = performance.now();
function end (count) {
const now = performance.now()
const nanos = Math.floor((now - start) * 1000000);
const elapsed = nanos / 1000000;
const seconds = nanos / 1000000000;
let rate = count / seconds;
const rss = mem();
const [usr, sys] = cputime();
const total = usr + sys;
const rate_pc_f = rate / (total / 100);
const rate_pc = rate_pc_f > 100 ? Math.ceil(rate_pc_f) : Math.ceil(rate_pc_f * 100) / 100;
const ns_iter = Math.floor((nanos / count) * 100) / 100;
rate = rate > 100 ? Math.ceil(rate) : Math.ceil(rate * 100) / 100;
start = now
return { rss, usr, sys, total, elapsed, rate, rate_pc, ns_iter }
}
function log (count, size = 0) {
const { rss, usr, sys, total, elapsed, rate, rate_pc, ns_iter } = end(count)
if (size) {
console.log(`${AG}${runtime.name.padEnd(10, ' ')}${AD} ${AM}${name.slice(0, 24).padEnd(20, ' ')}${AD} ${AY}${size.toString().padStart(8, ' ')}${AD} ${AY}time${AD} ${Math.floor(elapsed).toString().padStart(8, " ")} ${AY}rate${AD} ${rate.toString().padStart(12, " ")} ${AM}rate/core${AD} ${rate_pc.toString().padStart(12, " ")} ${AG}ns/iter${AD} ${ns_iter.toFixed(2).padStart(12, " ")} ${AG}rss${AD} ${rss.toString().padStart(12, " ")} ${AG}usr${AD} ${usr.toFixed(2).padStart(6, " ")} ${AR}sys${AD} ${sys.toFixed(2).padStart(6, " ")} ${AY}tot${AD} ${total.toFixed(2).padStart(6, " ")} ${AG}thru${AD} ${to_size_string(rate_pc * size).padStart(12, " ")}`,)
} else {
console.log(`${AG}${runtime.name.padEnd(10, ' ')}${AD} ${AM}${name.slice(0, 24).padEnd(20, ' ')}${AD} ${AY}${size.toString().padStart(8, ' ')}${AD} ${AY}time${AD} ${Math.floor(elapsed).toString().padStart(8, " ")} ${AY}rate${AD} ${rate.toString().padStart(12, " ")} ${AM}rate/core${AD} ${rate_pc.toString().padStart(12, " ")} ${AG}ns/iter${AD} ${ns_iter.toFixed(2).padStart(12, " ")} ${AG}rss${AD} ${rss.toString().padStart(12, " ")} ${AG}usr${AD} ${usr.toFixed(2).padStart(6, " ")} ${AR}sys${AD} ${sys.toFixed(2).padStart(6, " ")} ${AY}tot${AD} ${total.toFixed(2).padStart(6, " ")}`,)
}
}
return { end, log }
}
};
export {
pad,
formatNanos,
colors,
run,
runAsync,
Bench,
mem,
runtime,
to_size_string,
Stats,
cputime,
measure,
is_a_tty,
cpu_usage,
memory_usage,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment