编写高效Lua代码的方法 - 1 - 基本知识

翻译自《Lua Programming Gems》Chapter 2:Lua Performance Tips:Basic fact By Roberto Ierusalimschy

编写高效Lua代码的方法

基本知识

Lua在运行代码之前,会先把源码翻译(预编译)成一种内部编码,这种编码由一连串的虚拟机能够识别指令构成,与CPU的机器码很相似。接下来由C代码中的一个while循环负责解释这些内部编码,这个while循环中有一个很大的switch,一种指令就有对应的一个case。

    可能你已经从其他地方得知,自5.0版本开始,Lua就使用一个基于寄存器的虚拟机。但是这些“寄存器”跟CPU中的寄存器没有任何关联,因为这种关联会使Lua失去可移植性,并且会使Lua受限于可用的寄存器数量。Lua使用一个栈(由一个数组加上一些索引实现)来存放它的寄存器。每一个运行中的函数都有各自的一份活动记录,这些活动记录保存在栈中,内部存放着每个函数对应的寄存器。所以每个函数都有一组各自的寄存器。每条指令中只有8个bit用来标志寄存器,所以每个函数最多能够使用250个寄存器。

    由于Lua有如此大量的寄存器,所以在预编译时能够将所有的局部变量(local)存放到寄存器中。所以,在Lua中,访问局部变量是很快的。举个例子,如果a和b是局部变量,语句a= a + b只生成一条指令:ADD 0 0 1 (假设a和b分别在寄存器0和1中)。对比一下如果a和b是全局变量,生成上述加法运算的中间代码会像这样:

 

GETGLOBAL 0 0  ; a

GETGLOBAL 1 1  ; b

ADD            0 0 1

SETGLOBAL  00   ; a

 

所以,很明显我们可以得出Lua编程里面其中一条最重要的改进性能的规则:使用局部变量(uselocals)!

    如果你需要尽可能的提升程序的性能,你可以使用局部变量,比如,如果你在一个很长的循环里调用一个函数,你可以先将函数赋值给一个局部变量。比如以下代码

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

访问外层局部变量(也就是外一层函数的局部变量)并没有访问局部变量快,但是还是比访问全局变量快。看看以下代码片段:

function foo(x)
    for i =1, 1000000 do
        x =x + math.sin(i)
    end
    return x
end
print(foo(10))
我们通过在foo函数外面声明一次sin来优化它:
local sin = math.sin
function foo(x)
    for i =1, 1000000 do
        x =x + sin(i)
    end
    return x
end
print(foo(10))

第二段代码比第一段快30%。

    比起其他编译器,Lua的编译器是比较高效的,尽管如此,编译还是一项比较繁重的任务。所以,无论何时都要尽量避免在程序中编译代码(比如,调用loadstring函数)。除非你需要真正地动态地执行你的代码,比如代码是由用户输入的,否则你很少需要编译动态的代码。

    考虑以下例子,下面的代码创建一个存放了10000函数的table,这些存放在table中的函数分别返回常量1到10000:

local lim = 10000
local a = {}
for i = 1, lim do
    a[i] =loadstring(string.format("return %d", i))
end
print(a[10]()) --> 10

这份代码运行了1.4秒。

    我们通过使用闭包来避免动态编译。下面的代码在1/10的时间里(0.14)创建了同样的10000个函数:

function fk (k)
    returnfunction () return k end
end
local lim = 100000
local a = {}
for i = 1, lim do a[i] = fk(i) end
print(a[10]()) --> 10


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值