https://luajit.org/install.html
LuaJIT的運行環境包括一個用手寫匯編實現的Lua解釋器和一個可以直接生成機器代碼的JIT編譯器。Lua代碼在被執行之前總是會先被lfn
生成LuaJIT自己定義的字節碼ByteCode
。
開始時Lua字節碼總是被LuaJIT的解釋器解釋執行,LuaJIT的解釋器會在執行字節碼時同時記錄一些運行時的統計信息,如每個Lua函數調用入口的實際運行次數,還有每個Lua循環的實際執行次數。當這些次數超過某個預設的閾值時,便認為對應的Lua函數入口或對應的Lua循環足夠的熱,此時便會觸發JIT編譯器開始工作。
JIT編譯器會從熱函數的入口或熱循環的某個位置開始嘗試編譯對應的Lua代碼路徑,編譯的過程是把LuaJIT字節碼先轉換成LuaJIT自己定義的中間碼(IR),然后再生成針對目標體系結構的機器碼,如x86_64指令組成的機器碼。如果當前Lua代碼路徑上的所有操作都可以被JIT編譯器順利編譯,則這條編譯過的代碼路徑便被稱為一個trace
,在物理上對應一個trace
類型的GC對象,即參與Lua GC的對象。
即時編譯器
什么是JIT(Just In Time)呢?
程序運行通常有兩種方式:靜態編譯和動態解釋,即時編譯混合了二者。即時編譯是動態編譯的一種形式,是一種優化虛擬機運行的技術。
即時編譯器會將頻繁執行的代碼編譯成機器碼緩存起來,下次調用時將直接執行機器碼。相比原生逐條執行虛擬機指令效率更高。而對於那些只執行一次的代碼仍然逐條執行。
值得注意的是,即時編譯帶來的效率提升,並不一定能抵消編譯效率的下降。因為當虛擬機執行指令時並不會立即用JIT進行編譯,由於只有部分指令需要JIT進行編譯,JIT將決定那些代碼將被編譯。而延遲編譯則有助於JIT選擇一個最佳的解決方案。
為什么要使用JIT呢?
對於靜態編譯的缺點是不夠靈活、無法支持熱更,而且平台兼容性差。而對於動態解釋而言,效率低和代碼暴露是其主要缺陷。即時編譯混合了動態解釋和靜態編譯,在執行效率上要高於解釋執行卻低於靜態編譯。安全性上一般都會將源代碼轉換成字節碼。而無論是源碼或是字節碼,本質上都是資源,因此可采用熱更新機制。在兼容性上,由於虛擬機的存在,可以處理不同平台的差異,對用戶保持透明。
JVM JIT
即使編譯可以分為2種:方法即時編譯Method JIT
和跟蹤編即時譯Trace JIT
。
以Java為例,實際上是指的是JIT的一個變種:自適應動態編譯
簡單來說可分為2個步驟
- 跟蹤熱點函數或
trace
,編譯成機器碼執行,並緩存以供下次使用。 - 非熱點函數解釋執行
那么為什么只編譯熱點函數呢?
對於只執行一次的代碼而言,解釋執行其實是比JIT編譯執行要快,對於那些代碼JIT編譯在執行反而得不償失。而對於只執行少量次數的代碼,即使編譯帶來的速度的提升也未必能抵消最初編譯帶來的開銷,只有對頻繁執行的代碼,即使編譯才能保證有正面的收益。

luajit下載源碼后
make && make install
luajit -b ./hello.lua ./hello.luajit
luajit 執行的lua文件名