为什么Typed Arrays在JavaScript中导致Memoryleaks

时间:2016-09-05 15:34:36

标签: javascript arrays garbage-collection

我注意到在尝试创建许多Float32Arrays时出现此错误:

  

未捕获的RangeError:数组缓冲区分配失败

我试图像这样重现错误:

console.log("trying to cause memory leaks");
for(var i = 0; i < 1000; i++){
    console.log(i);
    var x = new Float32Array(100000000);
  //var x = new Array(100000000);
}
console.log("finished");

jsfiddle

据我了解垃圾收集器的概念,他应该收集并转储未链接的对象。但由于我得到上面提到的错误,我不认为它按预期工作。然而,当我使用Array而不是Float32Array做同样的事情时,没有任何问题。我甚至可以使用Array来扩展数字。 所以也许我对垃圾收集器不了解或者Float32Array构造函数有些可疑。也许我的测试缺乏完整性,即。垃圾收集器没有足够的时间收集,或者像这样琐碎?

也许有人可以给我一些见解?

PS:我使用的是使用V8引擎的Chrome 52.0.2743.116 m

1 个答案:

答案 0 :(得分:2)

  

然而,当我使用Array而不是Float32Array执行相同操作时,没有任何问题。我甚至可以使用Array来扩展数字。

new Array(100000000)除了具有length属性的数组对象外,不会分配任何内容。就是这样。没有创建任何元素插槽,因为标准数组aren't really arrays at all (我博客上发布的帖子),它们只是Array.prototype支持的特殊对象length属性以及对名称符合规范&#34;数组索引&#34;的定义的属性的特殊处理(详见the spec)。

相反,new Float32Array(100000000)必须为100,000,000个32位插槽(加上对象开销)分配连续内存。因此,如果没有可用于该缓冲区的400,000,000字节的连续块,它将会失败。

附注:我能够在* nix上的Chrome 52.0.2743.116(64位)中完成循环。花了一段时间,但......没有出现内存泄漏,系统内存使用在运行时看起来像这样(开始时的平坦线是在我开始之前,我在它完成之前很久就把它切掉了,它将方式太宽,否则):

enter image description here

我们可以看到V8(Chrome中的JavaScript引擎)会让一些垃圾堆积,然后运行GC并清理一些未引用的Float32Array,然后让垃圾堆积,然后GC等等。没有泄漏

Chrome的任务管理器显示了这种用法:

Before starting:                 58,000k
While running:    3,700,000 - 5,100,000k
At end:                         450,000,

...这是有道理的,因为在循环结束时没有清除x,所以它仍然引用最后一个数组。