前言
这是基于Lua官方文档总结(fan yi)出来的文章 -)
关于Lua的属性
- Lua中每一个active的函数都有一个activation record,其数据结构是stack(当然其实现的数据结构仍然是数组),activation record保存该函数的Registers 寄存器,一个函数最多可以拥有250多个寄存器,因为指向寄存器的指针的只有8位(bit)。
- Lua 的Table里面包含2部分,一部分是array,一部分是hash,在1-n范围内的数据存储到array,在n之外的其他数据存储在hash,其中hash部分使用了 open address 开放寻址法。默认table的大小为0,当新key要加入,table大小从0->1,1->2,2->4 ...。 Table只有在rehash的情况也就是insert的情况下才会缩小shrink Table,这样实现基于两个原因,一是避免检查nil,二是允许循环中赋值nil。
So, Lua traverses all entries, counting and
classifying them, and then chooses as the size of the array part the largest power
of 2 such that more than half the elements of the array part are filled. The hash
size is then the smallest power of 2 that can accommodate all the remaining
entries (that is, those that did not fit into the array part).
- Lua的字符串是内联( internalized)的,也就是说只保存一份字符串的拷贝,当新string出现,lua会检查是否存在这个字符串,有则复用。这样的做法有优点也有缺点,优点是方便字符串比较(比较指针是否相同即可),缺点是降低新建字符串的速度(要先查找字符串是否已经存在)。如上面所说,变量只是指向字符串。
技巧
技巧1 使用local变量
使用local变量,以a = a+b为例子,a、b是全局变量时候和a、b是局部变量时候的比对如下
a = a + b;
GETGLOBAL 0 0 ; a
GETGLOBAL 1 1 ; b
ADD 0 0 1
SETGLOBAL 0 0 ; a
local a;
local b;
a = a +b;
ADD 0 0 1
很明显使用local 少了运行3次
For instance, the code
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
技巧2 Table
为了减少Table rehash的次数,可直接使用构造方法直接赋值,如
多次赋值
local param = {};
param.type = 1;
param.id = 1;
直接赋值,Lua能知道table需要容纳2个元素并且新建相应大小的table。
local param = {type= 1, id = 1};
技巧3 字符串
使用table.concat连接字符串
技巧4 复用
这个适用于一个参数的方法调用,保存方法的计算结果,防止重复计算。
function memoize (f)
local mem = {} -- memoizing table
setmetatable(mem, {__mode = "kv"}) -- make it weak
return function (x) -- new version of ’f’, with memoizing
local r = mem[x]
if r == nil then -- no previous result?
r = f(x) -- calls original function
mem[x] = r -- store result for reuse
end
return r
end
end
技巧5 垃圾回收
Lua垃圾回收的速率是跟内存消耗的速率成正比。
关于垃圾回收有两个接口Lua的collectgarbage
和C的lua_gc
,
停止垃圾回收使用于批处理或者对时间敏感的程序当中