在我的JS实时应用程序中,垃圾收集时间过长

时间:2014-06-05 18:29:59

标签: javascript garbage-collection real-time google-chrome-devtools v8

所以我正在研究这个相当复杂的实时应用。我有一个音频引擎,每100毫秒触发重音频处理功能,以填充立即播放的缓冲区。 如果这些音频功能运行得太晚,甚至一次,您可以听到声音口吃

大多数时候一切都很好。 然而,当垃圾收集器由V8触发时,完成一轮需要大约150ms,这会触发上述裂缝

所以问题是:如何才能缩短垃圾收集时间?

几条评论:

我们可以尝试分配更少的变量,以便堆增长更慢,但我想这不会解决问题:即使GC被触发的频率是一半,我也没有看到为什么收集的原因应该跑得更快。我宁愿让它经常运行两次,也只能运行一半。

我已经阅读了有关V8 GC的一些内容。我知道我无法直接控制GC。我知道它有一个短期过程和一个长期过程(标记和扫描)。我猜它是造成这个问题的后者。但是,我不知道它花费这么长时间的确切原因:是删除的数据量还是浏览的数据结构?知道这一点可能会有所帮助。

我已经尝试过广泛使用Chrome开发工具,并且根据 this article我需要使用" Record Heap Allocations"模块。但是当我运行并同时查看时间轴时,我可以看到它一直触发垃圾收集,就像堆快照一样,所以我无法真正追踪到什么使我的内存增长。

我们没有任何内存泄漏,这已经过测试。没有常规的DOM访问,也没有创建事件侦听器。我想这是一个常见的问题,考虑到具有高FPS的应用程序的数量......请帮忙!

修改

我们想到的一个替代解决方案是故意将我们的数据存储在内存泄漏中,以便GC在我们明确决定释放内存之前不会运行。这听起来像一个邪恶的黑客,有没有人这样做过?你觉得怎么样?

1 个答案:

答案 0 :(得分:4)

您可以尝试实现“对象池”设计模式。基本原则是重用变量而不是创建删除变量。最好按对象类型设置一个池。

这是一个非常基本的实现。

var pool = [];
var poolRelease = function(obj) {
  pool.push(obj);
};
var poolGet = function() {
  // You could add parameters to the function to directly set the values of the object.
  if (pool.length) {
    return pool.pop();
  }
  // We don't have preexisting object, create it (can be anything).
  return {x: 0, y: 0};
}

// Then in the code:
var myObj = poolGet();
myObj.x = 20;
// When finished with the object move it back to the pool to avoid garbage collection.
poolRelease(myObj);