国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

WebAssembly 系列(五)為什么 WebAssembly 更快?

劉德剛 / 2071人閱讀

摘要:圖表中的比例并不代表真實情況下的確切比例情況。解析當到達瀏覽器時,源代碼就被解析成了抽象語法樹。解析過后抽象語法樹就變成了中間代碼叫做字節碼,提供給引擎編譯。目前為止,不支持垃圾回收。這就是為什么在大多數情況下,同一個任務比表現更好的原因。

作者:Lin Clark

編譯:胡子大哈

翻譯原文:http://huziketang.com/blog/posts/detail?postId=58c8b98da6d8a07e449fdd25

英文原文:What makes WebAssembly fast?

轉載請注明出處,保留原文鏈接以及作者信息

本文作者:Lin Clark
英文原文:What makes WebAssembly fast?

本文是關于 WebAssembly 系列的第五篇文章(本系列共六篇文章)。如果你沒有讀先前文章的話,建議先讀這里。如果對 WebAssembly 沒概念,建議先讀這里(中文文章)。

上一篇文章中,我介紹了如何編寫 WebAssembly 程序,也表達了我希望看到更多的開發者在自己的工程中同時使用 WebAssembly 和 JavaScript 的期許。

開發者們不必糾結于到底選擇 WebAssembly 還是 JavaScript,已經有了 JavaScript 工程的開發者們,希望能把部分 JavaScript 替換成 WebAssembly 來嘗試使用。

例如,正在開發 React 程序的團隊可以把調節器代碼(即虛擬 DOM)替換成 WebAssembly 的版本。而對于你的 web 應用的用戶來說,他們就跟以前一樣使用,不會發生任何變化,同時他們還能享受到 WebAssembly 所帶來的好處——快。

而開發者們選擇替換為 WebAssembly 的原因正是因為 WebAssembly 比較快。那么為什么它執行的快呢?我們來一起了解一下。

當前的 JavaScript 性能如何?

在我們了解 JavaScript 和 WebAssembly 的性能區別之前,需要先理解 JS 引擎的工作原理。

下面這張圖片介紹了性能使用的大概分布情況。

JS 引擎在圖中各個部分所花的時間取決于頁面所用的 JavaScript 代碼。圖表中的比例并不代表真實情況下的確切比例情況。

圖中的每一個顏色條都代表了不同的任務:

Parsing——表示把源代碼變成解釋器可以運行的代碼所花的時間;

Compiling + optimizing——表示基線編譯器和優化編譯器花的時間。一些優化編譯器的工作并不在主線程運行,不包含在這里。

Re-optimizing——當 JIT 發現優化假設錯誤,丟棄優化代碼所花的時間。包括重優化的時間、拋棄并返回到基線編譯器的時間。

Execution——執行代碼的時間

Garbage collection——垃圾回收,清理內存的時間

這里注意:這些任務并不是離散執行的,或者按固定順序依次執行的。而是交叉執行,比如正在進行解析過程時,其他一些代碼正在運行,而另一些正在編譯。

這樣的交叉執行給早期 JavaScript 帶來了很大的效率提升,早期的 JavaScript 執行類似于下圖,各個過程順序進行:

早期時,JavaScript 只有解釋器,執行起來非常慢。當引入了 JIT 后,大大提升了執行效率,縮短了執行時間。

JIT 所付出的開銷是對代碼的監視和編譯時間。JavaScript 開發者可以像以前那樣開發 JavaScript 程序,而同樣的程序,解析和編譯的時間也大大縮短。這就使得開發者們更加傾向于開發更復雜的 JavaScript 應用。

同時,這也說明了執行效率上還有很大的提升空間。

WebAssembly 對比

下面是 WebAssembly 和典型的 web 應用的近似對比圖:

各種瀏覽器處理上圖中不同的過程,有著細微的差別,我用 SpiderMonkey 作為模型來講解不同的階段:

文件獲取

這一步并沒有顯示在圖表中,但是這看似簡單地從服務器獲取文件這個步驟,卻會花費很長時間。

