Skip to content

Conversation

@Torathion
Copy link

High, I just found your package and wanted to contribute to it to make it even faster. I only did two things:

  • Use optional chaining (?.) when possible to reduce bundle size
  • Optimize loop end condition by outsourcing array length to own variable.

I don't know if it's okay to suggest using optional chaining, because you haven't specified a minimum required nodejs engine version in your package.json. Optional chaining has been introduced in NodeJS 14 which came out 5 years ago. I think, it's okay to support it, because supporting anything below that would be unreasonable.

Why is it important to outsource array lengths into a variable?

When accessing an object property like object.property, the underlying JS engine (NodeJS uses v8), does a quick memory lookup into the heap to get the value of said property. This can decrease performance by quite a bit depending on the number of of object property accesses performed. Since a loop head checks the end condition on every iteration, it will do as many memory lookups of array.length as there are iterations. Additionally, I found a loop end condition of < array.length - 1 and this will always recalculate the array length + doing a memory lookup.

Other benefits of outsourcing object properties to variables.

The other main benefit of outsourcing properties to local variables is the reduction of the bundle size. Unlike other languages, JS is interpreted and can't be converted to bytecode. Many bundlers, most of them today are esbuild based, have no option to mangle and minify object property names. That means, if I have a property object.superDuperMegaLongDescriptiveParagraphOfAnAwesomePropertyName, it will retain the name, bloating the bundle and output size of apps. While outsourcing is amazing to reduce bundle size, there is always the caveat of extra variables having to be cleaned up via the GC, so there has to be a balance.

My recommendation for the future of this project would be to slightly reduce of calling properties through this. and rather using local variables to further reduce the bundle size. Currently, it sits at a quite reasonable bundle size of 5.1KB as seen on bundlephobia, but I'm sure it can get a bit smaller.

@mafintosh
Copy link
Owner

Hi, thanks. Do you have a benchmark that shows the impact?

@Torathion
Copy link
Author

Okay, I might be close to another revelation about performance in JS as I think I'm misunderstanding object property accesses. For a very long time, I thought the difference was a bit bigger, but it's just maybe 2% oe 3% at best. Here is the js bench suite: https://jsben.ch/lFZ3Y . You'd need to run it a few times as the results can differ a lot.

I've tested it locally as well:

const array = new Array(1e7)
const len = array.length
console.time('property')
for (let i = 0; i < array.length; i++) 0
console.timeEnd('property')

console.time('variable')
for (let i = 0; i < len; i++) 0
console.timeEnd('variable')

And it was also mostly the same, with the variable one dipping two or three percentages lower in time than the object property test on some test runs. I guess, it's more important to reduce calculations and variables than outsourcing them. I'm really sorry I'm unable to test properly to definitely proof this micro optimization is better.

@Torathion Torathion closed this Nov 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants