說明
最近在學習 LuaJIT,想看看把它接入到項目中使用,會提高多大的性能。
今天抽時間,簡單地測試了一下 LuaJIT 2.2 和 Lua5.4.8 的性能。
測試平臺:
- 系統:Windows 10 WSL
- CPU:Intel? Core? i7-8700 CPU @ 3.20GHz 3.19 GHz
- 內存:48.0 GB
下面測試結果只是我簡單測試的結果,僅供參考。
相關代碼在最后面。
綜合性能對比分析
第一組測試(詳細性能對比)
測試項目 | Lua 5.4 | LuaJIT | 性能提升 |
---|---|---|---|
Fibonacci(30) 遞歸 | 0.0515秒 | 0.0095秒 | 5.4倍 |
數學操作(10萬次) | 0.0125秒 | 0.0022秒 | 5.7倍 |
字符串操作 | 0.0033秒 | 0.0043秒 | 0.8倍 |
表操作(10萬) | 0.0797秒 | 0.0322秒 | 2.5倍 |
第二組測試(深度分析)
測試規模/類型 | Lua 5.4 | LuaJIT | 性能提升 |
---|---|---|---|
100萬次循環 | 0.0041秒 | 0.0010秒 | 4.1倍 |
500萬次循環 | 0.0204秒 | 0.0051秒 | 4.0倍 |
1000萬次循環 | 0.0407秒 | 0.0102秒 | 4.0倍 |
浮點運算(100萬) | 0.0298秒 | 0.0056秒 | 5.3倍 |
整數操作 | 0.0062秒 | 0.0010秒 | 6.2倍 |
浮點操作 | 0.0069秒 | 0.0010秒 | 6.9倍 |
順序訪問 | 0.0020秒 | 0.0006秒 | 3.3倍 |
隨機訪問 | 0.0034秒 | 0.0010秒 | 3.4倍 |
關鍵說明
1. 穩定的性能提升
LuaJIT在所有數值計算任務上都展現了4-7倍的性能提升,這個倍數很穩定,說明JIT優化效果是可預測的。
2. 規模無關的優化效果
從100萬到1000萬次循環,性能提升倍數保持在4倍左右,說明LuaJIT的優化效果不受問題規模影響。
3. 內存使用效率
- Lua 5.4: 1048.76 KB
- LuaJIT: 563.17 KB
LuaJIT使用了約**46%**更少的內存,這可能因為:
- 更高效的對象表示
- 不同的垃圾回收策略
- JIT編譯后的代碼更緊湊
4. 類型統一優化
在LuaJIT中,整數和浮點操作的性能幾乎相同(都是0.0010秒),這說明JIT編譯器成功地進行了類型特化優化。
5. 內存訪問模式優化
LuaJIT對順序訪問和隨機訪問都有顯著優化,但順序訪問的優勢更明顯。
6. JIT預熱效果
有趣的是,這次測試中JIT預熱效果不明顯(1.01倍),這可能因為:
- 測試代碼相對簡單,很快就被優化了
- 測試規模足夠大,預熱時間相對較短
相關代碼
測試1
-- detailed_comparison.lua
print("=== Detailed Performance Comparison ===")
print("Lua Version:", _VERSION)
print("Engine:", jit and jit.version or "Standard Lua Interpreter")
print()local function benchmark(name, func, ...)collectgarbage("collect")local start = os.clock()local result = func(...)local elapsed = os.clock() - startprint(string.format("%-30s: %8.4f seconds", name, elapsed))return elapsed
end-- 避免溢出的斐波那契測試
local function safe_fibonacci(n)if n <= 1 then return n endlocal a, b = 0, 1for i = 2, n doa, b = b, a + b-- 檢查是否即將溢出if b > 1e15 thenreturn b -- 提前返回避免溢出endendreturn b
end-- 不同規模的遞歸測試
local function fib_recursive(n)if n <= 1 then return n endreturn fib_recursive(n-1) + fib_recursive(n-2)
end-- 數學計算密集
local function math_intensive(n)local sum = 0for i = 1, n dosum = sum + math.sin(i) * math.cos(i) + math.sqrt(i)endreturn sum
end-- 字符串操作
local function string_operations(n)local result = ""for i = 1, n doresult = result .. tostring(i)if #result > 100000 then break end -- 避免內存問題endreturn #result
end-- table密集操作
local function table_intensive(n)local t = {}for i = 1, n dot[i] = {x = i, y = i * 2, data = "item" .. i}endlocal sum = 0for i = 1, n dosum = sum + t[i].x + t[i].yendreturn sum
endprint("Running benchmarks...")-- 適中的測試規模
benchmark("Fibonacci(30) recursive", fib_recursive, 30)
benchmark("Safe Fibonacci(100000)", safe_fibonacci, 100000)
benchmark("Math operations (100K)", math_intensive, 100000)
benchmark("String operations", string_operations, 5000)
benchmark("Table operations (100K)", table_intensive, 100000)-- 顯示內存使用
collectgarbage("collect")
print(string.format("\nMemory usage: %.2f KB", collectgarbage("count")))-- JIT特定信息
if jit thenprint("\nJIT Information:")print("Status:", jit.status())print("Architecture:", jit.arch)-- 顯示編譯的trace數量local traces = 0for i = 1, 1000 doif jit.util and jit.util.traceinfo and jit.util.traceinfo(i) thentraces = traces + 1endendif traces > 0 thenprint("Compiled traces:", traces)end
end
測試代碼2:
-- deep_analysis.lua
print("=== Deep Performance Analysis ===")
print("Engine:", jit and jit.version or ("Standard " .. _VERSION))
print()local function benchmark_with_analysis(name, func, iterations, ...)-- 預熱運行func(...)-- 多次測試求平均值local times = {}for i = 1, iterations docollectgarbage("collect")local start = os.clock()local result = func(...)local elapsed = os.clock() - starttimes[i] = elapsedend-- 計算統計信息local total = 0local min_time = times[1]local max_time = times[1]for i = 1, iterations dototal = total + times[i]if times[i] < min_time then min_time = times[i] endif times[i] > max_time then max_time = times[i] endendlocal avg_time = total / iterationsprint(string.format("%-25s: avg=%.4fs, min=%.4fs, max=%.4fs", name, avg_time, min_time, max_time))return avg_time
end-- 不同規模的循環測試
local function loop_test(n)local sum = 0for i = 1, n dosum = sum + iendreturn sum
end-- 浮點數密集計算
local function float_intensive(n)local x = 1.0for i = 1, n dox = x * 1.000001x = math.sqrt(x)endreturn x
end-- 整數vs浮點數操作
local function integer_ops(n)local sum = 0for i = 1, n dosum = sum + (i * 2) -- 整數運算endreturn sum
endlocal function float_ops(n)local sum = 0.0for i = 1, n dosum = sum + (i * 2.0) -- 浮點運算endreturn sum
end-- 表訪問模式測試
local function sequential_access(n)local t = {}for i = 1, n dot[i] = iendlocal sum = 0for i = 1, n dosum = sum + t[i]endreturn sum
endlocal function random_access(n)local t = {}for i = 1, n dot[i] = iendlocal sum = 0for i = 1, n dolocal idx = (i * 17 + 31) % n + 1 -- 偽隨機訪問sum = sum + t[idx]endreturn sum
endprint("Multiple runs for statistical accuracy:")
print()-- 不同規模的測試
local sizes = {1000000, 5000000, 10000000}
for _, size in ipairs(sizes) doprint(string.format("=== Scale: %d operations ===", size))benchmark_with_analysis("Loop " .. size, loop_test, 3, size)if size <= 1000000 then -- 避免浮點運算太慢benchmark_with_analysis("Float " .. size, float_intensive, 3, size)endprint()
endprint("=== Data Type Comparison ===")
benchmark_with_analysis("Integer operations", integer_ops, 5, 1000000)
benchmark_with_analysis("Float operations", float_ops, 5, 1000000)
print()print("=== Memory Access Patterns ===")
benchmark_with_analysis("Sequential access", sequential_access, 3, 100000)
benchmark_with_analysis("Random access", random_access, 3, 100000)
print()-- JIT特定分析
if jit thenprint("=== JIT Warmup Analysis ===")local function warmup_test(n)local sum = 0for i = 1, n dosum = sum + math.sin(i) * math.cos(i)endreturn sumend-- 冷啟動local start = os.clock()warmup_test(100000)local cold_time = os.clock() - start-- 預熱后local start2 = os.clock()warmup_test(100000)local warm_time = os.clock() - start2print(string.format("Cold start: %.4fs", cold_time))print(string.format("After warmup: %.4fs", warm_time))print(string.format("Warmup speedup: %.2fx", cold_time / warm_time))
end
.
.
上述測試結果只是我簡單測試的結果,僅供參考(圖片AI生成)
.
.