【譯】Firefox 52 中對于 setTimeout() 的改動

火狐瀏覽器52版本的 setTimeout 的改動

編寫于 2017.3.13 標(biāo)簽: dom, mozilla, timer

上一周火狐瀏覽器52版本發(fā)布了,其中包括對 setTimeout() 以及 setInterval() 的一些改變。特別是我們改變了怎樣去調(diào)度以及執(zhí)行計(jì)時器回調(diào)以減少頁面崩潰的風(fēng)險。

在開始前,先看一下這個簡單的demo(你可能不會想要打開這個網(wǎng)頁)

Demo Site

當(dāng)你點(diǎn)擊 'Start' 按鈕的時候,瀏覽器就開始被網(wǎng)站上觸發(fā)的 setTimeout() 計(jì)時器給泛濫了。每一個回調(diào)都會觸發(fā)一個 setTimeout() 兩次。這將會導(dǎo)致計(jì)時器的指數(shù)爆炸。點(diǎn)擊 'Stop' 將會停止觸發(fā) setTimeout()。

頁面上有個GIF動畫以便你能直觀的看見是否有頁面崩潰的產(chǎn)生。(這是一個非常棒的想法,我從 Nolan Lawson's IDB performance post 那兒偷來的。

一般的來說,瀏覽器將會丟幀當(dāng)這樣的事情發(fā)生的時候(計(jì)時器指數(shù)爆炸),并且GIF也會停止動畫。比如,這個是 Firefox 45 ESR版本運(yùn)行上面的Demo的視頻:

在Firefox 45 ESR版本中

在Firefox 52版本中,我們做了一些改變以便讓瀏覽器在遇到這種情況是能夠最大化的存活(不崩潰)。下面這個video就展示了效果。經(jīng)過一段展示的停頓,這個GIF動畫繼續(xù)還算順利的渲染盡管有計(jì)時器洪水(我個人理解是計(jì)時器爆炸)。

在Firefox 52版本中

它是怎么工作的?

Firefox 實(shí)現(xiàn)這個是通過實(shí)施 yielding 在計(jì)時器的回調(diào)之間。 當(dāng)一個計(jì)時器的回調(diào)開始執(zhí)行的時候,我們允許任何其他的非計(jì)時器事件在下一個計(jì)時器回調(diào)開始運(yùn)行之前完成。

比如,考慮這樣一種情況,當(dāng)我們有一批的計(jì)時器回調(diào),希望在同步刷新的同時運(yùn)行。這是一個比賽,事件將首先運(yùn)行,然而,刷新通常被認(rèn)為更重要,因?yàn)槿绻谎舆t,則站點(diǎn)的每秒幀數(shù)將下降。

考慮到這一點(diǎn),思考一下調(diào)度事件的“最佳”情況和“最差”情況:

the best
the best

在最好的情況下,刷新首先運(yùn)行并且不會被延遲。在最壞的情況下,刷新被延遲直到所有的計(jì)時器回調(diào)都被執(zhí)行完成。在極端的情況下,像上面的演示,這個延遲可以是很長。

在計(jì)時器回調(diào)之間的Yielding會改變這種情況,所有最壞的情況將會被這個替代:

Yielding
Yielding

現(xiàn)在,刷新將最多被一個回調(diào)延遲。

事實(shí)上我們并沒有真正的重置所有事件在事件列表中。也許一個更好的方式來認(rèn)為它是計(jì)時器存儲在一個單獨(dú)的隊(duì)列,在任何時候只允許在主事件隊(duì)列上調(diào)度單個計(jì)時器

other thinks
other thinks

因此當(dāng) “callback1”完成后 “callback2” 才會被加入到主事件隊(duì)列的末尾,這允許接下來執(zhí)行刷新事件。

這是節(jié)流嗎?

不是?!坝?jì)時器節(jié)流”意味著向每個計(jì)時器引入一定量的延遲。例如,如果在后臺選項(xiàng)卡中調(diào)用 setTimeout(func, 5) ,大多數(shù)瀏覽器會將計(jì)時器回調(diào)延遲至少1秒鐘。

Yielding 的不同之處在于,如果主線程空閑,它允許計(jì)時器以全速運(yùn)行。如果主線程繁忙,Yielding只會導(dǎo)致計(jì)時器延遲。(當(dāng)然,如果主線程忙,那么計(jì)時器總是有被延遲的風(fēng)險。)

