10

Is uncapped, dynamic creation of ES6 Symbols something that can result in irrecoverable memory usage?

In Erlang (and also previously, Ruby), creation of atoms/symbols are not garbage collected.

It seems like Symbols created in the global symbol registry (Symbol.for('string')) could not be garbage collected and remain globally unique but I might be missing something. This did not seem to me to be dictated by the ES6 spec.

Eoin
  • 302
  • 1
  • 9
  • The question in your title is entirely on-topic. The question in your *text*, though, is off-topic (opinion-based). – T.J. Crowder Oct 12 '16 at 11:12
  • 4
    Symbols themselves are primitives. [The spec](http://www.ecma-international.org/ecma-262/7.0/index.html#sec-symbol.for) doesn't say anywhere that the records in the *GlobalSymbolRegistry* list (holding the keys and corresponding Symbols) are weakly held. So I'd guess (hence not an answer) that the records aren't GC'd. But you'd have to create a ***lot*** of them for it to matter. – T.J. Crowder Oct 12 '16 at 11:13
  • @zeroflagL, You don't know what you're talking about. Storing primitives need memory and if memory is unreclaimed, there is a memory leak. The engine doesn't need to predict if you will retrieve it. A properly implemented engine will check if you have the symbols in scope, and if not, remove them from the list. It doesn't at all matter that a different symbol is returned the next time as long as the previous returned symbol isn't in scope, because symbols don't support any operations except comparison to self. – Pacerier Sep 15 '17 at 14:39
  • @abetteroliver: *“Primitives are not subject to garbage collection in the first place”* Not true, how do you think strings work? – Ry- May 09 '23 at 06:01

1 Answers1

2

Symbols being primitives does not mean they cannot be implemented using references and allocation. Just think about primitive strings in js. Browsers might implement symbols this way, making them subject to gc. A quick test for(;;) Symbol(); (don't run it) in chrome causes a sawtooth memory profile so I assume symbols get allocated and garbage collected.

Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97
  • 1
    `for(;;) Symbol();` doesn't test global symbols, it tests only locally scoped ones. To test if there's a leak with global symbol db, use: `(function f(){ let first_char = String.fromCharCode(0); let s = first_char; let NextString = _1=>s.charCodeAt(0) !== 65535? String.fromCharCode(s.charCodeAt(0)+1)+s.substring(1):first_char+s; for(let x=1; x<=200000; ++x)Symbol.for(s),s=NextString(s); console.log('done a lap. next in 5 sec'); setTimeout(f,5000); })()`. I believe that Chrome doesn't test if used symbols are within scope, in other words, Chrome is subject to memory leak. – Pacerier Sep 15 '17 at 14:32
  • Also, firstly ensure this assert is fine: `{let r = 65536+Math.floor(Math.random()*(Number.MAX_SAFE_INTEGER+1-65536+1)); console.assert(String.fromCharCode(r)===String.fromCharCode(r%65536))}` – Pacerier Sep 15 '17 at 14:32
  • @Pacerier I used chrome's [builtin heap profiler](https://developers.google.com/web/tools/chrome-devtools/memory-problems/allocation-profiler) – Tamas Hegedus Sep 15 '17 at 15:54
  • What's your results for the updated code? Still sawtooth? – Pacerier Sep 18 '17 at 16:34
  • @Pacerier with my current Chrome I couldn't even reproduce the original results. Btw your code seems overly complicated. Why don't you just `Symbol.for('t'+i)`? – Tamas Hegedus Sep 18 '17 at 16:36