什麼是JIT
JIT = Just In Time即時編譯,是動態編譯的一種形式,是一種優化虛擬機運行的技術。
程序運行一般有兩種方式,一種是靜態編譯,一種是動態解釋,即時編譯混合了這兩者。Java和.Net/mono中都使用了這種技術。
然而IOS中禁止使用(不是針對JIT,而是全部的動態編譯都不支持)!php
解釋執行:緩存
效率低。
代碼暴露。安全
靜態編譯:jvm
不夠靈活,沒法熱更新。
平臺兼容性差。函數
JIT:優化
效率:高於解釋執行,低於靜態編譯。ui
安全性:通常都會先轉換成字節碼。編碼
熱更新:不管源碼仍是字節碼本質上都是資源文件。lua
兼容性:虛擬機會處理平臺差別,對用戶透明。命令行
JIT是如何實現的
這裏講的其實是JIT的一個變種:自適應動態編譯(adaptive dynamic compilation)。它分爲兩種:Method JIT和Trace JIT。
如圖所示,這是jvmjit的流程:
簡單來說:
跟蹤熱點函數或trace,編譯成機器碼執行,並緩存起來供之後使用。
非熱點函數解釋執行。
爲何只編譯熱點函數?
對只執行一次的代碼而言,解釋執行其實老是比JIT編譯執行要快。對這些代碼作JIT編譯再執行,能夠說是得不償失。而對只執行少許次數的代碼,JIT編譯帶來的執行速度的提高也未必能抵消掉最初編譯帶來的開銷。只有對頻繁執行的代碼,JIT編譯才能保證有正面的收益。
vs. Lua
Lua主要由如下三部分組成:
LuaJIT主要由如下四部分組成:
注:最新luajit對應lua5.1.5。
與jvmjit大體相同。
所謂trace即是一段線性的字節碼序列。熱點trace被編譯成機器碼,非熱點trace解釋執行。
注:並非全部的代碼都能被JIT。(NYI)
bytecode基本上能夠認爲是虛擬機的指令碼(「基本上」是由於luajit使用了uleb128)。
優勢:
編譯步驟分三步走:
minilua:其實是lua原生代碼的一個子集,用來執行lua腳本並生成平臺相關的指令。
buildvm:用來生成操做碼/庫函數到彙編/C語言的映射,用來jit編譯。
lib
exec:能夠執行lua代碼活轉換字節碼。
命令行執行
luajit –b <in> <out>。
虛擬機會判斷是不是字節碼,因此無需作額外的操做。
另外,能夠混用,即:一部分文件編成字節碼,另外一部分保持源代碼。
iSO64位報錯問題Cannot load incompatible bytecode! 這個錯是由於在luajit裏使用gcr用來比較對象指針,在64位環境下只有47位有效值(默認用戶內存不會超過128T)。其他17位中有4位保存對象類型,即一段內存中保存了兩條信息。因此在函數棧操做中有些地方須要一個空值佔位。由於字節碼直接反映了函數棧操做,因此64位和32位字節碼不一樣。