【问题标题】:Are ES6 global symbols garbage collected?ES6 全局符号是否被垃圾收集?
【发布时间】:2017-02-21 03:54:41
【问题描述】:

ES6 符号的无上限、动态创建是否会导致不可恢复的内存使用?

在 Erlang(以及以前的 Ruby)中,原子/符号的创建不会被垃圾回收。

似乎在全局符号注册表 (Symbol.for('string')) 中创建的符号无法被垃圾收集并保持全局唯一,但我可能会遗漏一些东西。在我看来,这似乎不是 ES6 规范所规定的。

【问题讨论】:

  • 你标题中的问题完全是在主题上。但是,您 text 中的问题是题外话(基于意见)。
  • 符号本身是原语。 The spec 没有说 GlobalSymbolRegistry 列表中的记录(持有键和相应的符号)被弱持有。所以我猜(因此不是答案)记录不是 GC'd。但是您必须创建 很多 组才重要。
  • @T.J.Crowder 已经在 J​​S 中写过符号是原语。原语首先不受垃圾收集的影响。引擎所能做的就是从列表中删除一个条目。无论哪种方式,这都没有任何意义。如果您将某些内容放入注册表,则引擎无法预测您将来是否会尝试获取它。
  • @zeroflagL,你不知道你在说什么。存储原语需要内存,如果内存未被回收,则存在内存泄漏。引擎不需要预测您是否会检索它。正确实施的引擎将检查您是否在范围内有符号,如果没有,则将它们从列表中删除。只要前一个返回的符号不在作用域内,下次返回不同的符号就没有关系,因为符号不支持除了与自身比较之外的任何操作。

标签: javascript ecmascript-6


【解决方案1】:

符号是原语并不意味着它们不能使用引用和分配来实现。想想 js 中的原始字符串。浏览器可能会以这种方式实现符号,使它们服从 gc。在 chrome 中快速测试 for(;;) Symbol();(不要运行它)会导致锯齿状的内存配置文件,所以我假设符号被分配并被垃圾收集。

【讨论】:

  • for(;;) Symbol(); 不测试全局符号,它只测试局部范围的符号。要测试是否存在带有全局符号 db 的泄漏,请使用:(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); })()。我相信 Chrome 不会测试使用的符号是否在范围内,换句话说,Chrome 会发生内存泄漏。
  • 另外,首先确保这个断言是好的:{let r = 65536+Math.floor(Math.random()*(Number.MAX_SAFE_INTEGER+1-65536+1)); console.assert(String.fromCharCode(r)===String.fromCharCode(r%65536))}
  • @Pacerier 我用的是chrome的builtin heap profiler
  • 更新代码的结果如何?还是锯齿状的?
  • @Pacerier 使用我目前的 Chrome 我什至无法重现原始结果。顺便说一句,您的代码似乎过于复杂。你为什么不直接Symbol.for('t'+i)
猜你喜欢
  • 2020-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-05
  • 2018-08-15
  • 1970-01-01
相关资源
最近更新 更多