在 Microsoft Edge 提供快速的 JavaScript 性能
我們已經在 Windows 10 和 Microsoft Edge 大大地提高了 Chakra JavaScript 引擎的性能。目的是盡可能地利用現有硬件,讓你的 JavaScript 代碼跑的更快。以便你創建的網頁能在 Microsoft Edge 中提供更好的用戶體驗。在開發過程中,我們團隊的目標之一,就是仔細觀察用戶反饋回來的數據,盡可能的讓在現有的網頁上面跑的更快些。
就在不久前, 我們曾經為 Microsoft Edge 提供,在 Windows 10 中提高 Chakra JavaScript 引擎性能的各種方案。 改善性能是永無止盡的追求,所以在本文中,我們來談一談,如何根據當今的網頁反饋回來的數據提高 Chakra’s JIT 編譯器的性能。
跨文件腳本內聯
現在的 JavaScript 編譯器都把內聯函數當作是優化性能的關鍵因素。函數內聯是指把被調用的函數體插入調用的函數當中,就好像被調用的函數直接寫在調用的函數代碼中一樣,因此,能節省函數調用和返回的開銷(比如,寄存器的保存與恢復)。對于那些對性能要求較高的代碼,函數內聯可以提高20-30%的性能。
在內聯過程中, 編譯器會自動權衡是否要內聯處理。 比如,有些時候,編譯器為了生成內聯代碼,而花在收集上下文信息上的時間,比優化過后省下來的時間還要多。或者,試圖內聯其他上下文或腳本文件的函數,付出的代價遠比從內聯得到的要高。
在開發 Windows 10 和 Microsoft Edge 過程中, 我們從現有的網站收集了一些數據, 以便更好的理解 Chakra 的內聯優化效果。我們從排名前 10000 的網站中, 隨機選取 f 3,000 個, 得出如下數據:
![]() |
![]() |
在 Chakra中只有 30% 的函數調用進行內聯。 而有 48% o的函數, 由于調用與被調用分別存放在不同的腳本文件中, 無法內聯。 | 在另外一個圖表中,超過 60% 的網站沒有內聯。 |
在 Windows 10 和 Microsoft Edge 中, Chakra’s JIT 編譯器和和執行管道已經優化過, 所以, Chakra 現在能夠高效地內聯跨腳本文件的函數, 而不會丟失過多的性能。這種方式, 允許現有網站的 JavaScript 代碼在 Microsoft Edge 上運行的更快。
通過固定字段提高全局常量速度
ECMAScript6 將 const 常量值 引入到了 Javascript 語言中。Const 常量在給 Javascript 開發者帶來語言和工具的便利的同時,還使得 Javascript 編譯器可以優化查詢的新能。當一個屬性被定義為常量,編譯器可以該屬性在程序的整個生命周期都是不會發生改變的。在這個前提下,編譯器可以相應的優化,從而避免在這種屬性的查詢開銷。查詢開銷包括了檢查該屬性的類型, 結構,內部表現,找到該屬性實際儲存的值,以及檢查在程序的執行過程該值是否發生過變化等一系列開銷。而對于常量,編譯器不用執行以上任何一種檢查。
然后常量在網站正在日益增加,但是現存的大多數網站都還沒有試用常量結構。對于現在的網站,多數的常量都是被定義為一個全局變量,然后在代碼中到處試用. 在我們對10,000多家網站進行的一種實驗中,我們發現20%的網站都有定義整形常量的現象。而且每家網站有平均超過4處這種做法。
在 Windows 10 和 Microsoft Edge 中,我們優化了 Chakra 的解析器和 JIT 編譯器,用以識別出聲明的非常數整型變量,這些變量在程序運行期間都有定義,但是沒有變化。一旦鑒別出來,Chakra 的 JIT 編譯器生成的代碼就可以大幅度地減小循環消耗,因為這樣的全局變量在整個程序運行期間它們的值和形狀都沒有發生改變。因此將面向性能的 ECMAScript 6 中關于常數聲明的價值主張延伸到今天常數是如何廣泛地應用在網絡中。
提升 try-catch 塊中代碼的性能
在今天,使用 try-catch 是非常普遍的。但是,在實踐中并不推薦使用 try-catch,尤其對于那些對性能很敏感的代碼。Try-catch 代碼很難被優化,因為 try-catch 塊中的大對數操作會導致異常,然后被捕獲。這種方式使 JIT 編譯器很難得到一個精準的模型。不同的技術需要使用不同的模型,這就導致執行引擎需要創建額外的開銷來維護不同的模型。
我們所做的數據采集實驗是基于4500個熱門站點的,就此了解有超過96%的站點會拋出JavaScript異常。實際上,超過50%的站點會拋出超過10個以上的JavaScript異常。
直到Windows 10,Chakra都沒有優化try-catch塊內的代碼。在Windows 10和Microsoft Edge中, Chakra的編譯器現在可以抽象try-catch代碼塊內的代碼和JIT優化的代碼。這種情況下異常不會被拋出,Chakra現在執行try塊內的代碼幾乎與普通的JIT代碼一樣(這就好像try-catch不存在一樣)。
Minified JS代碼現在帶來大小和速度的好處
現今的 Web 通常都使用了 minified JavaScript 代碼,這帶來了一個優勢,即減少了客戶端(瀏覽器)顯示內容的大小。在 Windows10 release 版本中,在調查一個特殊的性能問題的時候,我們發現一件事情,一些使用 minified JS 代碼(minified JS 使用 UglifyJS)的實例,性能不及未使用 minified JS 的實例。在某些情況下,開發者在使用 minified JS 的過程中,使用了一些我們認為開發者通常不會使用的代碼模式,這也是 Chakra 還未做優化的原因。于是,我們做了一個快速的試驗,用來查看 Web 上使用 minified JS 的情況。我們從 10,000 個站點中隨機采樣了 4,000 個站點,下面是我們發現的信息:
Minification on Top 4000 sites | ||
![]() |
![]() |
![]() |
95% of the sites had some form of minified code | Out of the 95%, 77% sites had some code that was minified using UglifyJS | Out of the 95%, 47% of the sites used jQuery minified via UglifyJS |
這個試驗確認了,在 Web 中 minified JS 代碼的使用非常流行,由于 UglifyJS 存在于其它代碼之中,所以它也非常廣泛的應用于現今的 Web 之中。因此,在 Windows10 和 Microsoft Edge 瀏覽器之中,我們增加了用來提升內聯的新途徑。同時,我們優化了在 Chahra 的 JIT 編譯器的一些探索法,用來確保 minified JS 代碼運行的盡可能和沒有使用 minified JS 代碼的版本一樣快--即便不比它們更快。基于這些改變,我們測試過,使用 UglifyJS 的單一代碼模式的 minified JS 性能提升了大概20-50%。
Array#indexOf 優化
在Web中使用數組的情況是非常普遍的。除了提供polyfills和幫助函數,許多非官方的JavaScript庫,嘗試著提供JavaScript語言一些標準數組內建函數的更快的實現。理想的情況下,對于內建的部分,所有的瀏覽器都應該足夠的快,這樣,庫就可以更集中于提供polyfill和幫助API,而不是擔心在不同瀏覽器之間修復內建部分的性能問題。另一方面,開發者也不應該,僅僅為了讓一些所有JavaScript引擎實現的基本內建部分運行的更快,而不得不使用一個庫。
盡管我們離上面提到的理想情況很遠,在最近的一個數據采集的試驗中,我們嘗試著估量在現今Web中使用最多的ECMAScript 5 的內建部分。這個試驗從10,000個站點中隨機采樣大約4000個站點。我們發現,其中使用最多的前三名分別是: Array#indexOf, Array#map 和 Array#forEach。
鑒于Array內建函數在Web中的廣泛使用,在Windows10 和 Microsoft Edge中,當引擎遍歷一個數組時,Chakra優化了獲取值的過程。當數組中存在“洞”(hole,即不存在元素)的時候,這項優化有助于去除訪問原型鏈(extraneous overhead)和根據序號查找數值的時候的外部開銷。這項優化提升了Chakra和Microsoft Edge中內建的 ECMAScript5 Array#indexOf 函數超過5倍的性能。
那么,我們已經夠快了嗎?
在下面列出來的許多優化中都是來自于網絡上面已經存在的數據,幫助站點在 Microsoft Edge 上面運行的更快。我們不愿意去討論關于虛擬測試,還是經常被問及(Charkra)是如何在 Mircorsoft Edge 上獲得如此高的 Javascript 測試性能的。下面的圖是我們目前為止已經提交的IE11同其他流行的瀏覽器相比在 Microsoft Edge 上得到性能加強的 Javascript 測試結果。
![]() |
![]() |
所有的測試基準都是在64位Window 10 技術預覽版上面運行的64位瀏覽器收集而得.
系統信息:HP Compaq 8100 Elite with Intel(R) Core(TM) i7
CPU 860 @ 2.80GHz (4 cores), 12GB RAM
這張圖說明了什么?在 Microsoft Edge 上 Charkra 比 IE11 更快。仔細看,Chakra 在以下的這些的測試中通過 Microsoft Edge 獲得了性能提升:
Benchmark Microsoft Edge 的性能改進超過了 IE11
Jet Stream Apple 超過了1.5倍
Octane 2.0 Google 超過了2.25倍
注意:你會好奇在這個性能測試中為什么是了 64 位瀏覽器而不是 32 位瀏覽器,原因是不像 IE11 Microsoft Edge 需要運行在 64 位的平臺下。所有的流行的 64 位 Javascript 引擎相比較 32 位平臺運行有一點點慢,選擇 64 位平臺可以提供一些安全特性,在這篇博客中得到了補充。
然而在贏得了跑分中并沒有使我們感到很滿意,關鍵是為了提升 Javascript 的性能從 IE11 開始 Microsoft Edge 已經走過了很長的一段路程,就像測試已經存在了。如我們開始提到的,性能是一個不懈的追求。我們會繼續挖掘 Javascript 在 Microsoft Egde 中得性能極限。請繼續保持反饋幫助我們提升。您可以在網站上提交 bug,在用戶之聲上提交反饋,或者在 推ter 上面的 @MSEdgeDev 為我們提供援助。
– Gaurav Seth, Principal PM Lead, Chakra