Skip to content

Instantly share code, notes, and snippets.

@svidgen
Last active November 18, 2024 22:46
Show Gist options
  • Select an option

  • Save svidgen/fc49f10e76daa9afc39804e5a07caed8 to your computer and use it in GitHub Desktop.

Select an option

Save svidgen/fc49f10e76daa9afc39804e5a07caed8 to your computer and use it in GitHub Desktop.
JavaScript/TypeScript loop performance
/**
* Incorrect example from https://x.com/BenjDicken/status/1857449788893286484
*/
function incorrect(baseLoopSize: number) {
const array = new Array(baseLoopSize);
const innerLoopSize = baseLoopSize * 10;
for (let i = 0; i < baseLoopSize; i++) {
for (let j = 0; j < innerLoopSize; j++) {
array[i] = array[i] + j;
}
}
return array;
}
/**
* Corrected to perform math against `Number` types instead of `NaN`
*/
function corrected(baseLoopSize: number) {
const array = new Array(baseLoopSize).fill(0);
const innerLoopSize = baseLoopSize * 10;
for (let i = 0; i < baseLoopSize; i++) {
for (let j = 0; j < innerLoopSize; j++) {
array[i] = array[i] + j;
}
}
return array;
}
/**
* Optimized to leverage `Uint32` math.
*/
function uInts(baseLoopSize: number) {
const i = new Uint32Array([0, 0]);
const array = new Uint32Array(baseLoopSize).fill(0);
const innerLoopSize = baseLoopSize * 10;
for (; i[0] < baseLoopSize; i[0]++) {
for (; i[1] < innerLoopSize; i[1]++) {
array[i[0]] = array[i[0]] + i[1];
}
}
return array;
}
function benchmark<T>(f: () => T): { time: number, result: T } {
const start = new Date();
const result = f();
const end = new Date();
return {
time: end.getTime() - start.getTime(),
result
}
}
const BASE_LOOP_SIZE = 2000;
console.clear();
const { time: incorrectTime, result: [ resultIncorrect ] } = benchmark(() => incorrect(BASE_LOOP_SIZE));
const { time: correctedTime, result: [ resultCorrected ] } = benchmark(() => corrected(BASE_LOOP_SIZE));
const { time: uIntTime, result: [ resultUInt ] } = benchmark(() => uInts(BASE_LOOP_SIZE));
console.log({
incorrectTime,
correctedTime,
uIntTime,
resultIncorrect,
resultCorrected,
resultUInt
})
/** Outputs:
{
"incorrectTime": 147,
"correctedTime": 96,
"uIntTime": 1,
"resultIncorrect": null,
"resultCorrected": 199990000,
"resultUInt": 199990000
}
*/
@svidgen

svidgen commented Nov 18, 2024

Copy link
Copy Markdown
Author

Updated playground shows that the biggest savings actually comes from forcing the loops to use UInt32.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment