【译】Firefox 52 中对于 setTimeout() 的改动

火狐浏览器52版本的 setTimeout 的改动

编写于 2017.3.13 标签: dom, mozilla, timer

上一周火狐浏览器52版本发布了,其中包括对 setTimeout() 以及 setInterval() 的一些改变。特别是我们改变了怎样去调度以及执行计时器回调以减少页面崩溃的风险。

在开始前,先看一下这个简单的demo(你可能不会想要打开这个网页)

Demo Site

当你点击 'Start' 按钮的时候,浏览器就开始被网站上触发的 setTimeout() 计时器给泛滥了。每一个回调都会触发一个 setTimeout() 两次。这将会导致计时器的指数爆炸。点击 'Stop' 将会停止触发 setTimeout()

页面上有个GIF动画以便你能直观的看见是否有页面崩溃的产生。(这是一个非常棒的想法,我从 Nolan Lawson's IDB performance post 那儿偷来的。

一般的来说,浏览器将会丢帧当这样的事情发生的时候(计时器指数爆炸),并且GIF也会停止动画。比如,这个是 Firefox 45 ESR版本运行上面的Demo的视频:

在Firefox 45 ESR版本中

在Firefox 52版本中,我们做了一些改变以便让浏览器在遇到这种情况是能够最大化的存活(不崩溃)。下面这个video就展示了效果。经过一段展示的停顿,这个GIF动画继续还算顺利的渲染尽管有计时器洪水(我个人理解是计时器爆炸)。

在Firefox 52版本中

它是怎么工作的?

Firefox 实现这个是通过实施 yielding 在计时器的回调之间。 当一个计时器的回调开始执行的时候,我们允许任何其他的非计时器事件在下一个计时器回调开始运行之前完成。

比如,考虑这样一种情况,当我们有一批的计时器回调,希望在同步刷新的同时运行。这是一个比赛,事件将首先运行,然而,刷新通常被认为更重要,因为如果它被延迟,则站点的每秒帧数将下降。

考虑到这一点,思考一下调度事件的“最佳”情况和“最差”情况:

the best
the best

在最好的情况下,刷新首先运行并且不会被延迟。在最坏的情况下,刷新被延迟直到所有的计时器回调都被执行完成。在极端的情况下,像上面的演示,这个延迟可以是很长。

在计时器回调之间的Yielding会改变这种情况,所有最坏的情况将会被这个替代:

Yielding
Yielding

现在,刷新将最多被一个回调延迟。

事实上我们并没有真正的重置所有事件在事件列表中。也许一个更好的方式来认为它是计时器存储在一个单独的队列,在任何时候只允许在主事件队列上调度单个计时器

other thinks
other thinks

因此当 “callback1”完成后 “callback2” 才会被加入到主事件队列的末尾,这允许接下来执行刷新事件。

这是节流吗?

不是。“计时器节流”意味着向每个计时器引入一定量的延迟。例如,如果在后台选项卡中调用 setTimeout(func, 5) ,大多数浏览器会将计时器回调延迟至少1秒钟。

Yielding 的不同之处在于,如果主线程空闲,它允许计时器以全速运行。如果主线程繁忙,Yielding只会导致计时器延迟。(当然,如果主线程忙,那么计时器总是有被延迟的风险。)

也就是说,如果我们检测到计时器队列正在备份,我们开始节流计时器。这个负载有助于避免在脚本生成更多setTimeout() 调用的时候耗尽内存。这种负载被调整到只在极端情况下触发,大多数网站不应该体验它。

这是优先级吗?

不是。计时器的Yielding与使用优先级队列和标记计时器回调优先级不同。在严格的优先级排序方案中,低优先级事件将可能从不运行。这不是这种情况。

在我们的计时器的Yielding方法中,下一个计时器回调以与所有其他事件相同的优先级运行。它可以在其他工作之前执行。它也保证在某个点执行。

有什么收获

虽然我们的一般方法是在计时器之间Yielding,但我们的最终解决方案实际上并不这样做。我们实际上允许有限数量的计时器回调运行不经过使用yielding。我们这样做是为了减轻对使用计时器但饱和主线程的网站的影响。

比如,考虑到这样的网站:

  1. 通过大量的计时器回调运行动画。
  2. 动画渲染使主线程变得饱和。

在这种情况下计时器回调将会由渲染的速率来节流。当浏览器不能以60FPS渲染时,那么在每个刷新驱动程序事件之间最多只能获得一个计时器回调。

busy
busy

对于“闭环”动画,这不是一个问题,你可以衡量运行的时间和调整你的更改以匹配。但是,他可以显著增加“开环”动画的整体动画时间。

比如,看看这个动画演示网站
“Open Loop” Animation Demo

这里,这个网站预先计算所有的动画步骤,并为每一个计划一个单独的 setTimeout() 。每一个计时器回调只是修改其步骤的DOM。而不是测量动画是否落后。

这个演示网站将导致几乎每个现代浏览器下降到零帧每秒。然而,总动画将很快运行。
普通现代浏览器

在Firefox 52 ,由于我们的Yielding使许多的计时器被延迟。这使得浏览器运行在30FPS,但是因此动画需要更长的时间来完成:
Firefox 52

这是一个极端的情况,我们不认为反映了大多数网站的典型行为有许多的方法来实现这个动画,而不需要成千上百的同时计时器。网站很可能使用这些备用方法来避免触发由此技术引起的差的FPS性能。

话虽如此。我们仍然想尽可能的避免打破现有的网站,这就是为什么我们不是在每个计时器回调之后执行严格的yield。我们希望通过允许几个计时器回调运行而不产生损失,我们可以减轻对这些类型的工作负载的影响,同时仍然提高一般的站点的性能。

下一步是什么

这些 setTimeout() 更改刚刚更新到Firefox 52.我们将会持续的寻找任何不被察觉的兼容性问题。到目前为止,我们只有一个单一的错误报告在四个月内,因为它降落在夜间。

如果你认为你的网站在Firefox中有因为这个改动而导致的问题,请报告错误并且将我添加到CC列表

除了大规模的问题,我们计划继续改进这种方法。我们可能会改变对“允许出现的计时器”的限制,使用时间预算方法而不是固定数字。另外,Quantum DOM项目将对一般的事件队列调度进行更多的改变

原文链接 :https://blog.wanderview.com/blog/2017/03/13/firefox-52-settimeout-changes/?winzoom=1

参考:从setTimeout说事件循环
PS: 因为我英语不太好,基本上是借着google翻译的,所以受不了的可以直接点击原文查看。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容