我目前正在使用 Javascript 构建游戏。经过一些测试后,我开始注意到偶尔的延迟,这只能由 GC 启动引起。我决定对其运行一个配置文件。结果表明GC实际上是罪魁祸首:
我读到创建新对象会导致大量 GC。我想知道是否有这样的事情:
var x = [];
也创建任何垃圾,因为 Java 中的原始类型不这样做。由于 Javascript 中没有真正的类型,我不确定。此外,以下哪项最适合产生最少的垃圾:
选项 1:
function do() {
var x = [];
...
}
选项 2:
var x = [];
function do() {
x = [];
...
}
选项 3:
function do() {
x = [];
...
}
或选项 4:
function do() {
var x = [];
...
delete x;
}
选项 5:
var x = [];
function do() {
x.length = 0;
...
}
在我的例子中,do 函数每秒调用 30 次。它在数组上运行多个操作。
我想知道这一点,因为我只是将所有变量设为全局变量以试图防止它们被 GC 收集,但 GC 并没有太大变化。
您能否也提供一些产生大量垃圾的常见示例和一些替代方案。
谢谢。
最佳答案
能不能把timeline的内存也显示出来?如果您有 GC 问题,那么这些问题应该很明显,因为您会看到锯齿波图。每当图形下降时,就是 GC 启动,阻止您的线程清空我们的垃圾,这是内存相关卡住的主要原因
一般来说,您使用哪个对象实例并不重要,因为 []
对内存的影响很小,您感兴趣的是数组的内容,但是通过你的选择:
选项 1:这通常没问题,但需要考虑一个因素:闭包。您应该尽量避免关闭,因为它们通常是 GC 的主要原因。
选项 2: 避免引用范围之外的内容,这对内存没有帮助,而且会使您的应用变慢一些,因为它必须向上移动闭包链才能找到匹配项.这样做没有任何好处
选项 3:永远不要这样做,你总是想在某个地方定义 x
否则你会故意泄漏到全局范围内,因此它可能永远不会被 GC
选项 4: 这实际上是一个有趣的选项。通常 delete x
不会执行任何操作,因为 delete
仅作用于对象的属性。如果您不知道,delete
实际上会返回一个 bool 值,表示该对象是否已被删除,因此您可以在 chrome 控制台中运行此示例:
function tmp () {
var a = 1;
delete a; // false
console.log('a=', a) // 1
b = 2;
delete b; // true !!!
console.log('b=', b) // Exception
}
tmp();
什么?!好吧,当你说 b = 2
(没有 var
)时,它和写 window.b = 2
是一样的,所以当你 delete b
,您基本上是在执行 delete window.b
,它满足“仅删除属性子句”。
不过,不要这样做!
选项 5:这个选项实际上为您节省了一点点内存,因为它不需要 GC x
,但是:它确实必须 GC 所有x
的内容通常比 x
本身大得多,因此不会有什么不同
如果您想了解有关内存分析和常见内存性能陷阱的更多信息,这是一篇很棒的文章:http://www.smashingmagazine.com/2012/11/writing-fast-memory-efficient-javascript/
关于JavaScript 垃圾收集。创建对象和变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33317506/