前端P.04:JIT V8 外星人
🥜 前情提要:
了解JavaScript的缺陷後,我們提出三種解決方案,JIT、TypeScript、WebAssembly,今天介紹第一個 JIT
即時編譯:JIT(Just-in-time compilation) :
今天JavaScript如何在瀏覽器上工作的,在電影「降臨」中外星人降臨地球了,人類為了理解外星人為何降臨,於是雙方進行了溝通,但是很明顯外星人聽不懂我們的話,於是有了翻譯的存在,情況像是下面:
而解釋型就是執行一行翻譯一行,給你看:
而編譯型就是全部翻譯完,給你看:
綜上所述,解釋型對於頻繁執行的重複代碼有缺陷,還是會重新解釋一次,所以JIT就是解決這問題
JIT這個單字其實不是JavaScript專有 C#、Java、Python等等也皆有使用JIT,但最早使用的是在20世紀Toyota汽車工業中提出生產管理的方法學:
在20世紀後半期,整個汽車市場進入了一個市場需求多樣化的新階段,而且對質量的要求也越來越高,隨之給製造業提出的新課題即是,如何有效地組織多品種小批量生產,否則的話,生產過剩所引起的只是設備、人員、非必須費用等一系列的浪費,從而影響到企業的競爭能力以至生存。
由上述例子可以看到他們提出當時遇到的問題,以此為基礎提出了解決方法就是減少庫存進而減少儲存費用,
「讓正確的物資,在正確的時間,流動到正確的地方,數量是剛剛好的數量。」。
那麼程式語言對於當前解釋器遇到的問題引用該概念,「重複解釋相同指令」就是庫存。
JIT是混合了編譯器和解釋器這二者,一字一句編譯成原始碼,但是能夠將編譯過的代碼快取儲存以降低效能損耗(下面會詳細介紹)。相對於編譯型,JIT的代碼可以處理延遲繫結並增強安全性。
V8
那麼這樣新型態的JavaScript是如何實現在瀏覽器的呢?
假設今天我們寫的JS程式碼,寄宿在HTML網頁並丟到瀏覽器執行顯示,此時瀏覽器就會有專門處理JavaScript指令碼的虛擬機器,這種東西我們稱之為「JavaScript引擎」。
在2008年以前JavaScript引擎一直被當作一門解釋器,用於將JavaScript轉換成機器語言。
而2008年時Google提出了鼎鼎大名的V8引擎
V8的工作可不是單純的解釋器,它還要負責執行代碼、分配內存、垃圾回收、JIT等等各種技術來優化JavaScript。所以我們知道V8使用各種技術來優化JavaScript解釋器的缺陷,這邊我們舉個範例:
JIT中新增了一個監視器,這個監視器監視著程式碼的運行情況,記錄該行程式碼一共運行了多少次,如何運行的等信息。
當某一行程式碼被執行多次,監視器就會給予一個標籤 warm,JIT就會把這段代碼的編譯結果儲存下來。
當某一行程式碼被執行很多次,監視器就會給予一個標籤 hot,JIT就會把這段代碼的編譯結果進行優化。
當下次又執行到該行發現是warm為已經解釋過的程式碼時候,JIT就會把結果丟出來給你,並且說:不要再解釋了,上次解釋過了,結果長這樣。
當下次又執行到該行發現是hot為已經解釋過並且優化的程式碼時候,JIT就會把結果丟出來給你,並且說:不要再解釋了,上次解釋過了,結果長這樣。
其優化手段如下:
未優化的程式碼:
1 | class Calculator { |
針對 Class Calculator 進行第一步優化會變成:
1 | class Calculator { |
針對 Class Calculator 進行第二步優化會變成:
1 | class Calculator { |
針對 Class Calculator 進行第三步優化會變成:
1 | class Calculator { |
針對 Class Calculator 進行第四步優化會變成:
1 | class Calculator { |
runtime:
JavaScript的runtime是在腳本化語言定義中所提到的「已存在的實體或系統」。程式碼通過 JavaScript 引擎傳遞,一旦被解析和被理解之後,實體或系統將會執行解釋行為。
而對於Client端 這個存在的實體就是瀏覽器,不同瀏覽器提供各自的引擎來解析,告訴瀏覽器要執行對應的行為。然而對於Server開發者就是NodeJS了(後續會介紹)。
簡單說:JavaScript引擎、虛擬機、runtime 大部分時候三者是通用的,你可以把它當作JavaScript實作的環境,但詳細區別可以看:知乎