精华内容
参与话题
问答
  • lua 优化

    2018-08-21 11:10:00
    彻底解析Android缓存机制——...lua:部分常用操作的效率对比及代码优化建议(附测试代码) https://blog.csdn.net/u013119612/article/details/78758253 Lua性能优化技巧 https://blog.csdn.net/summerh...

    彻底解析Android缓存机制——LruCache

    https://www.jianshu.com/p/b49a111147ee

    lua:部分常用操作的效率对比及代码优化建议(附测试代码)

    https://blog.csdn.net/u013119612/article/details/78758253

     

    Lua性能优化技巧

    https://blog.csdn.net/summerhust/article/details/18599375

    高性能 Lua 技巧(译)

    https://segmentfault.com/a/1190000004372649

    编写高性能的Lua代码

    http://wuzhiwei.net/lua_performance/

     

    Lua性能优化

    https://www.cnblogs.com/YYRise/p/7082637.html

     

    使用局部变量local

    https://www.cnblogs.com/lovevivi/p/3284643.html

     

    Lua性能优化—Lua内存优化

    https://blog.uwa4d.com/archives/usparkle_luaperformance.html

    Lua的CPU开销性能优化

    http://www.sohu.com/a/191810651_726639

    编写高效Lua代码的方法(整理)  

    https://blog.csdn.net/u013097730/article/details/52411658

     

    转载于:https://www.cnblogs.com/javalzy/p/9510231.html

    展开全文
  • lua优化

    2015-10-18 20:59:00
    前言 Lua是一门以其性能著称的脚本语言,被广泛应用在很多方面,尤其是游戏。像《魔兽世界》的插件,手机游戏《大掌门》《神曲》...所以一个好的程序员在考虑优化性能前必须问自己两个问题:“我的程序真的需要优化...

    前言

    Lua是一门以其性能著称的脚本语言,被广泛应用在很多方面,尤其是游戏。像《魔兽世界》的插件,手机游戏《大掌门》《神曲》《迷失之地》等都是用Lua来写的逻辑。

    所以大部分时候我们不需要去考虑性能问题。Knuth有句名言:“过早优化是万恶之源”。其意思就是过早优化是不必要的,会浪费大量时间,而且容易导致代码混乱。

    所以一个好的程序员在考虑优化性能前必须问自己两个问题:“我的程序真的需要优化吗?”。如果答案为是,那么再问自己:“优化哪个部分?”。

    我们不能靠臆想和凭空猜测来决定优化哪个部分,代码的运行效率必须是可测量的。我们需要借助于分析器来测定性能的瓶颈,然后着手优化。优化后,我们仍然要借助于分析器来测量所做的优化是否真的有效。

    我认为最好的方式是在首次编写的时候按照最佳实践去写出高性能的代码,而不是编写了一堆垃圾代码后,再考虑优化。相信工作后大家都会对事后的优化的繁琐都深有体会。

    一旦你决定编写高性能的Lua代码,下文将会指出在Lua中哪些代码是可以优化的,哪些代码会是运行缓慢的,然后怎么去优化它们。

    使用local

    在代码运行前,Lua会把源码预编译成一种中间码,类似于Java的虚拟机。这种格式然后会通过C的解释器进行解释,整个过程其实就是通过一个while循环,里面有很多的switch...case语句,一个case对应一条指令来解析。

    自Lua 5.0之后,Lua采用了一种类似于寄存器的虚拟机模式。Lua用来储存其寄存器。每一个活动的函数,Lua都会其分配一个栈,这个栈用来储存函数里的活动记录。每一个函数的栈都可以储存至多250个寄存器,因为栈的长度是用8个比特表示的。

    有了这么多的寄存器,Lua的预编译器能把所有的local变量储存在其中。这就使得Lua在获取local变量时其效率十分的高。

    举个栗子: 假设a和b为local变量,a = a + b的预编译会产生一条指令:

    1
    2
    ;a是寄存器0 b是寄存器1
    ADD 0 0 1
     

    但是若a和b都没有声明为local变量,则预编译会产生如下指令:

     
    1
    2
    3
    4
    GETGLOBAL    0 0    ;get a
    GETGLOBAL    1 1    ;get b
    ADD          0 0 1  ;do add
    SETGLOBAL    0 0    ;set a
     

    所以你懂的:在写Lua代码时,你应该尽量使用local变量

    以下是几个对比测试,你可以复制代码到你的编辑器中,进行测试。

    1
    2
    3
    4
    5
    6
    a = os.clock()
    for i = 1,10000000 do
      local x = math.sin(i)
    end
    b = os.clock()
    print(b-a) -- 1.113454

    math.sin赋给local变量sin

     
    1
    2
    3
    4
    5
    6
    7
    a = os.clock()
    local sin = math.sin
    for i = 1,10000000 do
      local x = sin(i)
    end
    b = os.clock()
    print(b-a) --0.75951
     

    直接使用math.sin,耗时1.11秒;使用local变量sin来保存math.sin,耗时0.76秒。可以获得30%的效率提升!

    关于表(table)

    表在Lua中使用十分频繁,因为表几乎代替了Lua的所有容器。所以快速了解一下Lua底层是如何实现表,对我们编写Lua代码是有好处的。

    Lua的表分为两个部分:数组(array)部分和哈希(hash)部分。数组部分包含所有从1到n的整数键,其他的所有键都储存在哈希部分中。

    哈希部分其实就是一个哈希表,哈希表本质是一个数组,它利用哈希算法将键转化为数组下标,若下标有冲突(即同一个下标对应了两个不同的键),则它会将冲突的下标上创建一个链表,将不同的键串在这个链表上,这种解决冲突的方法叫做:链地址法。

    当我们把一个新键值赋给表时,若数组和哈希表已经满了,则会触发一个再哈希(rehash)。再哈希的代价是高昂的。首先会在内存中分配一个新的长度的数组,然后将所有记录再全部哈希一遍,将原来的记录转移到新数组中。新哈希表的长度是最接近于所有元素数目的2的乘方。

    当创建一个空表时,数组和哈希部分的长度都将初始化为0,即不会为它们初始化任何数组。让我们来看下执行下面这段代码时在Lua中发生了什么:

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

    最开始,Lua创建了一个空表a,在第一次迭代中,a[1] = true触发了一次rehash,Lua将数组部分的长度设置为2^0,即1,哈希部分仍为空。在第二次迭代中,a[2] = true再次触发了rehash,将数组部分长度设为2^1,即2。最后一次迭代,又触发了一次rehash,将数组部分长度设为2^2,即4。

    下面这段代码:

    1
    2
    a = {}
    a.x = 1; a.y = 2; a.z = 3

    与上一段代码类似,只是其触发了三次表中哈希部分的rehash而已。

    只有三个元素的表,会执行三次rehash;然而有一百万个元素的表仅仅只会执行20次rehash而已,因为2^20 = 1048576 > 1000000。但是,如果你创建了非常多的长度很小的表(比如坐标点:point = {x=0,y=0}),这可能会造成巨大的影响。

    如果你有很多非常多的很小的表需要创建时,你可以将其预先填充以避免rehash。比如:{true,true,true},Lua知道这个表有三个元素,所以Lua直接创建了三个元素长度的数组。类似的,{x=1, y=2, z=3},Lua会在其哈希部分中创建长度为4的数组。

    以下代码执行时间为1.53秒:

    1
    2
    3
    4
    5
    6
    7
    a = os.clock()
    for i = 1,2000000 do
        local a = {}
        a[1] = 1; a[2] = 2; a[3] = 3
    end
    b = os.clock()
    print(b-a)  --1.528293

    如果我们在创建表的时候就填充好它的大小,则只需要0.75秒,一倍的效率提升!

    1
    2
    3
    4
    5
    6
    7
    a = os.clock()
    for i = 1,2000000 do
        local a = {1,1,1}
        a[1] = 1; a[2] = 2; a[3] = 3
    end
    b = os.clock()
    print(b-a)  --0.746453

    所以,当需要创建非常多的小size的表时,应预先填充好表的大小

    关于字符串

    与其他主流脚本语言不同的是,Lua在实现字符串类型有两方面不同。

    第一,所有的字符串在Lua中都只储存一份拷贝。当新字符串出现时,Lua检查是否有其相同的拷贝,若没有则创建它,否则,指向这个拷贝。这可以使得字符串比较和表索引变得相当的快,因为比较字符串只需要检查引用是否一致即可;但是这也降低了创建字符串时的效率,因为Lua需要去查找比较一遍。

    第二,所有的字符串变量,只保存字符串引用,而不保存它的buffer。这使得字符串的赋值变得十分高效。例如在Perl中,$x = $y,会将$y的buffer整个的复制到$x的buffer中,当字符串很长时,这个操作的代价将十分昂贵。而在Lua,同样的赋值,只复制引用,十分的高效。

    但是只保存引用会降低在字符串连接时的速度。在Perl中,$s = $s . 'x'$s .= 'x'的效率差距惊人。前者,将会获取整个$s的拷贝,并将’x’添加到它的末尾;而后者,将直接将’x’插入到$x的buffer末尾。

    由于后者不需要进行拷贝,所以其效率和$s的长度无关,因为十分高效。

    在Lua中,并不支持第二种更快的操作。以下代码将花费6.65秒:

    1
    2
    3
    4
    5
    6
    7
    a = os.clock()
    local s = ''
    for i = 1,300000 do
        s = s .. 'a'
    end
    b = os.clock()
    print(b-a)  --6.649481

    我们可以用table来模拟buffer,下面的代码只需花费0.72秒,9倍多的效率提升:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    a = os.clock()
    local s = ''
    local t = {}
    for i = 1,300000 do
        t[#t + 1] = 'a'
    end
    s = table.concat( t, '')
    b = os.clock()
    print(b-a)  --0.07178

    所以:在大字符串连接中,我们应避免..。应用table来模拟buffer,然后concat得到最终字符串

    3R原则

    3R原则(the rules of 3R)是:减量化(reducing),再利用(reusing)和再循环(recycling)三种原则的简称。

    3R原则本是循环经济和环保的原则,但是其同样适用于Lua。

    Reducing

    有许多办法能够避免创建新对象和节约内存。例如:如果你的程序中使用了太多的表,你可以考虑换一种数据结构来表示。

    举个栗子。 假设你的程序中有多边形这个类型,你用一个表来储存多边形的顶点:

    1
    2
    3
    4
    5
    6
    polyline = {
        { x = 1.1, y = 2.9 },
        { x = 1.1, y = 3.7 },
        { x = 4.6, y = 5.2 },
        ...
    }

    以上的数据结构十分自然,便于理解。但是每一个顶点都需要一个哈希部分来储存。如果放置在数组部分中,则会减少内存的占用:

    1
    2
    3
    4
    5
    6
    polyline = {
        { 1.1, 2.9 },
        { 1.1, 3.7 },
        { 4.6, 5.2 },
        ...
    }

    一百万个顶点时,内存将会由153.3MB减少到107.6MB,但是代价是代码的可读性降低了。

    最变态的方法是:

    1
    2
    3
    4
    polyline = {
        x = {1.1, 1.1, 4.6, ...},
        y = {2.9, 3.7, 5.2, ...}
    }

    一百万个顶点,内存将只占用32MB,相当于原来的1/5。你需要在性能和代码可读性之间做出取舍。

    在循环中,我们更需要注意实例的创建。

    1
    2
    3
    4
    5
    for i=1,n do
        local t = {1,2,3,'hi'}
        --执行逻辑,但t不更改
        ...
    end

    我们应该把在循环中不变的东西放到循环外来创建:

    1
    2
    3
    4
    5
    local t = {1,2,3,'hi'}
    for i=1,n do
        --执行逻辑,但t不更改
        ...
    end

    Reusing

    如果无法避免创建新对象,我们需要考虑重用旧对象。

    考虑下面这段代码:

    1
    2
    3
    4
    local t = {}
    for i = 1970, 2000 do
        t[i] = os.time({year = i, month = 6, day = 14})
    end

    在每次循环迭代中,都会创建一个新表{year = i, month = 6, day = 14},但是只有year是变量。

    下面这段代码重用了表:

    1
    2
    3
    4
    5
    6
    local t = {}
    local aux = {year = nil, month = 6, day = 14}
    for i = 1970, 2000 do
        aux.year = i;
        t[i] = os.time(aux)
    end

    另一种方式的重用,则是在于缓存之前计算的内容,以避免后续的重复计算。后续遇到相同的情况时,则可以直接查表取出。这种方式实际就是动态规划效率高的原因所在,其本质是用空间换时间。

    Recycling

    Lua自带垃圾回收器,所以我们一般不需要考虑垃圾回收的问题。

    了解Lua的垃圾回收能使得我们编程的自由度更大。

    Lua的垃圾回收器是一个增量运行的机制。即回收分成许多小步骤(增量的)来进行。

    频繁的垃圾回收可能会降低程序的运行效率。

    我们可以通过Lua的collectgarbage函数来控制垃圾回收器。

    collectgarbage函数提供了多项功能:停止垃圾回收,重启垃圾回收,强制执行一次回收循环,强制执行一步垃圾回收,获取Lua占用的内存,以及两个影响垃圾回收频率和步幅的参数。

    对于批处理的Lua程序来说,停止垃圾回收collectgarbage("stop")会提高效率,因为批处理程序在结束时,内存将全部被释放。

    对于垃圾回收器的步幅来说,实际上很难一概而论。更快幅度的垃圾回收会消耗更多CPU,但会释放更多内存,从而也降低了CPU的分页时间。只有小心的试验,我们才知道哪种方式更适合。

    结语

    我们应该在写代码时,按照高标准去写,尽量避免在事后进行优化。

    如果真的有性能问题,我们需要用工具量化效率,找到瓶颈,然后针对其优化。当然优化过后需要再次测量,查看是否优化成功。

    在优化中,我们会面临很多选择:代码可读性和运行效率,CPU换内存,内存换CPU等等。需要根据实际情况进行不断试验,来找到最终的平衡点。

    最后,有两个终极武器:

    第一、使用LuaJIT,LuaJIT可以使你在不修改代码的情况下获得平均约5倍的加速。查看LuaJIT在x86/x64下的性能提升比

    第二、将瓶颈部分用C/C++来写。因为Lua和C的天生近亲关系,使得Lua和C可以混合编程。但是C和Lua之间的通讯会抵消掉一部分C带来的优势。

    注意:这两者并不是兼容的,你用C改写的Lua代码越多,LuaJIT所带来的优化幅度就越小。

    声明

    这篇文章是基于Lua语言的创造者Roberto Ierusalimschy在Lua Programming Gems 中的Lua Performance Tips翻译改写而来。本文没有直译,做了许多删节,可以视为一份笔记。

    感谢Roberto在Lua上的辛勤劳动和付出!

     

     

    【Lua、LuaJIT、tolua++、lua for windows】这几个到底有什么关系?!

    官网分别是:

    lua:http://www.lua.org/

    tolua++:http://www.codenix.com/~tolua/#news

    luajit:http://luajit.org/luajit.html

    lua for windows:http://luaforge.net/projects/luaforwindows/

    为什么整出一堆其他的东东呢?这还不是因为这语言好,好多人做出了自己的优化扩展版本(例如LuaJIT、tolua++、lua for windows)。

    lua是个脚本语言,脚本语言!!就是脚本文件加解释器。之后你就可以看效果了。可是呢,lua如果正是靠自己独立完成点事情,那就是大材小用,需要和其他东西结合起来,比如C/C++.貌似主要也就是C/C++。

    下面说说这个三个:

    LuaJIT:LuaJIT is a Just-In-Time Compiler (JIT) for the Lua programming language. 。。。。。。说了半天就一个lua的高效率版本。

    tolua++:首先看名字“到、lua、++”,就是把其他语言(C/C++函数对象转化为lua能调用形式,++这里理解为增强版),有了这个工具,我们就可以快速的将我们现成的C/C++代码封装成Lua接口形式。

    lua for windows:lua在windows下的打包版本,除了最基本的lua解释器,还包括了可用于和C/C++集成开发的【动态链接库、静态链接库、头文件】、文本编辑器、常用的lua module,帮助说明文档。

     

     

    table.sort()不能用<=,不然会报错。当<与==拆分的时候,==(如果是最后一个if语句)必须要返回false。

     

    转载于:https://www.cnblogs.com/MrZivChu/p/luayouhua.html

    展开全文
  • lua优化建议

    2015-06-09 14:54:20
    这里的局部变量也包括函数function,因为在Lua里函数也是一个变量。局部变量的存取会更快,而且在生命周期之外就会释放掉。 使用全局变量 CCX = display.contentCenterX --global va

    1.使用局部变量local

    这是最基础也是最有用的策略,虽然使用全局变量并不能完全避免,但还是应该尽量避免,取而代之使用局部变量即local。这里的局部变量也包括函数function,因为在Lua里函数也是一个变量。局部变量的存取会更快,而且在生命周期之外就会释放掉。

    使用全局变量

    CCX = display.contentCenterX  --global variable
    for i = 1,100 do
       local image = display.newImage( "myImage" )
       image.x = CCX
    end
    

    使用局部变量

    local CCX = display.contentCenterX  --local variable
    for i = 1,100 do
       local image = display.newImage( "myImage" )
       image.x = CCX
    end
    

    这个原则也适用于Lua的核心库,比如math库。对于这类函数也应该使用局部变量。

    非局部变量

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

    使用局部变量

    local sin = math.sin  --local reference to math.sin
    local function foo(x)
       for i = 1,100 do
          x = x + sin(i)
       end
       return x
    end
    

    最后,记住尽量用局部变量的方式来使用函数。当然,这样需要注意函数的作用域的问题。如果你对Lua的作用域还不够清楚,请看Understanding “SCOPE” for beginning programmers

    使用全局的函数

    function func1()
       func2( "myValue" )
    end
    function func2( y )
       print( y )
    end
    func1()
    

    使用局部的函数

    --"func2" properly scoped above "func1" 
    local function func2( y )
       print( y )
    end
    local function func1()
       func2( "myValue" )
    end
    func1()
    

    2.避免将函数体定义作为其他函数的参数来使用

    如果函数的参数是函数时,应将参数函数作为局部变量传进参数,而不要直接写函数定义,请看下面两个例子:

    直接在参数表里定义函数

    local func1 = function(a,b,func)
       return func(a+b)
    end
    for i = 1,100 do
       local x = func1( 1, 2, function(a) return a*2 end )
       print( x )
    end
    

    使用局部变量传参

    local func1 = function( a, b, func )
       return func( a+b )
    end
    local func2 = function( c )
       return c*2
    end
    for i = 1,100 do
       local x = func1( 1, 2, func2 )
       print( x )
    end
    

    3.避免使用table.insert()

    下面来看看4个实现表插入的方法。在4个方法之中table.insert()在效率上不如其他方法,是应该避免使用的。

    使用table.insert

    local a = {}
    local table_insert = table.insert
    for i = 1,100 do
       table_insert( a, i )
    end
    

    使用循环的计数

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

    使用table的size

    local a = {}
    for i = 1,100 do
       a[#a+1] = i
    end
    

    使用计数器

    local a = {}
    local index = 1
    for i = 1,100 do
       a[index] = i
       index = index+1
    end
    

    4.减少使用 unpack()函数

    Lua的unpack()函数不是一个效率很高的函数。你完全可以写一个循环来代替它的作用。

    使用unpack()

    local a = { 100, 200, 300, 400 }
    for i = 1,100 do
       print( unpack(a) )
    end
    

    代替方法

    local a = { 100, 200, 300, 400 }
    for i = 1,100 do
       print( a[1],a[2],a[3],a[4] )
    end
    

    5.缓存table的元素

    缓存table的元素,特别是在循环内使用会提高效率。

    未缓存

    for i = 1,100 do
       for n = 1,100 do
          a[n].x = a[n].x + 1
          print( a[n].x )
       end
    end
    

    缓存

    for i = 1,100 do
       for n = 1,100 do
          local y = a[n]
          y.x = y.x + 1
          print( y.x )
       end
    end
    

    6.避免使用ipairs()

    当遍历table时,使用Lua的ipairs()的效率并不高。

    使用ipairs()

    local t1 = {}
    local t2 = {}
    local t3 = {}
    local t4 = {}
    local a = { t1, t2, t3, t4 }
    for i,v in ipairs( a ) do
       print( i,v )
    end
    

    代替方法

    local t1 = {}
    local t2 = {}
    local t3 = {}
    local t4 = {}
    local a = { t1, t2, t3, t4 }
    for i = 1,#a do
       print( a[i] )
    end
    

    7.数学方法的效率比较

    应该使用更快的数学方法。

    避免对正数使用math.fmod()

    --math.fmod method (discouraged)
    local fmod = math.fmod
    for i = 1,100 do
       if ( fmod( i,30 ) < 1 ) then
          local x = 1
       end
    end
    --modulus operator method (recommended)
    for i = 1,100 do
       if ( ( i%30 ) < 1 ) then
          local x = 1
       end
    end
    

    乘法比除法快

    x * 0.5 ; x * 0.125  --recommended
    x/2 ; x/8            --discouraged
    

    乘法比乘幂快

    x * x * x  --recommended
    x^3        --discouraged
    

    8.保存Texture内存

    Texture内存一般只有在出现警告时才会去关注,但那时就很难去补救了。

    1. 当texture不需要的时候记得释放掉。
    2. 如果你有一个525×600的背景图片,你可以改成448×512的。因为OpenGL对图片内存遵循2的倍数原则,即每次使用内存都是以2的倍数为长度的。所以525×600的图片将会消耗1024*1024的内存(即1024×1024 (pixels) × 4 (bytes) = 4,194,304 bytes = 4 MB),而448×512只会消耗1/4的内存。在图片清晰度容忍的情况下尽量缩小到下一个2倍量级内。
    3. 尽可能的重复利用素材。对于图片相同而颜色不同的可以使用setFillColor函数。例如你有红苹果和青苹果,那么你可以创建一个灰度的图片然后分别添加红色和绿色。
    4. 如果你使用image sheet,那么一定要使用类似TexturePacker的软件,不仅能提高开发效率也能优化图片大小。

    9.预先创建物理对象

    如果你要在场景中使用一定数量的物理对象,那么预先创建所有的对象会在使用时提高效率。那些暂时用不到的对象可以设置为未激活的状态然后放到屏幕的外面或者放到一个不可见的group里。当需要时设置对于的位置并激活即可。 实时创建物理对象并不是不可以,但一次性创建10-20个对象必然会造成性能问题,而导致顿卡延时等。 当然,也要考虑到内存的问题,如果一开始就创建几百个物体,那么对于内存的消耗就使得性能提高有点得不偿失了。

    10.音频使用策略

    有些音效是整个app都会用到的,这样的音效需要一开始就载入到内存中。对于音质并没有特别高的要求的音乐和音效需要考虑是否需要压缩,比如使用11khz来减小音频文件的大小,一般用户也听不出太大的区别,而这样减少的内存可是相当可观的。而且要使用简单的适合多平台的音频格式,比如WAV格式。 如果需要的话,音效可以如下组织成一个table,这样便于在使用时引用或者在不需要的时候释放掉。

    --load these sounds during NON-time-critical code
    local soundTable = {
       mySound1 = audio.loadSound( "a.wav" ),
       mySound2 = audio.loadSound( "b.wav" ),
       mySound3 = audio.loadSound( "c.wav" ),
       mySound4 = audio.loadSound( "d.wav" ),
       mySound5 = audio.loadSound( "e.wav" ),
       mySound6 = audio.loadSound( "f.wav" ),
       mySound7 = audio.loadSound( "g.wav" ),
       mySound8 = audio.loadSound( "h.wav" ),
    }
    

    播放一个音效就非常简单:

    local mySound = audio.play( soundTable["mySound1"] )
    

    永远不要忘记,当音效不需要的时候就要释放掉:

    local ST = soundTable
    for s,v in pairs(ST) do
       audio.dispose( ST[s] ) ; ST[s] = nil
    end
    展开全文
  • Lua优化技巧

    2020-04-04 09:30:09
    1.大量字符串拼接使用 table.concat() 不能使用…
    1.大量字符串拼接使用 table.concat() 不能使用运算符…和string.format
    • 创建字符串,Lua会检查内部是否有相同的字符串,如果有直接返回一个引用,如果没有才创建。使得Lua中String的比较和赋值非常地快速。另一方面这个机制使得Lua在拼接字符串上开销比较大,因为在一些直接持有字符串buffer的语言中,往往可以直接把后者的buffer插入到前者的buffer的末尾,而Lua先要遍历查找是否有相同的字符串,然后会把后者整个拷贝然后拼接。

    • 使用table.concat来代替。查看Lua的源码发现,原理是table.concat只会创建一块buffer,然后拼接所有字符串。而用运算符“…”来连接则每次都会产生一串新的字符串,开辟一块新的buffer–》对内存的影响更大,对CPU耗时的影响比较小–>减少GC

    • string.format() 效率低于运算符…

    2.使用局部变量比全局变量快,使用效率:local >upvalue>global
    • local变量存放在栈中,upvalue存放在链表中,global存放在全局的表中
    • 案例:
    --local
    function Add()
    	local x=1
    	local y=2
    	return x+y
    end
    --upvalue(外部局部变量)
    local x,y=1
    function Add()
    	return x+y
    end
    --global
    function Add()
    	return x+y
    end
    
    3.Lua table.insert() 添加元素的效率
    • table.inset(tab,1,a)< table.inser(tab,a) < tab[#tab+1]=a < tab[index]=a
    • luajit下性能差距不大
    • 案例:
    function table_insert()
        local t = {}
        for i = 1, 1000, 2 do
            table.insert(t, i)
        end
        return t
    end
     
    function table_insertL()
        local t, insert = {}, table.insert
        for i = 1, 1000, 2 do
            insert(t, i)
        end
        return t
    end
     
    function use_counter()
        local t, c = {}, 1
        for i = 1, 1000, 2 do
            t[c], c = i, c + 1
        end
        return t
    end
     
    function use_length()
        local t = {}
        for i = 1, 1000, 2 do
            t[#t + 1] = i
        end
    end
     
    --[[------------------------
    In Lua (1x)
    ID  Case name       t1      t2      t3      t4      t5      avg.    %
    1   table.insert G  2.72    2.73    2.72    2.73    2.72    2.724   100%
    2   table.insert L  2.24    2.24    2.24    2.24    2.24    2.24    82.23%
    3   use counter     1.13    1.13    1.14    1.12    1.13    1.13    41.48%
    4   use length      1.43    1.44    1.43    1.43    1.43    1.432   52.57%
    --]]------------------------
    
    4.Lua 预分配空间
    • 默认创建出来的表,是空的,在插入元素的过程,逐渐翻倍扩大,从0到1, 1到2,2到4,…都会触发realloc,同时把旧元素拷贝到新申请的空间中,对于最终有成千上万个元素的table,扩张的开销可以接受,但是对于大量生成小的table的场景,会明显拖慢性能,可以通过lua的构造函数,让Lua的编译器预分配空间。
    5.持续更新中…
    展开全文
  • lua优化小技巧

    2020-04-26 18:47:39
    1.闭包优化 面向对象编程时,经常需要写一些回调函数,而回调函数中又调用了自身的方法,在这个时候会产生闭包 local a = function () self:b() end 每次调用local a时,都会重新复制self和self.b,浪费大量内存...
  • cocos2dx lua优化总结

    千次阅读 2017-01-06 12:06:55
    经过一周多的优化,在性能上取得了较大的提升。游戏采用 Cocos2d-x 3.2 + Lua 进行开发,以下将在渲染效率,CPU效率,包大小等方面进行总结。 渲染效率 纹理格式 – 运行效率 内存 包大小 所有的...
  • Lua性能优化Lua内存优化

    千次阅读 2017-06-09 14:15:46
    笔者在这里和大家分享了一些在Lua性能优化方面的经验。比如说拿到原始数据后,如何处理过滤数据、信息的经验,从而更快更准确地定位问题。如果大家有更好更精准的处理数据、过滤信息的方法请不吝赐教。
  • lua代码优化

    千次阅读 2019-03-06 15:23:50
    使用缓存来优化,提高程序性能是一个很大的主题,这里不再详细论述。只需记得,当使用重复数据(或有重叠)时一定要缓存起来,以供后面使用,而不是每次都重新计算,这样会大大提高效率,尤其是涉及到繁...
  • Lua性能优化

    2019-03-25 01:09:01
    Lua 是一门以其性能著称的脚本语言,被广泛应用在很多方面,尤其是游戏。 我认为最好的方式是在首次编写的时候按照最佳实践去写出高性能的代码,而不是编写了一堆垃圾代码后,再考虑优化。相信工作后大家都会对事后...
  • Lua 性能优化

    2016-05-19 15:17:07
    因此,要优化使用表的程序(这里特指Lua程序),了解一些表的实现细节是很有好处的。 Lua的表的实现使用了一些很聪明的算法。每个Lua表的内部包含两个部分:数组部分和哈希部分。数组部分以从1到一个特定的n之间的...
  • lua性能优化

    2015-01-09 10:10:29
    编写高性能的Lua代码 3条回复 前言 Lua是一门以其性能著称的脚本语言,被广泛应用在很多方面,尤其是游戏。像《魔兽世界》的插件,手机游戏《大掌门》《神曲》《迷失之地》等都是用Lua来写的逻辑。 所以大...
  • lua 代码优化

    2019-07-11 09:08:33
    lua判断空表 function isEmpty( tab,isArray ) --判断lua空表,如果确定是数组类型,可以直接用#tab == 0 if tab == nil then return nil end if isArray then return #tab == 0 ...代码优化 1,大量字...
  • lua内存优化

    2015-07-12 11:27:19
    最近由于项目原因,我开始研究lua的回收机制,内存泄漏以及内存优化,于是在网上开始搜寻资料。 http://www.huomo.cn/developer/article-e8c5.html这篇文章讲述了游戏过程中遇到一些内存泄漏的问题,其中最容易犯的...
  • Lua代码优化总结

    2018-10-04 11:07:27
    编写高性能的Lua代码总结

空空如也

1 2 3 4 5 ... 20
收藏数 752
精华内容 300
关键字:

lua优化