WebAssembly 比 JavaScript 的壓縮率更高,所以文件獲取也更快。即便通過壓縮算法可以顯著地減小 JavaScript 的包大小,但是壓縮后的 WebAssembly 的二進制代碼依然更小。

這就是說在服務器和客戶端之間傳輸文件更快,尤其在網絡不好的情況下。

解析

當到達瀏覽器時,JavaScript 源代碼就被解析成了抽象語法樹。

瀏覽器采用懶加載的方式進行,只解析真正需要的部分,而對于瀏覽器暫時不需要的函數只保留它的樁。

解析過后 AST (抽象語法樹)就變成了中間代碼(叫做字節碼),提供給 JS 引擎編譯。

而 WebAssembly 則不需要這種轉換,因為它本身就是中間代碼。它要做的只是解碼并且檢查確認代碼沒有錯誤就可以了。

編譯和優化

上一篇關于 JIT 的文章中,我有介紹過,JavaScript 是在代碼的執行階段編譯的。因為它是弱類型語言,當變量類型發生變化時,同樣的代碼會被編譯成不同版本。

不同瀏覽器處理 WebAssembly 的編譯過程也不同,有些瀏覽器只對 WebAssembly 做基線編譯,而另一些瀏覽器用 JIT 來編譯。

不論哪種方式,WebAssembly 都更貼近機器碼,所以它更快,使它更快的原因有幾個:

在編譯優化代碼之前,它不需要提前運行代碼以知道變量都是什么類型。

編譯器不需要對同樣的代碼做不同版本的編譯。

很多優化在 LLVM 階段就已經做完了,所以在編譯和優化的時候沒有太多的優化需要做。

重優化

有些情況下,JIT 會反復地進行“拋棄優化代碼<->重優化”過程。

當 JIT 在優化假設階段做的假設,執行階段發現是不正確的時候,就會發生這種情況。比如當循環中發現本次循環所使用的變量類型和上次循環的類型不一樣,或者原型鏈中插入了新的函數,都會使 JIT 拋棄已優化的代碼。

反優化過程有兩部分開銷。第一,需要花時間丟掉已優化的代碼并且回到基線版本。第二,如果函數依舊頻繁被調用,JIT 可能會再次把它發送到優化編譯器,又做一次優化編譯,這是在做無用功。

在 WebAssembly 中,類型都是確定了的,所以 JIT 不需要根據變量的類型做優化假設。也就是說 WebAssembly 沒有重優化階段。

執行

自己也可以寫出執行效率很高的 JavaScript 代碼。你需要了解 JIT 的優化機制,例如你要知道什么樣的代碼編譯器會對其進行特殊處理(JIT 文章里面有提到過)。

然而大多數的開發者是不知道 JIT 內部的實現機制的。即使開發者知道 JIT 的內部機制,也很難寫出符合 JIT 標準的代碼,因為人們通常為了代碼可讀性更好而使用的編碼模式,恰恰不合適編譯器對代碼的優化。

加之 JIT 會針對不同的瀏覽器做不同的優化,所以對于一個瀏覽器優化的比較好,很可能在另外一個瀏覽器上執行效率就比較差。

正是因為這樣,執行 WebAssembly 通常會比較快,很多 JIT 為 JavaScript 所做的優化在 WebAssembly 并不需要。另外,WebAssembly 就是為了編譯器而設計的,開發人員不直接對其進行編程,這樣就使得 WebAssembly 專注于提供更加理想的指令(執行效率更高的指令)給機器就好了。

執行效率方面,不同的代碼功能有不同的效果,一般來講執行效率會提高 10% - 800%。

垃圾回收

JavaScript 中,開發者不需要手動清理內存中不用的變量。JS 引擎會自動地做這件事情,這個過程叫做垃圾回收。

可是,當你想要實現性能可控,垃圾回收可能就是個問題了。垃圾回收器會自動開始,這是不受你控制的,所以很有可能它會在一個不合適的時機啟動。目前的大多數瀏覽器已經能給垃圾回收安排一個合理的啟動時間,不過這還是會增加代碼執行的開銷。

目前為止,WebAssembly 不支持垃圾回收。內存操作都是手動控制的(像 C、C++一樣)。這對于開發者來講確實增加了些開發成本,不過這也使代碼的執行效率更高。

