Skip to content

Instantly share code, notes, and snippets.

@KevLehman
Created November 25, 2025 16:11
Show Gist options
  • Select an option

  • Save KevLehman/843643c446d0b0875aec33e78f54e295 to your computer and use it in GitHub Desktop.

Select an option

Save KevLehman/843643c446d0b0875aec33e78f54e295 to your computer and use it in GitHub Desktop.
/* eslint-disable no-console */
const ARRAY_SIZE = parseInt(process.env.ARRAY_SIZE || "2_000_000", 10);
const WARMUP_RUNS = 1;
const MEASURE_RUNS = 3;
function formatBytes(bytes) {
if (bytes < 1024) return `${bytes} B`;
const units = ["KB", "MB", "GB", "TB"];
let i = -1;
let value = bytes;
do {
value /= 1024;
i += 1;
} while (value >= 1024 && i < units.length - 1);
return `${value.toFixed(2)} ${units[i]}`;
}
function snapMemory(label) {
const mu = process.memoryUsage();
return {
label,
rss: mu.rss,
heapUsed: mu.heapUsed,
heapTotal: mu.heapTotal,
};
}
function diffMemory(before, after) {
return {
rss: after.rss - before.rss,
heapUsed: after.heapUsed - before.heapUsed,
heapTotal: after.heapTotal - before.heapTotal,
};
}
function printMemSnapshot(title, snap) {
console.log(`\n${title}`);
console.log(` rss: ${formatBytes(snap.rss)}`);
console.log(` heapUsed: ${formatBytes(snap.heapUsed)}`);
console.log(` heapTotal: ${formatBytes(snap.heapTotal)}`);
}
function printMemDiff(title, diff) {
console.log(`\n${title}`);
console.log(` Δ rss: ${formatBytes(diff.rss)}`);
console.log(` Δ heapUsed: ${formatBytes(diff.heapUsed)}`);
console.log(` Δ heapTotal: ${formatBytes(diff.heapTotal)}`);
}
class Counter {
constructor(start = 0) {
this.value = start;
}
step() {
this.value += 1;
return this.value;
}
}
const counter = new Counter();
const getNum = () => counter.step();
const halve = (x) => x / 2;
const isInt = (x) => Math.floor(x) === x;
function loopClassicFor(source) {
const len = source.length;
const out = new Array(len);
for (let i = 0; i < len; i += 1) {
const n = getNum();
const h = halve(n);
out[i] = isInt(h);
}
return out;
}
/**
* 2) for..of loop
*/
function loopForOf(source) {
const out = new Array(source.length);
let i = 0;
for (const _ of source) {
const n = getNum();
const h = halve(n);
out[i] = isInt(h);
i += 1;
}
return out;
}
/**
* 3) Array.prototype.map chain using map().map().filter()
*/
function loopMap(source) {
return source
.map(() => getNum())
.map((n) => halve(n))
.filter((h) => isInt(h));
}
/**
* 4) Array.prototype.reduce to new array
*/
function loopReduce(source) {
return source.reduce((acc) => {
const n = getNum();
const h = halve(n);
acc.push(isInt(h));
return acc;
}, []);
}
// Add more implementations here if needed
const LOOP_VARIANTS = [
{ name: "classic for (i++)", fn: loopClassicFor },
{ name: "for...of", fn: loopForOf },
{ name: "Array.map", fn: loopMap },
{ name: "Array.reduce", fn: loopReduce },
];
// ---------------------- Runner --------------------------
async function runVariant(variant, source) {
console.log(`\n=== Variant: ${variant.name} ===`);
// Warmup (not measured)
for (let i = 0; i < WARMUP_RUNS; i += 1) {
// eslint-disable-next-line no-unused-vars
const _warm = variant.fn(source);
}
const before = snapMemory("before");
const tStart = process.hrtime.bigint();
let lastResult = null;
for (let i = 0; i < MEASURE_RUNS; i += 1) {
lastResult = variant.fn(source);
}
const tEnd = process.hrtime.bigint();
const after = snapMemory("after");
const diff = diffMemory(before, after);
const durationMs = Number(tEnd - tStart) / 1e6;
printMemDiff("Memory delta (over all measured runs)", diff);
console.log(`\nTime over ${MEASURE_RUNS} runs: ${durationMs.toFixed(2)} ms`);
console.log(`Avg per run: ${(durationMs / MEASURE_RUNS).toFixed(2)} ms`);
// Small sanity check to ensure the work is actually done:
const trueCount = lastResult.filter(Boolean).length;
console.log(`Result sanity: last run produced ${trueCount} "true" values`);
}
async function main() {
console.log("=== Array loop memory footprint benchmark ===");
console.log(`ARRAY_SIZE = ${ARRAY_SIZE.toLocaleString("en-US")}`);
console.log(`WARMUP_RUNS = ${WARMUP_RUNS}`);
console.log(`MEASURE_RUNS = ${MEASURE_RUNS}`);
// Build a big array whose values we ignore; we only care about length
const baseArray = new Array(ARRAY_SIZE).fill(0);
printMemSnapshot("Initial memory snapshot", snapMemory("initial"));
for (const variant of LOOP_VARIANTS) {
await runVariant(variant, baseArray);
await tryGC();
}
printMemSnapshot("\nFinal memory snapshot", snapMemory("final"));
}
// Run if executed directly
if (require.main === module) {
main().catch((err) => {
console.error("Benchmark failed:", err);
process.exitCode = 1;
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment