Luajit 概述

整理了下luajit 相關內容,分爲了幾部分,每部分最後是參考的blog地址。有興趣的可以詳細閱讀原文。
一、JIT即時編譯器
JIT:即時編譯器。將頻繁執行的代碼,通過JIT編譯器編譯成機器碼緩存起來,下次再調用時直接執行機器碼。相比與原生Lua的逐條執行虛擬機指令效率更高。對於那些只執行一次的代碼,則保持於原生Lua一樣,逐條執行。JIT帶來的效率提升,並不一定能抵消編譯效率的下降。
當虛擬機執行指令時並不會立刻用JIT進行編譯。只有部分指令需要JIT進行編譯,JIT將決定那些代碼將被編譯。延遲編譯有助於JIT選擇一個最優的解決方案,進行決策。

二、Luajit性能優化
1.使用ffi實現數據結構,減少內存消耗,避免hash重構。
2.用ffi調用C函數,ffi中會聲明函數原型包含參數返回值的類型,jit可以直接生成機器碼,從而實現對c函數調用的無縫對接,消除了對Lua虛擬堆棧的操作。

三、Luajit 和Lua區別:
hash算法不一樣,導致表的遍歷順序不同。
Luajit中新增了一些轉義字符,並且處理轉義字符的方式也不一樣。
Luajit內存上線是4G
函數中的局部變量最大限制Luajit要小於Lua
Luajit不夠穩定,在ios上不支持JIT功能

四、Luajit API
1.ffi.new ffi.typeof :構造C數據 數據是垃圾回收的
local Num
-- 構造一個基礎類型
Num = ffi.new('int', 20)
-- 構造基礎類型數組
Num = ffi.new('int[1]',20)
-- 變長數組
Num = ffi.new('int[?]',10,2,20) -- ?是佔位符號 int[10]
-- 定義一個ctype
local CType = ffi.typeof("int") -- ffi.new('int') 等價於 ffi.new( ffi.typeof("int") )
Num = CType(10)

2.ffi.cast:lua類型轉換成CType類型
local LuaStr = "abc"
local CStr = ffi.cast("const char*",LuaStr)

3.ffi.metatype:爲c數據結構綁定元表
ffi.cdef[[
typedef struct { double x, y; } point_t;
]]

local point
local mt = {
__add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
__len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
__index = {
area = function(a) return a.x*a.x + a.y*a.y end,
},
}
point = ffi.metatype("point_t", mt)
--point = ffi.metatype("point_t", {}) -- wrong 調用了metatype後 point_t的元表不可再更改
local a = point(3, 4)
print(a.x, a.y) --> 3 4
print(#a) --> 5
print(a:area()) --> 25
local b = a + point(0.5, 8)
print(#b) --> 12.5

4.cdata = ffi.gc(cdata, finalizer):爲 cdata設置析構函數,當cdata不在被其他對象引用時觸發。

5.ffi.sizeof:返回Cdata內存大小
print( ffi.sizeof("int[?]",10) ) --> sizeof(int) * 10 = 40

6.ffi.alignof:返回內存ctype內存對齊最小字節
ffi.cdef[[
typedef struct { int y; double x; } point_t;
]]
print( ffi.alignof("point_t") )

7.ffi.offsetof:返回ctype結構體中 x字段的字節偏移量
print ( ffi.offsetof("point_t", "x") ) -->8

8.ffi.istype:判斷cdata是否是ctype類型 是返回true
local Point = ffi.new("point_t")
print ( ffi.istype("point_t", Point) ) -->true

9.str = ffi.string(ptr [,len]):ctype<const char*> 轉 lua string
local LuaStr = "abc"
local CStr = ffi.cast("const char*",LuaStr) -- lua string 轉 ctype<const char*>
LuaStr = nil
LuaStr = ffi.string(CStr) -- ctype<const char*> 轉 lua string
print(LuaStr) --> abc

五、ffi基本用法:
(1)、調用C函數(提高函數執行效率)
1.C標準庫中函數
local ffi = require("ffi")ffi.cdef[[int printf(const char *fmt, ...);]]ffi.C.printf("Hello %s!", "world")
首先 require("ffi") 加載ffi庫,然後聲明函數,最後表用函數

2.調用其他庫函數
在調用函數前先 ffi.load(庫名,[])加載庫,C標準庫是默認加載的不需要手動load。
3.調用C/C++自定義函數
在C/C++中聲明函數時 添加 extern "C" __declspec(dllexport)修飾函數。

ffi只可在lua中調用C/C++中的導出函數,也就是庫函數或extern "C" __declspec(dllexport)修飾的自定義函數。

(2)、在Lua中使用C結構體(減少內存開銷)
ffi.cdef [[
typedef struct MyStruct{char a; char b;} Point;
]]
local point = ffi.new("Point")
print(ffi.sizeof(point))
定義結構體,並不需要要在C/C++中定義,只需在Lua中定義即可。構造一個對象。print(ffi.sizeof(point)) = 2 point佔用兩個字節。

  • Lua 可以使用 ffi.new 初始化一個 cdata 對象,也可以使用 ffi.typeof 生成的類型來初始化一個 cdata 對象,在創建數組時應使用ffi.typeof 只生成一次類型重複使用這樣效率更高。
  • 對於基本類型和字符串類型,沒有必要將其轉爲 cdata 對象,其可以作爲參數傳入 C 函數中。也可以接收 C 函數的返回值
  • 對於基本類型指針對象,可以使用單元素數組進行初始化,可以使用數組元素賦值的方式改變其中的值
  • 對於結構類型,可以傳入 C 指針參數,也可以傳入 C 普通參數。對結構類型的操作,與 table 的字典操作類似








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章