聊聊LuaJIT

JIT

什麼是JIT
JIT = Just In Time即時編譯,是動態編譯的一種形式,是一種優化虛擬機運行的技術。
程序運行一般有兩種方式,一種是靜態編譯,一種是動態解釋,即時編譯混合了這兩者。Java和.Net/mono中都使用了這種技術。
然而IOS中禁止使用(不是針對JIT,而是全部的動態編譯都不支持)!php

爲何要使用JIT

解釋執行:緩存

效率低。
代碼暴露。安全


靜態編譯:jvm

不夠靈活,沒法熱更新。
平臺兼容性差。函數

JIT:優化

效率:高於解釋執行,低於靜態編譯。ui

安全性:通常都會先轉換成字節碼。編碼

熱更新:不管源碼仍是字節碼本質上都是資源文件。lua

兼容性:虛擬機會處理平臺差別,對用戶透明。命令行

JIT是如何實現的
這裏講的其實是JIT的一個變種:自適應動態編譯(adaptive dynamic compilation)。它分爲兩種:Method JIT和Trace JIT。
如圖所示,這是jvmjit的流程:

簡單來說:

跟蹤熱點函數或trace,編譯成機器碼執行,並緩存起來供之後使用。
非熱點函數解釋執行。
爲何只編譯熱點函數?
對只執行一次的代碼而言,解釋執行其實老是比JIT編譯執行要快。對這些代碼作JIT編譯再執行,能夠說是得不償失。而對只執行少許次數的代碼,JIT編譯帶來的執行速度的提高也未必能抵消掉最初編譯帶來的開銷。只有對頻繁執行的代碼,JIT編譯才能保證有正面的收益。

LuaJIT

vs. Lua
Lua主要由如下三部分組成:

  1. 語法實現。
  2. 庫函數。
  3. 字節碼。

LuaJIT主要由如下四部分組成:

  1. 語法實現。
  2. Trace JIT編譯器。
  3. 庫函數。
    1. 原生庫++(強化過的原生庫)
    2. bit
    3. ffi
    4. jit
  4. 字節碼

注:最新luajit對應lua5.1.5。

trace jit編譯器

 

與jvmjit大體相同。
所謂trace即是一段線性的字節碼序列。熱點trace被編譯成機器碼,非熱點trace解釋執行。
注:並非全部的代碼都能被JIT。(NYI)

bytecode

bytecode基本上能夠認爲是虛擬機的指令碼(「基本上」是由於luajit使用了uleb128)。
優勢:

  1. 減小文件大小。
  2. 生成函數原型更快。
  3. 增長被破解的難度。
  4. 對源代碼輕微的優化。
  5. 庫函數和可執行文件

編譯步驟分三步走:

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位字節碼不一樣。

相關文章
相關標籤/搜索