我正在尝试构建一个流畅的60fps动画浏览器javascript循环。我注意到垃圾收集器启动并为动画帧添加了可变的非零时间。我开始追踪我的代码中的分配,然后将循环隔离开来。我正在使用requestAnimationFrame
并发现在所谓的“空”循环中它仍会导致每次迭代的分配并触发垃圾收集器。令人沮丧的是,这似乎也发生在其他循环机制setInterval
和setTimeout
中。
下面我将一些jsfiddles和屏幕截图放在一起,演示样本'空循环'。所有样本均来自约5秒的时间线。
此时,我正在寻找最小化垃圾收集的最佳解决方案。从下面的示例看,requestAnimationFrame在这方面看起来是最糟糕的选择。
requestAnimationFrame
https://jsfiddle.net/kevzettler/e8stfjx9/
var frame = function(){
window.requestAnimationFrame(frame);
};
window.requestAnimationFrame(frame);
的setInterval
https://jsfiddle.net/kevzettler/p5LbL1am/
var frame = function(){
//literally nothing
};
window.setInterval(frame, 0);
的setTimeout
https://jsfiddle.net/kevzettler/9gcs6gqp/
var frame = function(){
window.setTimeout(frame, 0);
}
window.setTimeout(frame, 0);
答案 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