美文网首页
编写高性能的Lua代码

编写高性能的Lua代码

作者: IvanRunning | 来源:发表于2016-12-16 21:05 被阅读89次

    只要实战不说废话

    变量

    因为 Lua 的寄存器很多,预编译时便能将所有的局部变量存到寄存器中。所以,在 Lua 中访问局部变量是很快的。所以解决Lua性能问题,最重要的是用 local 去修饰变量。不使用 local 修饰的变量都是全局变量,在查询局部变量的时候要去全局表 _G 中查询,很耗时间。

    除了这个明显的地方,另有几处也可使用局部变量,可以助你挤出更多的性能。比如,如果在很长的循环里调用函数,可以先将这个函数赋值给一个局部变量。这个代码:

    for i = 1, 1000000 do  
      local x = math.sin(i)
    end
    

    下面的方法比上面的方法快30%

    local sin = math.sin
    for i = 1, 1000000 do
      local x = sin(i)
    end
    

    访问外层局部变量(也就是外一层函数的局部变量 up Value)并没有访问局部变量快,但是仍然比访问全局变量快。访问速度是这样的:first Value > up Value > global
    考虑如下代码:

    function foo(x)  
      for i = 1, 1000000 do   
        x = x + math.sin(i) 
      end
      return x
    end
    

    我们可以通过在 foo函数外面定义一个 sin来优化它:(local sin 就相当于 function fooup Value)

    local sin = math.sin
    function foo(x)  
      for i = 1, 1000000 do   
         x = x + sin(i) 
      end 
      return x
    end
    print(foo(10))
    

    当 Lua 想在表中插入一个新的键值而哈希数组已满时,Lua 会做一次重新哈希(rehash),我们以往写程序的习惯是这么初始化表 a = {} 这个时候 Lua 是没有给 table 分配空间的。如果是下面的代码会发生什么:

    local a = {}
    for i =1, 3 do
      a[i] = true
    end
    

    这段代码触发了两次 rehash (一次分配2的指数值大小),如果是处理一个大数据,需要几万次的循环,可想而知 rehash 的次数将非常大,所以这样大大浪费了空间和性能。以后初始化表的时候如果如果知道表中有固定的值了,就直接构造进去。比如:
    a = {true, true, true}

    for i = 1, 1000000 do
      local a = {}
      a [1] = 1; a[2] = 2; a[3] = 3
    end
    

    这段代码运行了2.0s

    其他

    可以把不变的操作放在循环外

    function foo (...) 
     for i = 1, n do   
       local t = {1, 2, 3, "hi"}    
       -- 做一些不改变 t 的操作   
       ... 
     end
    end
    
    local t = {1, 2, 3, "hi"} -- 一次性地创建 t
    function foo (...)  
      for i = 1, n do    
        -- 做一些不改变 t 的操作   
         ... 
      end
    end
    

    很多字符串的处理,都可以通过在现有字符串上使用下标,来避免创建不必要的新字符串。例如,函数 string.find返回的是给定模式出现的位置,而不是一个与之匹配的字符串。返回下标,就避免了在成功匹配时创建一个新的子字符串。若有需要,可以再通过函数 string.sub 来获取匹配的子字符串。

    相关文章

      网友评论

          本文标题:编写高性能的Lua代码

          本文链接:https://www.haomeiwen.com/subject/yztomttx.html