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

问题描述 投票:0回答:2

我正在尝试构建一个流畅的 60fps 动画浏览器 JavaScript 循环。我注意到垃圾收集器启动并向动画帧添加可变的非零时间。我首先跟踪代码中的分配情况,然后隔离循环本身。我正在使用

requestAnimationFrame
并发现在所谓的“空”循环上它仍然会导致每次迭代分配并触发垃圾收集器。令人沮丧的是,这似乎也发生在其他循环机制
setInterval
setTimeout
中。

下面我整理了一些 jsfiddles 和屏幕截图,演示了示例“空循环”。所有样本均来自约 5 秒的时间线。

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

请求动画框架

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

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

window.requestAnimationFrame(frame);

设置间隔

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

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

window.setInterval(frame, 0);

设置超时

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

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

window.setTimeout(frame, 0);

javascript performance google-chrome garbage-collection v8
2个回答
2
投票

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


1
投票

我不是专家,但根据我所读到的内容。我也遇到了您在评论中提到的相同错误报告:

按照建议,在每次调用时分配 Number 对象,将与垃圾收集相符。

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

它还表明,仅仅打开调试器来记录堆栈跟踪可能会导致问题。不知道远程调试的时候是不是也是这样?

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

从你问的问题的深度来看,我确定我是什么 即将要说的内容对您来说是显而易见的,但重新关注可能会有兴趣 你的总体目标(尽管可能对你的目标没有帮助) Chrome 的有趣观察)。

我们需要记住的一件事是我们并不是要避免 完全垃圾收集,因为它是 JS 的基础。相反,我们是 希望尽可能地减少它以适应渲染我们的 16ms 的帧(以获得 60fps)。

VelocityJs 的方法之一是使用单个全局“tick”来处理所有动画...

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

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

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

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

https://web.archive.org/web/20120318031940/http://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript

© www.soinside.com 2019 - 2024. All rights reserved.