Immutable-js: slow empty Map creation

Created on 31 Aug 2016  路  3Comments  路  Source: immutable-js/immutable-js

Ran into this while profiling a hot path in our application where we follow the pattern var thing = fooMap.get('key', new Immutable.Map()) in order to ensure we have an object to work with. The v8 profile flagged that line as a surprisingly high share of CPU load so I put together a quick benchmark gist with various ways to format the line, my results:

// map has key and returns the value
baseline 169ms

// map has the key, but pass a new Immutable.Map() as the second parameter
successful accessor, always creating new map 539ms

// map has the key, fall back via || operator to a new Immutable.Map()
successful accessor, conditionally creating new map 417ms

// map doesn't have the key, pass new Immutable.Map()
failed accessor, always creating new map 667ms

// map doesn't have the key, fall back via || operator to new Immutable.Map()
failed accessor, conditionally creating new map 517ms

// map doesn't have the key, pass an existing empty Map as the second parameter
failed accessor, locally cached map 50ms

// map doesn't have the key, pass a an empty Map that was attached to Immutable.Map
failed accessor, immutable cached map 67ms

The results show that re-using an empty Map object is over 10x (in this microbenchmark) faster than calling new Immutable.Map(); I debugged the call to create an empty Map and verified it is properly re-using EMPTY_MAP, so it looks like this may all be due JavaScript's function call & stack overhead we know and love.

That said, I was wondering if you would be willing to include empty collections objects statically, something like Immutable.Map.Empty and Immutable.List.Empty which, while still somewhat slower (the last benchmark value above) it remains much faster than calling new Immutable.Map() and would allow us to not define a new empty Map in various modules.

You may argue this is over-optimizing (and it may be) but by passing the cached Map we had a noticeable impact on our server-side rendering.

Most helpful comment

Closing this aging issue.

The solution is to not use new. The JS VM will allocate new memory when call new even though Immutable.js does not use that memory, and that can create a performance hit.

In fact, Immutable.Map() when called with no arguments does in fact return the same instance of the empty Map every time, and VMs are very fast at optimizing paths like this.

All 3 comments

Right, calling Immutable.Map() is expensive. Thus my question of can an empty Map, List, etc, be produced & exported on startup so applications can use that variable instead of calling Immutable.Map() ?

Closing this aging issue.

The solution is to not use new. The JS VM will allocate new memory when call new even though Immutable.js does not use that memory, and that can create a performance hit.

In fact, Immutable.Map() when called with no arguments does in fact return the same instance of the empty Map every time, and VMs are very fast at optimizing paths like this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

papercuptech picture papercuptech  路  4Comments

sljuka picture sljuka  路  3Comments

jshthornton picture jshthornton  路  3Comments

davidwparker picture davidwparker  路  3Comments

Haroenv picture Haroenv  路  3Comments