總結

WebAssembly 比 JavaScript 執行更快是因為:

文件抓取階段,WebAssembly 比 JavaScript 抓取文件更快。即使 JavaScript 進行了壓縮,WebAssembly 文件的體積也比 JavaScript 更小;

解析階段,WebAssembly 的解碼時間比 JavaScript 的解析時間更短;

編譯和優化階段,WebAssembly 更具優勢,因為 WebAssembly 的代碼更接近機器碼,而 JavaScript 要先通過服務器端進行代碼優化。

重優化階段,WebAssembly 不會發生重優化現象。而 JS 引擎的優化假設則可能會發生“拋棄優化代碼<->重優化”現象。

執行階段,WebAssembly 更快是因為開發人員不需要懂太多的編譯器技巧,而這在 JavaScript 中是需要的。WebAssembly 代碼也更適合生成機器執行效率更高的指令。

垃圾回收階段,WebAssembly 垃圾回收都是手動控制的,效率比自動回收更高。

這就是為什么在大多數情況下,同一個任務 WebAssembly 比 JavaScript 表現更好的原因。

但是,還有一些情況 WebAssembly 表現的會不如預期;同時 WebAssembly 的未來也會朝著使 WebAssembly 執行效率更高的方向發展。這些我會在下一篇文章《WebAssembly 系列(六)WebAssembly 的現在與未來》中介紹。

我最近正在寫一本《React.js 小書》,對 React.js 感興趣的童鞋,歡迎指點。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81996.html

相關文章

  • WebAssembly 系列(一)生動形象地介紹 WebAssembly

    摘要:但是為什么執行的更快呢在這個系列文章中,我會為你解釋這一點。所以當人們說更快的時候,一般來講是與相比而言的。被人們廣為傳播的性能大戰在年打響。性能的提升使得的應用范圍得到很大的擴展。現在通過,我們很有可能正處于第二個拐點。 作者:Lin Clark 編譯:胡子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=58ce8036...

    wangbjun 評論0 收藏0
  • WebAssembly 什么比 asm.js 快?

    摘要:并且于年月日,四個主要的瀏覽器一致同意宣布的版本已經完成,即將推出一個瀏覽器可以搭載的穩定版本。因此本文著重介紹為什么比更快。本文主要表達的是為什么應該是更快的。則不同,它是由幾大主要的瀏覽器廠商共同設計的。 作者:Alon Zakai 編譯:胡子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=58ce80d2a6d8a0...

    Binguner 評論0 收藏0
  • 圖說 WebAssembly):高性能原因

    摘要:本文是圖說系列文章的第五篇。這樣的話,使用的開發者也不需要做任何適配,但是它們卻能獲得更高性能。該圖并不是用來準確的衡量其性能的。運行編寫出高性能的代碼是可能的。這種清理工作由引擎自動進行,稱為垃圾回收。 本文是圖說 WebAssembly 系列文章的第五篇。如果您還未閱讀之前的文章,建議您從第一篇入手。 在上一篇文章中,我們說到了使用 WebAssembly 和 JavaScript...

    seal_de 評論0 收藏0
  • WebAssembly 系列(六)WebAssembly 的現在與未來

    摘要:目前正在開發兩個編譯器系統。這就意味著有很多功能還在襁褓之中,沒有經過徹底思考以及實際驗證。這些特性叫做未來特性。實現這一功能將會使用中的,而這一功能的實現將會提高程序執行的效率。目前瀏覽器在逐漸支持用標記來加載模塊。 作者:Lin Clark 編譯:胡子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=58ce7fd3a6...

    mcterry 評論0 收藏0
  • WebAssembly 系列(四)WebAssembly 工作原理

    摘要:但是它們其實并不是二選一的關系并不是只能用或者。正因為如此,指令有時也被稱為虛擬指令。這是因為是采用基于棧的虛擬機的機制。聲明模塊的全局變量。。下文預告現在你已經了解了模塊的工作原理,下面將會介紹為什么運行的更快。 作者:Lin Clark 編譯:胡子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=58c77641a6d8...

    stormzhang 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<