Lua Unpack 效能評比

在使用 lua 的 unpack 語法一定要特別注意,如果已經知道參數的數量,那會強烈建議不要使用 unpack。

測試條件

  • 迴圈執行次數 一百萬
  • table 長度 5

選手一 unpack

1
2
3
4
5
local style1 = function()
for i=1, loopCount do
local v1,v2,v3,v4,v5 = table.unpack(table_a)
end
end

選手二 get value directly

1
2
3
4
5
6
7
8
9
local style2 = function()
for i=1, loopCount do
local v1 = table_a[1]
local v2 = table_a[2]
local v3 = table_a[3]
local v4 = table_a[4]
local v5 = table_a[5]
end
end

結果

1
2
elapsed: 75.28 ms  // style1: unpack
elapsed: 0.40 ms // style2

結論

如果已經確定知道長度,還是不要使用 unpack 語法,可以看到效率是差到百倍以上。

有的人想到可以使用 # 來取得長度,是也是沒錯,但是要確保丟入參數沒有 nil,不然會算錯。

演示: length of table

準備了一組含有 nil 的測試資料…

1
2
3
4
5
6
7
8
testTable = {
{'value1'}, {'value1', 2}, {'value1', nil}, {'value1', nil, 3}, {nil},
{1}, {1,2}, {1,2,nil}
}

for i=1, #testTable do
print(string.format('%d: %d', i, #testTable[i]))
end

結果:

1
2
3
4
5
6
7
8
1: 1
2: 2
3: 1 //{'value1', nil}
4: 1 //{'value1', nil, 3}
5: 0
6: 1
7: 2
8: 2 // {1,2,nil}

從結果來看,如果不能保證沒有 nil,就還是盡量避免使用 # 取得長度。
*還是有方法可以算出正確的長度,但效能上不見得值得

完整 Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
loopCount = 1000000 --100萬
table_a = {'value1','value2','value3','value4','value5'}
require "socket"

local style1 = function()
for i=1, loopCount do
local v1,v2,v3,v4,v5 = table.unpack(table_a)
end
end

local style2 = function()
for i=1, loopCount do
local v1 = table_a[1]
local v2 = table_a[2]
local v3 = table_a[3]
local v4 = table_a[4]
local v5 = table_a[5]
end
end

local measureTimeFunction = function(func)
clock_x = socket.gettime()
func()
print(string.format('elapsed: %.2f ms', (socket.gettime() - clock_x)*1000 ))
end

measureTimeFunction(style1)
measureTimeFunction(style2)

testTable = {
{'value1'}, {'value1', 2}, {'value1', nil}, {'value1', nil, 3}, {nil},
{1}, {1,2}, {1,2,nil}
}

for i=1, #testTable do
print(string.format('%d: %d', i, #testTable[i]))
end
  • 作者: MingYi Chou
  • 版權聲明: 轉載不用問,但請註明出處!本網誌均採用 BY-NC-SA 許可協議。