Search code examples
javascriptnode.jsv8

Artificial performance limits in V8 / nodejs


V8 is capable of wrangling a lot of memory with use of --max-old-space-size. I regularly use node for tasks which require 10GB+, it's great - memory is cheap and it's much faster than reading/writing from/to disk.

Where I run into trouble, however, is when trying to create very large individual arrays/maps/objects. I end up with error messages like this:

FATAL ERROR: invalid table size Allocation failed - JavaScript heap out of memory

And this:

RangeError: Invalid array length

In both cases, it's not that my computer can't handle it, or that I've ran out of memory - it's because there are some insidious artificial limits hiding in V8.

To get the range error, throw this in your terminal: node -e "new Array(5*1000*1000*1000)"

And to get the invalid table size error: node -e "(new Array(200*1000*1000)).fill(1)"

These artificial limits are well known (1, 2), and are apparently due to some old garbage collector code that the V8 team is scared of touching knows will take a lot of work to fix (see chromium bug report).


Question:

To someone who knows the V8 and nodejs roadmaps well: Will these limits ever be lifted? How long could we expect to wait, roughly?

Please note that I understand patterns for lower memory usage like streaming and I know that nodejs and V8 weren't made for "big data" stuff - this question isn't about how to optimise my memory usage and the like. Just curious about the V8 and nodejs roadmaps in terms of these artificial limits.


Solution

  • V8 developer here. In short, it's not on the roadmap, sorry.

    We're aware that having size limitations on arrays and strings is unfortunate. However, raising the existing limits is going to be a lot of effort. We'd like to do it at some point, but it doesn't have priority right now. (That's pretty much what the bug you've referenced sums up to -- we're not so much scared of it, it's just non-trivial because it's not just an "insidious artificial limit", and we don't have time for it given other priorities.)

    It's not just a question of effort either, there are also technical considerations. Supporting arbitrary lengths, while possible, would make certain operations slower. We recognize that some use cases would really benefit from this increased flexibility, but other use cases benefit from the speed that comes from a simpler and faster underlying implementation. Finding the right balance is not obvious. Also, we still have to support 32-bit platforms, where the pointer size puts rather low limits on e.g. object sizes, and we as much as possible want to have the same behavior regardless of underlying hardware/OS. That's part of the point of having a JavaScript VM in the first place...

    Speaking of JavaScript: The ECMAScript spec defines that new Array(n) throws a RangeError whenever n != ToUint32(n). 5*1000*1000*1000 is not a uint32. So this particular case is actually required behavior; if V8 were to support such arrays, it would be violating the spec.