8

考虑这个 javascript 代码:

var s = "Some string";
s = "More string";

垃圾收集器(GC)在这种操作之后会有工作吗?

(我想知道在尝试最小化 GC 暂停时是否应该担心分配字符串文字。)

e:我觉得有点好笑,虽然我在问题中明确指出我需要最小化 GC,但每个人都认为我错了。如果真的必须知道具体细节:我有一个 javascript 游戏——它在 Chrome 中运行良好,但在 Firefox 中有半频繁的暂停,这似乎是由于 GC。(我什至检查了 Firefox 的 MemChaser 扩展,停顿与垃圾收集完全一致。)

4

5 回答 5

10

是的,字符串需要被垃圾收集,就像任何其他类型的动态分配的对象一样。是的,这是一个有效的问题,因为在繁忙的循环中不小心分配对象肯定会导致性能问题。

但是,字符串值是不可变的(不可更改),并且大多数现代 JavaScript 实现都使用“字符串实习”,即它们只存储每个唯一字符串值的一个实例。这意味着如果你有这样的东西......

 var s1 = "abc",
     s2 = "abc";

...只会分配一个“abc”实例。这仅适用于字符串值,不适用于String对象。

要记住几件事:

  1. substring,等函数slice将为每个函数调用分配一个新对象(如果使用不同的参数调用)。

  2. 即使两个变量都指向内存中的相同数据,当 GC 循环运行时,仍然有两个变量需要处理。过多的局部变量也会对您造成伤害,因为它们中的每一个都需要由 GC 处理,从而增加开销。

一些关于编写高性能 JavaScript 的进一步阅读:

于 2012-11-29T01:39:26.103 回答
0

是的,垃圾收集器将有一个包含"Some string"要摆脱的字符串对象。而且,在回答您的问题时,该字符串分配将为 GC 工作。

因为字符串是不可变的并且被大量使用,所以 JS 引擎有一种非常有效的方式来处理它们。您应该不会注意到垃圾收集一些字符串的任何暂停。垃圾收集器在 javascript 编程的正常过程中一直有工作要做。这就是它应该如何工作的方式。

如果您正在观察 GC 的暂停,我宁愿怀疑它来自几个字符串。更有可能发生更大的问题。要么你有成千上万的对象需要 GC,要么有一些非常复杂的 GC 任务。如果不研究整体代码,我们无法真正推测这一点。

除非您正在执行一些巨大的循环并处理数以万计的对象,否则这不应该是一个问题。在这种情况下,可能需要更仔细地进行编程,以尽量减少创建的中间对象的数量。但是,如果没有该级别的对象,您应该首先正确清晰、可靠的代码,然后仅在某些事情表明您需要担心性能问题时才针对性能进行优化。

于 2012-11-29T00:54:55.570 回答
0

是的,但是除非您在循环中执行此操作数百万次,否则它不太可能成为您担心的因素。

于 2012-11-29T00:55:55.657 回答
0

正如您已经注意到的,JavaScript 不是 JavaScript。它在不同的平台上运行,因此将具有不同的性能特征。所以对于“在这种操作之后 GC 有工作要做吗?”这个问题的明确答案。是:也许。如果脚本和您展示的一样短,那么 JIT 编译器可能会完全删除第一个字符串。但是语言定义中没有规定必须以这种方式或其他方式。所以最终它就像在 JavaScript 中经常发生的那样:你必须尝试它。

更有趣的问题也可能是:如何避免垃圾收集。那就是尽量减少新对象的分配。游戏通常具有相当数量的对象,并且通常在旧对象未被使用之前不会有新对象。对于字符串,这可能更难,因为它们在 JS 中是不可变的。因此,尽可能尝试用其他(可变)表示替换字符串。

于 2012-11-29T01:27:38.307 回答
-2

要回答您的问题“我想知道在尝试最小化 GC 暂停时是否应该担心分配字符串文字”:不。

关于垃圾收集,你真的不需要担心这种事情。

GC 仅在创建和销毁大量 Javascript 对象或大量 DOM 元素时才需要考虑。

于 2012-11-29T00:56:14.933 回答