也就是說,如果我們檢測到計(jì)時器隊(duì)列正在備份,我們開始節(jié)流計(jì)時器。這個負(fù)載有助于避免在腳本生成更多setTimeout() 調(diào)用的時候耗盡內(nèi)存。這種負(fù)載被調(diào)整到只在極端情況下觸發(fā),大多數(shù)網(wǎng)站不應(yīng)該體驗(yàn)它。

這是優(yōu)先級嗎?

不是。計(jì)時器的Yielding與使用優(yōu)先級隊(duì)列和標(biāo)記計(jì)時器回調(diào)優(yōu)先級不同。在嚴(yán)格的優(yōu)先級排序方案中,低優(yōu)先級事件將可能從不運(yùn)行。這不是這種情況。

在我們的計(jì)時器的Yielding方法中,下一個計(jì)時器回調(diào)以與所有其他事件相同的優(yōu)先級運(yùn)行。它可以在其他工作之前執(zhí)行。它也保證在某個點(diǎn)執(zhí)行。

有什么收獲

雖然我們的一般方法是在計(jì)時器之間Yielding,但我們的最終解決方案實(shí)際上并不這樣做。我們實(shí)際上允許有限數(shù)量的計(jì)時器回調(diào)運(yùn)行不經(jīng)過使用yielding。我們這樣做是為了減輕對使用計(jì)時器但飽和主線程的網(wǎng)站的影響。

比如,考慮到這樣的網(wǎng)站:

  1. 通過大量的計(jì)時器回調(diào)運(yùn)行動畫。
  2. 動畫渲染使主線程變得飽和。

在這種情況下計(jì)時器回調(diào)將會由渲染的速率來節(jié)流。當(dāng)瀏覽器不能以60FPS渲染時,那么在每個刷新驅(qū)動程序事件之間最多只能獲得一個計(jì)時器回調(diào)。

busy
busy

對于“閉環(huán)”動畫,這不是一個問題,你可以衡量運(yùn)行的時間和調(diào)整你的更改以匹配。但是,他可以顯著增加“開環(huán)”動畫的整體動畫時間。

比如,看看這個動畫演示網(wǎng)站
“Open Loop” Animation Demo

這里,這個網(wǎng)站預(yù)先計(jì)算所有的動畫步驟,并為每一個計(jì)劃一個單獨(dú)的 setTimeout() 。每一個計(jì)時器回調(diào)只是修改其步驟的DOM。而不是測量動畫是否落后。

這個演示網(wǎng)站將導(dǎo)致幾乎每個現(xiàn)代瀏覽器下降到零幀每秒。然而,總動畫將很快運(yùn)行。
普通現(xiàn)代瀏覽器

在Firefox 52 ,由于我們的Yielding使許多的計(jì)時器被延遲。這使得瀏覽器運(yùn)行在30FPS,但是因此動畫需要更長的時間來完成:
Firefox 52

這是一個極端的情況,我們不認(rèn)為反映了大多數(shù)網(wǎng)站的典型行為有許多的方法來實(shí)現(xiàn)這個動畫,而不需要成千上百的同時計(jì)時器。網(wǎng)站很可能使用這些備用方法來避免觸發(fā)由此技術(shù)引起的差的FPS性能。

話雖如此。我們?nèi)匀幌氡M可能的避免打破現(xiàn)有的網(wǎng)站,這就是為什么我們不是在每個計(jì)時器回調(diào)之后執(zhí)行嚴(yán)格的yield。我們希望通過允許幾個計(jì)時器回調(diào)運(yùn)行而不產(chǎn)生損失,我們可以減輕對這些類型的工作負(fù)載的影響,同時仍然提高一般的站點(diǎn)的性能。

下一步是什么

這些 setTimeout() 更改剛剛更新到Firefox 52.我們將會持續(xù)的尋找任何不被察覺的兼容性問題。到目前為止,我們只有一個單一的錯誤報告在四個月內(nèi),因?yàn)樗德湓谝归g。

如果你認(rèn)為你的網(wǎng)站在Firefox中有因?yàn)檫@個改動而導(dǎo)致的問題,請報告錯誤并且將我添加到CC列表。

除了大規(guī)模的問題,我們計(jì)劃繼續(xù)改進(jìn)這種方法。我們可能會改變對“允許出現(xiàn)的計(jì)時器”的限制,使用時間預(yù)算方法而不是固定數(shù)字。另外,Quantum DOM項(xiàng)目將對一般的事件隊(duì)列調(diào)度進(jìn)行更多的改變

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

參考:從setTimeout說事件循環(huán)
PS: 因?yàn)槲矣⒄Z不太好,基本上是借著google翻譯的,所以受不了的可以直接點(diǎn)擊原文查看。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容