Skip to content

Instantly share code, notes, and snippets.

@episage
Forked from DungGramer/fastest_for.js
Last active August 26, 2024 15:36
Show Gist options
  • Save episage/076ded007d0583f6a275f93a8c9c8047 to your computer and use it in GitHub Desktop.
Save episage/076ded007d0583f6a275f93a8c9c8047 to your computer and use it in GitHub Desktop.
Find fastest way to loop through an array in Javascript
const { performance } = require('perf_hooks');
const assert = require('assert');
const DURATION_COLUMN = 'time[ns]';
// Create 1000 random numbers
const createTestArray = length => Array.from({ length }, () => 1 + Math.floor(Math.random() * 1000));
const createReferenceArray = testArray => testArray.map(v => Math.ceil((v + 2) / 10));
const sumUp = array => array.reduce((sum, value) => sum + value, 0);
const computeBenchmark = v => Math.ceil((v + 2) / 10);
function record(testArray) {
console.log(`Benchmarking [${testArray.length}] element array...`);
const referenceSum = sumUp(createReferenceArray(testArray));
const benchmarkResults = [];
function timeRun(callback, message) {
const start = performance.now();
const iterationResult = callback();
const end = performance.now();
const duration = Math.floor((end - start) * 1000 * 1000);
benchmarkResults.push({
type: message,
[DURATION_COLUMN]: duration,
});
const sum = sumUp(iterationResult);
assert.strictEqual(sum, referenceSum);
}
timeRun(() => {
const result = [];
for (let i = 0, length = testArray.length; i < length; i++) {
result.push(computeBenchmark(testArray[i]));
}
return result;
}, 'for ++');
timeRun(() => {
const result = [];
for (let i = 0, length = testArray.length; i < length; ++i) {
result.push(computeBenchmark(testArray[i]));
}
return result;
}, '++ for');
timeRun(() => {
const result = [];
for (let i = 0, length = testArray.length; i !== length; i++) {
result.push(computeBenchmark(testArray[i]));
}
return result;
}, 'for !== ++');
timeRun(() => {
const result = [];
for (let i = 0, length = testArray.length; i !== length; ++i) {
result.push(computeBenchmark(testArray[i]));
}
return result;
}, '++ for !==');
timeRun(() => {
const result = [];
for (let length = testArray.length, i = length - 1; i >= 0; i--) {
result.push(computeBenchmark(testArray[i]));
}
return result;
}, 'for --');
timeRun(() => {
const result = [];
for (let length = testArray.length, i = length - 1; i >= 0; --i) {
result.push(computeBenchmark(testArray[i]));
}
return result;
}, '-- for');
timeRun(() => {
const result = [];
for (let i = testArray.length; i--;) {
result.push(computeBenchmark(testArray[i]));
}
return result;
}, 'for i length --');
timeRun(() => {
const result = [];
for (let i = testArray.length + 1; --i;) {
result.push(computeBenchmark(testArray[i - 1]));
}
return result;
}, '--for i length');
timeRun(() => {
const result = [];
testArray.map(v => {
result.push(computeBenchmark(v));
});
return result;
}, 'map');
timeRun(() => {
const result = [];
for (const v of testArray) {
result.push(computeBenchmark(v));
}
return result;
}, 'for of');
timeRun(() => {
const result = [];
testArray.flatMap(v => {
result.push(computeBenchmark(v));
return [v];
});
return result;
}, 'flatMap');
timeRun(() => {
const result = [];
for (const i in testArray) {
result.push(computeBenchmark(testArray[i]));
Object.prototype.hasOwnProperty.call(testArray, i);
}
return result;
}, 'for in');
timeRun(() => {
const result = [];
testArray.forEach(v => {
result.push(computeBenchmark(v));
});
return result;
}, 'forEach');
timeRun(() => {
const result = [];
[].forEach.call(testArray, v => {
result.push(computeBenchmark(v));
});
return result;
}, 'forEach call');
timeRun(() => {
const result = [];
Array.from(testArray, v => {
result.push(computeBenchmark(v));
});
return result;
}, 'Array from');
timeRun(() => {
const result = [];
Object.keys(testArray).map(i => {
result.push(computeBenchmark(testArray[i]));
});
return result;
}, 'Object.keys map');
timeRun(() => {
const result = [];
let i = 0;
let length = testArray.length;
while (i = length--) {
result.push(computeBenchmark(testArray[i - 1]));
}
return result;
}, 'while forward --');
timeRun(() => {
const result = [];
let i = 0;
let length = testArray.length;
while (i = --length) {
result.push(computeBenchmark(testArray[i]));
}
result.push(computeBenchmark(testArray[i]));
return result;
}, '--while forward');
timeRun(() => {
const result = [];
let i = 0;
let length = testArray.length;
do {
i = length--;
result.push(computeBenchmark(testArray[i - 1]));
} while (length);
return result;
}, 'do while forward --');
timeRun(() => {
const result = [];
let i = 0;
let length = testArray.length;
do {
result.push(computeBenchmark(testArray[i]));
i = --length;
} while (length);
return result;
}, '--do while forward');
timeRun(() => {
const result = [];
let i = 0;
while (i < testArray.length) {
result.push(computeBenchmark(testArray[i]));
i++;
}
return result;
}, 'while ++');
timeRun(() => {
const result = [];
let i = 0;
while (i < testArray.length) {
result.push(computeBenchmark(testArray[i]));
++i;
}
return result;
}, '++ while');
timeRun(() => {
const result = [];
let i = 0;
do {
result.push(computeBenchmark(testArray[i]));
i++;
} while (i < testArray.length);
return result;
}, 'do while ++');
timeRun(() => {
const result = [];
let i = 0;
do {
result.push(computeBenchmark(testArray[i]));
++i;
} while (i < testArray.length);
return result;
}, '++ do while');
timeRun(() => {
const result = [];
let i = testArray.length;
while (--i >= 0) {
result.push(computeBenchmark(testArray[i]));
}
return result;
}, '--while >= 0');
// warning: this benchmark is very slow
// timeRun(() => {
// const result = [];
// let v;
// const arrClone = [...testArray];
// /* warning: test array must not contain zero */
// while (v = arrClone.shift()) {
// result.push(computeBenchmark(v));
// }
// return result;
// }, 'while shift');
const arrClone = [...testArray];
timeRun(() => {
const result = [];
for (let v; (v = arrClone.pop());) {
result.push(computeBenchmark(v));
}
return result;
}, 'pop');
benchmarkResults.sort((a, b) => a[DURATION_COLUMN] - b[DURATION_COLUMN]);
const baseline = benchmarkResults[0][DURATION_COLUMN];
benchmarkResults.forEach(r => {
r.baseline = parseFloat((r[DURATION_COLUMN] / baseline).toFixed(2));
});
console.log(`The fastest [${benchmarkResults[0].type}] took [${benchmarkResults[0][DURATION_COLUMN]}ns]`);
console.table(benchmarkResults);
console.log();
}
record(createTestArray(100));
record(createTestArray(1000));
record(createTestArray(10_000));
record(createTestArray(100_000));
record(createTestArray(1_000_000));
record(createTestArray(10_000_000));
Benchmarking [100] element array...
The fastest [++ while] took [18625ns]
┌─────────┬───────────────────────┬──────────┬──────────┐
│ (index) │ type │ time[ns] │ baseline │
├─────────┼───────────────────────┼──────────┼──────────┤
│ 0 │ '++ while' │ 18625 │ 1 │
│ 1 │ '--while >= 0' │ 18915 │ 1.02 │
│ 2 │ 'do while ++' │ 19709 │ 1.06 │
│ 3 │ 'for i length --' │ 20291 │ 1.09 │
│ 4 │ '-- for' │ 20292 │ 1.09 │
│ 5 │ 'while ++' │ 20333 │ 1.09 │
│ 6 │ 'do while forward --' │ 20750 │ 1.11 │
│ 7 │ '--do while forward' │ 21165 │ 1.14 │
│ 8 │ 'for !== ++' │ 21332 │ 1.15 │
│ 9 │ '++ for !==' │ 21624 │ 1.16 │
│ 10 │ '--while forward' │ 21624 │ 1.16 │
│ 11 │ 'for --' │ 22375 │ 1.2 │
│ 12 │ 'forEach' │ 23792 │ 1.28 │
│ 13 │ '++ for' │ 23999 │ 1.29 │
│ 14 │ 'map' │ 25957 │ 1.39 │
│ 15 │ 'while forward --' │ 26709 │ 1.43 │
│ 16 │ 'Object.keys map' │ 29249 │ 1.57 │
│ 17 │ '--for i length' │ 30500 │ 1.64 │
│ 18 │ 'pop' │ 30833 │ 1.66 │
│ 19 │ 'Array from' │ 33166 │ 1.78 │
│ 20 │ 'for of' │ 33749 │ 1.81 │
│ 21 │ '++ do while' │ 38459 │ 2.06 │
│ 22 │ 'for in' │ 43499 │ 2.34 │
│ 23 │ 'flatMap' │ 61082 │ 3.28 │
│ 24 │ 'forEach call' │ 118541 │ 6.36 │
│ 25 │ 'for ++' │ 164665 │ 8.84 │
└─────────┴───────────────────────┴──────────┴──────────┘
Benchmarking [1000] element array...
The fastest [--do while forward] took [34749ns]
┌─────────┬───────────────────────┬──────────┬──────────┐
│ (index) │ type │ time[ns] │ baseline │
├─────────┼───────────────────────┼──────────┼──────────┤
│ 0 │ '--do while forward' │ 34749 │ 1 │
│ 1 │ '--while >= 0' │ 34832 │ 1 │
│ 2 │ '++ do while' │ 37666 │ 1.08 │
│ 3 │ 'do while ++' │ 37708 │ 1.09 │
│ 4 │ '++ while' │ 37833 │ 1.09 │
│ 5 │ 'while ++' │ 37916 │ 1.09 │
│ 6 │ 'pop' │ 41707 │ 1.2 │
│ 7 │ '++ for' │ 60292 │ 1.74 │
│ 8 │ '--while forward' │ 60416 │ 1.74 │
│ 9 │ 'for --' │ 61208 │ 1.76 │
│ 10 │ '--for i length' │ 61583 │ 1.77 │
│ 11 │ 'forEach' │ 61959 │ 1.78 │
│ 12 │ 'for !== ++' │ 63040 │ 1.81 │
│ 13 │ 'while forward --' │ 63416 │ 1.82 │
│ 14 │ '-- for' │ 63624 │ 1.83 │
│ 15 │ 'forEach call' │ 65292 │ 1.88 │
│ 16 │ 'map' │ 67666 │ 1.95 │
│ 17 │ 'for ++' │ 70708 │ 2.03 │
│ 18 │ '++ for !==' │ 73915 │ 2.13 │
│ 19 │ 'for of' │ 78332 │ 2.25 │
│ 20 │ 'Object.keys map' │ 84542 │ 2.43 │
│ 21 │ 'for in' │ 137583 │ 3.96 │
│ 22 │ 'Array from' │ 174124 │ 5.01 │
│ 23 │ 'flatMap' │ 234874 │ 6.76 │
│ 24 │ 'do while forward --' │ 297708 │ 8.57 │
│ 25 │ 'for i length --' │ 348999 │ 10.04 │
└─────────┴───────────────────────┴──────────┴──────────┘
Benchmarking [10000] element array...
The fastest [--while forward] took [282292ns]
┌─────────┬───────────────────────┬──────────┬──────────┐
│ (index) │ type │ time[ns] │ baseline │
├─────────┼───────────────────────┼──────────┼──────────┤
│ 0 │ '--while forward' │ 282292 │ 1 │
│ 1 │ 'forEach call' │ 338792 │ 1.2 │
│ 2 │ 'map' │ 359666 │ 1.27 │
│ 3 │ 'forEach' │ 424417 │ 1.5 │
│ 4 │ 'Object.keys map' │ 497000 │ 1.76 │
│ 5 │ 'Array from' │ 556208 │ 1.97 │
│ 6 │ '++ while' │ 904833 │ 3.21 │
│ 7 │ '--while >= 0' │ 906834 │ 3.21 │
│ 8 │ 'do while forward --' │ 975041 │ 3.45 │
│ 9 │ 'do while ++' │ 979249 │ 3.47 │
│ 10 │ '++ do while' │ 979250 │ 3.47 │
│ 11 │ 'for i length --' │ 1049666 │ 3.72 │
│ 12 │ '--do while forward' │ 1069957 │ 3.79 │
│ 13 │ 'while forward --' │ 1076249 │ 3.81 │
│ 14 │ '-- for' │ 1087292 │ 3.85 │
│ 15 │ 'while ++' │ 1113832 │ 3.95 │
│ 16 │ '--for i length' │ 1138500 │ 4.03 │
│ 17 │ 'for --' │ 1184916 │ 4.2 │
│ 18 │ 'for !== ++' │ 1186041 │ 4.2 │
│ 19 │ '++ for' │ 1211167 │ 4.29 │
│ 20 │ '++ for !==' │ 1276000 │ 4.52 │
│ 21 │ 'pop' │ 1374208 │ 4.87 │
│ 22 │ 'for of' │ 1374458 │ 4.87 │
│ 23 │ 'for ++' │ 1471458 │ 5.21 │
│ 24 │ 'flatMap' │ 1577583 │ 5.59 │
│ 25 │ 'for in' │ 2149333 │ 7.61 │
└─────────┴───────────────────────┴──────────┴──────────┘
Benchmarking [100000] element array...
The fastest [while ++] took [1222500ns]
┌─────────┬───────────────────────┬──────────┬──────────┐
│ (index) │ type │ time[ns] │ baseline │
├─────────┼───────────────────────┼──────────┼──────────┤
│ 0 │ 'while ++' │ 1222500 │ 1 │
│ 1 │ '--do while forward' │ 1257041 │ 1.03 │
│ 2 │ '++ while' │ 1276417 │ 1.04 │
│ 3 │ 'do while forward --' │ 1282749 │ 1.05 │
│ 4 │ '++ do while' │ 1289125 │ 1.05 │
│ 5 │ '--for i length' │ 1306707 │ 1.07 │
│ 6 │ 'for --' │ 1314458 │ 1.08 │
│ 7 │ 'do while ++' │ 1331832 │ 1.09 │
│ 8 │ 'while forward --' │ 1365584 │ 1.12 │
│ 9 │ '++ for !==' │ 1475708 │ 1.21 │
│ 10 │ 'for i length --' │ 1486041 │ 1.22 │
│ 11 │ '-- for' │ 1528416 │ 1.25 │
│ 12 │ '++ for' │ 1603416 │ 1.31 │
│ 13 │ 'pop' │ 1622375 │ 1.33 │
│ 14 │ '--while >= 0' │ 1662499 │ 1.36 │
│ 15 │ 'forEach call' │ 1692457 │ 1.38 │
│ 16 │ 'map' │ 1694999 │ 1.39 │
│ 17 │ 'for !== ++' │ 1714249 │ 1.4 │
│ 18 │ 'for of' │ 1728790 │ 1.41 │
│ 19 │ 'for ++' │ 1731832 │ 1.42 │
│ 20 │ 'forEach' │ 2495874 │ 2.04 │
│ 21 │ '--while forward' │ 2820000 │ 2.31 │
│ 22 │ 'Array from' │ 3138792 │ 2.57 │
│ 23 │ 'Object.keys map' │ 4254665 │ 3.48 │
│ 24 │ 'for in' │ 7819000 │ 6.4 │
│ 25 │ 'flatMap' │ 11796875 │ 9.65 │
└─────────┴───────────────────────┴──────────┴──────────┘
Benchmarking [1000000] element array...
The fastest [for ++] took [7869749ns]
┌─────────┬───────────────────────┬───────────┬──────────┐
│ (index) │ type │ time[ns] │ baseline │
├─────────┼───────────────────────┼───────────┼──────────┤
│ 0 │ 'for ++' │ 7869749 │ 1 │
│ 1 │ '--while >= 0' │ 8002958 │ 1.02 │
│ 2 │ '++ while' │ 8145208 │ 1.04 │
│ 3 │ 'while ++' │ 8258959 │ 1.05 │
│ 4 │ '--do while forward' │ 8265458 │ 1.05 │
│ 5 │ '--while forward' │ 8269958 │ 1.05 │
│ 6 │ 'for --' │ 8283666 │ 1.05 │
│ 7 │ '-- for' │ 8286583 │ 1.05 │
│ 8 │ 'do while forward --' │ 8308249 │ 1.06 │
│ 9 │ '++ for !==' │ 8392999 │ 1.07 │
│ 10 │ 'do while ++' │ 8539333 │ 1.09 │
│ 11 │ 'pop' │ 8614290 │ 1.09 │
│ 12 │ 'for i length --' │ 8735291 │ 1.11 │
│ 13 │ '++ for' │ 9813832 │ 1.25 │
│ 14 │ '--for i length' │ 11337000 │ 1.44 │
│ 15 │ 'for !== ++' │ 11456417 │ 1.46 │
│ 16 │ '++ do while' │ 12133708 │ 1.54 │
│ 17 │ 'while forward --' │ 13511167 │ 1.72 │
│ 18 │ 'forEach' │ 14522583 │ 1.85 │
│ 19 │ 'for of' │ 16070708 │ 2.04 │
│ 20 │ 'map' │ 17058082 │ 2.17 │
│ 21 │ 'forEach call' │ 20377459 │ 2.59 │
│ 22 │ 'Array from' │ 29647792 │ 3.77 │
│ 23 │ 'Object.keys map' │ 80981415 │ 10.29 │
│ 24 │ 'for in' │ 84645334 │ 10.76 │
│ 25 │ 'flatMap' │ 123533874 │ 15.7 │
└─────────┴───────────────────────┴───────────┴──────────┘
Benchmarking [10000000] element array...
The fastest [for ++] took [76762166ns]
┌─────────┬───────────────────────┬────────────┬──────────┐
│ (index) │ type │ time[ns] │ baseline │
├─────────┼───────────────────────┼────────────┼──────────┤
│ 0 │ 'for ++' │ 76762166 │ 1 │
│ 1 │ 'for of' │ 82407583 │ 1.07 │
│ 2 │ '--while forward' │ 83723083 │ 1.09 │
│ 3 │ 'do while forward --' │ 83942958 │ 1.09 │
│ 4 │ '--do while forward' │ 84225584 │ 1.1 │
│ 5 │ 'while forward --' │ 85156957 │ 1.11 │
│ 6 │ '--while >= 0' │ 89745916 │ 1.17 │
│ 7 │ '++ do while' │ 90306542 │ 1.18 │
│ 8 │ 'for !== ++' │ 90319083 │ 1.18 │
│ 9 │ '-- for' │ 90360167 │ 1.18 │
│ 10 │ 'for i length --' │ 90558833 │ 1.18 │
│ 11 │ '++ for' │ 90616125 │ 1.18 │
│ 12 │ 'do while ++' │ 90657541 │ 1.18 │
│ 13 │ '--for i length' │ 90757708 │ 1.18 │
│ 14 │ 'for --' │ 90799875 │ 1.18 │
│ 15 │ '++ while' │ 92697417 │ 1.21 │
│ 16 │ '++ for !==' │ 94488209 │ 1.23 │
│ 17 │ 'pop' │ 108399917 │ 1.41 │
│ 18 │ 'while ++' │ 109276500 │ 1.42 │
│ 19 │ 'forEach call' │ 147140124 │ 1.92 │
│ 20 │ 'forEach' │ 148886207 │ 1.94 │
│ 21 │ 'map' │ 207100583 │ 2.7 │
│ 22 │ 'Array from' │ 353166207 │ 4.6 │
│ 23 │ 'flatMap' │ 1213152082 │ 15.8 │
│ 24 │ 'Object.keys map' │ 1294475333 │ 16.86 │
│ 25 │ 'for in' │ 1338988749 │ 17.44 │
└─────────┴───────────────────────┴────────────┴──────────┘
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment