Search code examples
javascriptv8

Why is nulling a value faster than undefining it (javascript v8)


Heyho tested a bit around with maps vs objects in Javascript and found out that nulling is much faster (2,5 times) than putting the value to undefined or compared to simply delete the property

https://www.measurethat.net/Benchmarks/Show/15592/0/compare-nulling-undefining-and-deleting-of-javascript-o

If you are wondering why i allways create the map and or the javascript Object i did it so that every test has the same "overhead".

EDIT: also got this one which got a logical mistake in it(setting a value to from null to null or setting it from undefined to undefined) https://www.measurethat.net/Benchmarks/Show/15587/0/delete-vs-null-vs-undefined-vs-void-0-vs-objectcreatenu

and here the result is a bit more extreme 4mio ops (from null to null) vs 4k ops (undefined to undefined)

I know the test isnt really relevant its pure interest im asking :).


Solution

  • (V8 developer here.)

    Microbenchmarks are misleading! Don't waste your time on them.

    Setting an object property to null or to undefined has the same speed. Guaranteed.

    Considering the significant difference that your test reproducibly shows, I got curious and dug in a bit. Turns out measurethat.net's framework code is... let's say... far from perfect: it uses "direct eval" in a way that introduces huge performance artifacts for accessing globals (that's one of several reasons why "never use direct eval!" is common advice), and one of JavaScript's historical accidents is that while null is a reserved keyword, undefined is just a global variable. See here for how ridiculous it gets:
    https://www.measurethat.net/Benchmarks/Show/15627/0/accessing-null-vs-undefined
    If you know what's going on, you can sidestep the issue:
    https://www.measurethat.net/Benchmarks/Show/15635/0/null-vs-undefined-iiffe
    But keep in mind that in a real app that doesn't use eval, you wouldn't see any of these differences; you're just playing games with a bad benchmark runner there!

    Another thing that's really weird on that site is that when editing test cases and "validating" them, they produce very different results (I've seen 100x!) compared to "running" them after submitting them.

    In short, I wouldn't trust any of the reported numbers on that site.

    All that said, it makes sense that delete a.a is slower, because deleting an object property is a more complicated operation than overwriting an existing property's value. Importantly (and your benchmark doesn't show this, because it's too simple!), deleting properties often has non-local effects, i.e. it's not the deletion itself that's necessarily slow, but other parts of your app might get slowed down as side effects. We generally recommend not to use the delete keyword at all. Deleting entries in Maps is a different story: that's perfectly fine, as Maps are built to support that efficiently.