Search code examples
javascriptjavagarbage-collectionnashorn

Preventing Java Nashorn from super excessive memory usage when dynamically creating a map


This trivial code, when running with Nashorn, causes full GCs

var x = {}; 
for (var i = 0; i < 10000; i++) { 
  var key = "key-" + i; 
  x[key] = i; 
} 

Reading through the Nashorn implementation, I believe each addition to an Object (using PropertyMap class) clones an object, adds the new key, links it to the previous version's "history" as a weak reference, and so on and so on.

This makes the code above quadratic in both memory and time.

Any ideas how to avoid it?


Solution

  • Your analysis is correct, Nashorn objects and property maps do not currently scale to lots of properties. The reason for making PropertyMap immutable is to allow quick validation of inline callsites by comparing PropertyMap references.

    One solution would be to switch to per-ScriptObject, mutable property maps when the number of properties exceeds some threshold. We might implement this in a future version of Nashorn, but I can't make any promises right now.

    As a workaround, you could use Java Maps for storing larger amounts of key-value pairs. Also, in JDK 9 Nashorn will get some ECMAScript 6 features which include the new Map, Set, WeakMap and WeakSet collections.