Skip to content

Instantly share code, notes, and snippets.

@mertcanaltin
Created November 2, 2025 13:09
Show Gist options
  • Save mertcanaltin/a8aa09ffee910803227422190fbe65f4 to your computer and use it in GitHub Desktop.
Save mertcanaltin/a8aa09ffee910803227422190fbe65f4 to your computer and use it in GitHub Desktop.
nodejs bench for Buffer.copy
// 100 chunks × 4KB streaming test
const { performance } = require('perf_hooks');
// Prepare test data: 100 chunks of 4KB each
const numChunks = 100;
const chunkSize = 4096; // 4KB
const chunks = [];
for (let i = 0; i < numChunks; i++) {
const chunk = Buffer.allocUnsafe(chunkSize);
// Fill with some data
for (let j = 0; j < chunkSize; j++) {
chunk[j] = (i + j) % 256;
}
chunks.push(chunk);
}
console.log(`Test data: ${numChunks} chunks × ${chunkSize} bytes = ${numChunks * chunkSize} bytes\n`);
// Warmup
for (let i = 0; i < 100; i++) {
const result = Buffer.allocUnsafe(numChunks * chunkSize);
let offset = 0;
for (const chunk of chunks) {
chunk.copy(result, offset);
offset += chunk.length;
}
}
// Test 1: Buffer.copy()
console.log('Test 1: Buffer.copy()');
const iterations = 100;
let totalTime = 0;
for (let iter = 0; iter < iterations; iter++) {
const result = Buffer.allocUnsafe(numChunks * chunkSize);
let offset = 0;
const start = performance.now();
for (const chunk of chunks) {
chunk.copy(result, offset);
offset += chunk.length;
}
const end = performance.now();
totalTime += (end - start);
}
const avgTime = totalTime / iterations;
const perChunkTime = avgTime / numChunks;
const throughputMBs = (numChunks * chunkSize / 1024 / 1024) / (avgTime / 1000);
console.log(` Average time: ${avgTime.toFixed(4)}ms`);
console.log(` Per-chunk: ${(perChunkTime * 1000).toFixed(2)}μs`);
console.log(` Throughput: ${throughputMBs.toFixed(2)} MB/s`);
// Test 2: TypedArray.set() for comparison
console.log('\n Test 2: TypedArray.set() (baseline)');
totalTime = 0;
for (let iter = 0; iter < iterations; iter++) {
const result = Buffer.allocUnsafe(numChunks * chunkSize);
let offset = 0;
const start = performance.now();
for (const chunk of chunks) {
result.set(chunk, offset);
offset += chunk.length;
}
const end = performance.now();
totalTime += (end - start);
}
const avgTimeSet = totalTime / iterations;
const perChunkTimeSet = avgTimeSet / numChunks;
const throughputSetMBs = (numChunks * chunkSize / 1024 / 1024) / (avgTimeSet / 1000);
console.log(`Average time: ${avgTimeSet.toFixed(4)}ms`);
console.log(`Per-chunk: ${(perChunkTimeSet * 1000).toFixed(2)}μs`);
console.log(`Throughput: ${throughputSetMBs.toFixed(2)} MB/s`);
// Comparison
console.log('\n Comparison:');
const speedup = avgTime / avgTimeSet;
const overhead = ((avgTime - avgTimeSet) / avgTimeSet * 100);
console.log(`Buffer.copy() is ${speedup.toFixed(2)}x slower than TypedArray.set()`);
console.log(`Overhead: ${overhead.toFixed(1)}%`);
// Correctness check
console.log('\n Correctness check:');
const testResult = Buffer.allocUnsafe(numChunks * chunkSize);
let offset = 0;
for (const chunk of chunks) {
chunk.copy(testResult, offset);
offset += chunk.length;
}
let correct = true;
for (let i = 0; i < numChunks; i++) {
const chunkOffset = i * chunkSize;
for (let j = 0; j < chunkSize; j++) {
const expected = (i + j) % 256;
if (testResult[chunkOffset + j] !== expected) {
correct = false;
break;
}
}
if (!correct) break;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment