lua的性能优化

  1. 云栖社区>
  2. 博客>
  3. 正文

lua的性能优化

meteoric 2017-12-07 20:33:00 浏览975
展开阅读全文

Roberto Ierusalimschy写过经典的Lua 性能提示的文章,链接地址>>

我通过实际的代码来验证,发现一个问题。当我使用 LuaStudio 运行时,发现结果反而与提示相反,甚是奇怪,而使用luac进行运行,与作者给予的提示相符,在某些地方性能可能有优化,比如读取35kb的文件时,时间还是比较快的(可能5.1版本做过优化了)。

 

日常的Lua编码中,需要注意以下几点:

1)多使用local

print(_VERSION)

local startTime, endTime


startTime = os.clock()

for i = 1, 100 * 10000 do
    local x = math.sin(i)
end

endTime = os.clock()

print("[local] used time " .. (endTime - startTime) * 1000 .. " ms")



startTime = os.clock()

local sin = math.sin
for i = 1, 100 * 10000 do
    local x = sin(i)
end

endTime = os.clock()

print("[local] used time " .. (endTime - startTime) * 1000 .. " ms")

image

上面二段代码,唯一的区别就是使用 local sin 将 math.sin缓存起来。性能提升约 (107 - 74) / 107 ~= 30.8%,基本符合作者所说的30%的效率提升。

 

startTime = os.clock()
function foo(x)
    for i = 1, 100 * 10000 do
        x = x + math.sin(i)
    end
    return x
end

foo(10)

endTime = os.clock()

print("[foo] used time " .. (endTime - startTime) * 1000 .. " ms")


startTime = os.clock()
function foo2(x)
    local sin = math.sin
    for i = 1, 100 * 10000 do
        x = x + sin(i)
    end
    return x
end

foo2(10)

endTime = os.clock()

print("[foo2] used time " .. (endTime - startTime) * 1000 .. " ms")

image

提升的时间是 (125 – 88) /125 = 29.6%,也约为30%(需要多次测试取平均值)

 

使用闭包,避免动态编译。

startTime = os.clock()
local lim = 10 * 10000
local a = {}
for i = 1, lim do
    a[i] = loadstring(string.format("return %d", i))
end

print(a[10]())

endTime = os.clock()

print("used time " .. (endTime - startTime) * 1000 .. " ms")




startTime = os.clock()
function fk(k)
    return function() return k end
end

local lim = 10 * 10000
local a = {}
for i = 1, lim do
    a[i] = fk(i)
end
endTime = os.clock()

print("used time " .. (endTime - startTime) * 1000 .. " ms")

image

节省了约92%的时间,差异距大。

 

2) 字符串拼接,尽可能使用 table 替代

startTime = os.clock()

local buff = ""
for line in io.lines("C:/Users/zhangyi/Desktop/xxx.txt") do
    buff = buff .. line .. "\n"    
end

endTime = os.clock()

print(collectgarbage("count") * 1024)

print("used time " .. (endTime - startTime) * 1000 .. " ms")




startTime = os.clock()

local buff = ""
local tbl = {}
for line in io.lines("C:/Users/zhangyi/Desktop/xxx.txt") do
    table.insert(tbl, line)
end

buff = table.concat(table, "\n")

endTime = os.clock()

print(collectgarbage("count") * 1024)

print("used time " .. (endTime - startTime) * 1000 .. " ms")

image

差异非常大,无论是内存还是时间,主要原因是:Lua中字符串的拼接都是新创建一个新的字符串,有一个新创建一块内存、copy字符串的动作,时间、空间上消耗都比较大。

 

3) table使用的优化

startTime = os.clock()
for i = 1, 100 * 10000 do
    local a = {}
    a[1] = 1
    a[2] = 2
    a[3] = 3
end
endTime = os.clock()

print("used time " .. (endTime - startTime) * 1000 .. " ms")


startTime = os.clock()
for i = 1, 100 * 10000 do
    local a = {true, true, true}
    a[1] = 1
    a[2] = 2
    a[3] = 3
end
endTime = os.clock()

print("used time " .. (endTime - startTime) * 1000 .. " ms")
image

时间相差一倍,也就是说如果不给{}给定初时化大小,当赋值的时候,它会申请空间来存放相应的值。

 

 

local polyline= {}

for i = 0, 100 * 10000 do
    table.insert(polyline, {x = i, y = 1})
end

print(collectgarbage("count") / 1024)

107.57151889801MB

 

local polyline= {}

for i = 0, 100 * 10000 do
    table.insert(polyline, {i, 1})
end

print(collectgarbage("count") / 1024)

77.053853034973MB

 

local polyline= {
    x = {},
    y = {}
}

for i = 0, 100 * 10000 do
    table.insert(polyline.x, i)
    table.insert(polyline.y, i)
end

print(collectgarbage("count") / 1024)

32.019150733948MB

空间占用差距也非常大,从上面似乎可以得到这样的结论:尽可能减少table的长度,尽可能使用array 而不是 hash。

 

综上所述,尽可能多使用local,减少查询的性能损耗。json数据表如果需要转化为table时,改变数据的存储结构可能减少很大的内存使用。

网友评论

登录后评论
0/500
评论
meteoric
+ 关注