abaojin 开发工程师

lua 性能分析

2020-03-09
lua

简介

lua作为一种脚本语言,主要的用途有两个方面,一方面是作为项目或应用的配置脚本使用,另一方面 作为应用的逻辑编写脚本使用,作为逻辑编写脚本主要提交游戏方便,今天主要讨论lua编写时的一些 影响性能的注意事项,希望对于热爱lua这门脚本语言的同学以启发。

测试函数

为了进行性能,这里给出一个简单性能测试通用函数,下面的测试都将使用这个函数进行测试,废话不 多说,直接贴上代码。

function profiler(func, count)
    if type(func) ~= "function" then
        return
    end
    
    if count == nil then
        count = 100
    end

    local total_time = 0
    for i = 1, count do
        local startTime = os.clock()
        func()
        local endTime = os.clock()
        total_time = total_time + (endTime - startTime)
    end

    local average_time = total_time / count

    print("function run times=" .. count .. ",average cost time=".. average_time)
end

lua表性能

table是Lua 的一种数据结构用来帮助我们创建不同的数据类型,如:数组、字典等。 下面给出两种方式看看性能数据

  • 第一种方式
function func_table_1(c)
    for i = 1, c do
        local t = {}
        t[1] = 1
        t[2] = 2
        t[3] = 3
    end
end

profiler(function()
    func_table_1(100000)
end)

测试结果: function run times=100,average cost time=0.0631
  • 第二种方式
function func_table_2(c)
    for i = 1, c do
        local t = {0, 0, 0}
        t[1] = 1
        t[2] = 2
        t[3] = 3
    end
end

profiler(function()
    func_table_2(100000)
end)

测试结果: function run times=100,average cost time=0.0279

上面两份测试结果可以看出第二种方式速度差不多是第一种的3倍,主要原因是: 默认创建出来的的表,都是空的,在插入元素的过程,逐渐翻倍扩大,从0到1, 1到2,2到4,…都会触发realloc,同时把旧元素拷贝到新申请的空间中,对于最终有成千上万个元素的table,扩张的开销可以接受,但是对于大量生成小的table的场景,会明显拖慢性能,可以通过lua的构造函数,让Lua的编译器预分配空间,Hash的扩展也是同样的原理。

全局和局部变量性能

全局变量和局部变量是编写代码时时刻需要涉及的,但是什么时候使用全局,什么时候使用局部,这些都是非常影响代码运行效率,先分析两种方式,看看性能结果。

  • 第一种方式
function func_var_1(c)
    r = 0
    for i = 1, c do
        r = r + i
        math.type(i)
    end
end

profiler(function()
    func_var_1(1000000)
end)

测试结果:function run times=100,average cost 0.06832
  • 第二种方式
function func_var_2(c)
    local r = 0
    local t = math.type
    for i = 1, c do
        r = r + i
        t(i)
    end
end

profiler(function()
    func_var_2(1000000)
end)

测试结果:function run times=100,average cost time=0.03914

上面测试结果可以看出第二种方式也是第一种方式的2倍效率,其中原因主要是因为 全局变量涉及的到表的查询和修改,所以性能要显著差于local变量,对于函数也是 相同的道理。

垃圾回收性能

lua5.0之后采用是3色标记的GC回收算法,相比较5.0的双色标记算法的有点是算法 可以分布进行计算,避免阻塞影响逻辑脚本性能,具体实现和影响性能测试改天单 独写一篇文章讲解,今天简单说如何避免GC的开销。

  • 减少创建对象的次数,如果有需要可以循环利用
  • 根据实际业务的需要,控制垃圾回收的启动和关闭

参考资料

lua源码


Similar Posts

下一篇 lua 编码规范

评论