Javascript如何创建一个免费的动画循环来避免垃圾收集器?

时间:2016-03-10 04:48:55

标签: javascript performance google-chrome garbage-collection v8

我正在尝试构建一个流畅的60fps动画浏览器javascript循环。我注意到垃圾收集器启动并为动画帧添加了可变的非零时间。我开始追踪我的代码中的分配,然后将循环隔离开来。我正在使用requestAnimationFrame并发现在所谓的“空”循环中它仍会导致每次迭代的分配并触发垃圾收集器。令人沮丧的是,这似乎也发生在其他循环机制setIntervalsetTimeout中。

下面我将一些jsfiddles和屏幕截图放在一起,演示样本'空循环'。所有样本均来自约5秒的时间线。

此时,我正在寻找最小化垃圾收集的最佳解决方案。从下面的示例看,requestAnimationFrame在这方面看起来是最糟糕的选择。

requestAnimationFrame

https://jsfiddle.net/kevzettler/e8stfjx9/

var frame = function(){
    window.requestAnimationFrame(frame);
};

window.requestAnimationFrame(frame);

enter image description here

的setInterval

https://jsfiddle.net/kevzettler/p5LbL1am/

var frame = function(){
   //literally nothing
};

window.setInterval(frame, 0);

enter image description here

的setTimeout

https://jsfiddle.net/kevzettler/9gcs6gqp/

var frame = function(){
    window.setTimeout(frame, 0);
}

window.setTimeout(frame, 0);

enter image description here

2 个答案:

答案 0 :(得分:2)

我实际上并不确定,但我似乎记得网络工作者有自己的垃圾收集器,因此GC命中率不会影响主线程中的FPS(尽管它仍然会影响更新&# 39;能够被发送到主线程)

答案 1 :(得分:1)

我不是专家,而是我从读过的东西。我也遇到了你在评论中提到的同一个错误报告:

正如所建议的那样,在每次调用时分配Number对象,就会收集垃圾。

https://bugs.chromium.org/p/chromium/issues/detail?id=120186#c20

它还表明,只需让调试器打开记录堆栈跟踪就可能导致问题。我想知道在进行远程调试时是否会出现同样的情况?

这个答案建议在动画帧之间翻转,以减少垃圾收集:https://stackoverflow.com/a/23129638/141022

根据您提出的问题的深度来判断,我确定我的意思 即将说明对你来说很明显,但重新关注可能是有意义的 一般来说你的目标(尽管可能对你的目标没有帮助) 有趣的观察Chrome)。

我们需要记住的一件事是我们不打算避免 完全垃圾收集,因为它对JS来说非常重要。相反,我们是 希望尽可能地减少它以适应渲染我们的 帧数为16ms(达到60fps)。

VelocityJs的一种方法是拥有一个处理所有动画的全局“滴答”......

  

在setInterval(),setTimeout()和时创建计时器   使用requestAnimationFrame()。有两个性能问题   计时器创建:1)太多计时器一次点火会减少帧数   由于浏览器维护它们的开销导致的费率,以及2)   不正确地标记动画开始的时间结果   丢帧。

     

Velocity对第一个问题的解决方案是保持单一   全局刻度循环,循环遍历所有活动的速度动画   一旦。不为每个Velocity动画创建单独的计时器。   简而言之,Velocity优先考虑调度而不是中断。

http://www.sitepoint.com/incredibly-fast-ui-animation-using-velocity-js/

这与减少垃圾收集的一般做法一起,例如创建回收缓存以重用对象,甚至重写诸如数组切片之类的方法以避免垃圾。

https://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript