1. 先profile,找bottle neck,再动手
2. 使用 local
for i = 1, 1000000 do
local x = math.sin(i)
end
local sin = math.sin -- faster way
for i = 1, 1000000 do
local x = sin(i)
end
3. 关于 table
lua 的 table 包含了 array, map 两种语义。我不认为这是个好的设计。
empty table 一开始包含了 0 size array 和 0 size map,所以:
for i = 1, 10000000 do
local a = {}
a[1] = 1; a[2] = 2; a[3] = 3
end
for i = 1, 10000000 do
local a = {true, true, true} -- 一开始初始化了 array size,比上面快
a[1] = 1; a[2] = 2; a[3] = 3
end
并且,只有在插入新元素的时,才可能重新计算 size。所以:
a = {}
lim = 10000000
for i = 1, lim do a[i] = i end
for i = 1, lim do a[i] = nil end -- 此时,a 内部的 size 还是很大的,并没有 shrink。
4. 关于 string
lua 对于同一份 string,只保存了一份 copy。所以变量对其都是 ref。所以在 s = a + b 的时候,其实是在创建新的 string,所以速度比较慢。大量字符串合并,推荐如下方式:
a = {}
a[1] = "abc"
a[2] = "bbb"
a[3] = "qqq"
table.concat(a, ",")
5. reuse
不要每次生成新的 table,尽量 reuse。
function foo (...)
for i = 1, n do
local t = { 1, 2, 3 }
-- use t
end
end
local t = { 1, 2, 3 } -- faster, only create once
function foo (...)
for i = 1, n do
-- use t
end
end
-----------------------------
local t = {}
for i = 1970, 2000 do
t[i] = os.time({year = 1, month = 6, day = 14})
end
local t = {}
local aux = {year = nil, month = 6, day = 14)
for i = 1970, 2000 do
aux.year = i
t[i] = os.time(aux)
end
-----------------------------
文中还提到个更绝的,reuse coroutine。
co = corutine.create(function (f)
while f do
f = coroutine.yield(f())
end
end)
co(function foo (...) do ... end)
co(function bar (...) do ... end)
6. LuaJIT
评论