垃圾收集在我的JS实时应用程序中花费了太长时间

Garbage collecting takes too long in my JS real-time app

本文关键字:长时间 应用程序 实时 JS 我的      更新时间:2023-09-26

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

大多数时候一切都很好。然而,当V8触发垃圾收集器时,完成一轮大约需要150ms,这就触发了前面提到的裂缝

所以这里的问题是:我怎么能得到更短的垃圾收集?

几个备注:

我们可以尝试分配更少的变量,以便堆增长得更慢,但我想这并不能解决问题:即使触发GC的频率减半,我也看不出有任何理由让收集运行得更快。我宁愿让它运行两倍的频率和持续时间的一半。

我读了一些关于V8的GC的东西。我知道我不能直接控制GC。我理解这有一个短期的过程,也有一个长期的过程。扫描)。我想是后者引起了这个问题。然而,我不知道它需要这么长时间的确切原因:是删除的数据量还是浏览的数据结构?知道这一点可能会有所帮助。

我已经尝试使用Chrome开发工具广泛,并根据这篇文章我需要使用"记录堆分配"模块。但是当我运行一个并并行查看时间轴时,我可以看到它一直在触发垃圾收集,就像堆快照一样,所以我无法真正跟踪到底是什么使我的内存增长。

我们没有任何内存泄漏,这已经过测试。没有常规的DOM访问,没有创建事件侦听器。我想这是一个普遍的问题,因为有很多应用的FPS都很高……请帮助!

编辑

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

您可以尝试实现"对象池"设计模式。基本原则是重用变量,而不是创建和删除它们。最好按对象类型划分一个池。

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

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);