Lua随手记

官网:The Programming Language Lua

手册:Lua 5.2 Reference Manual

社区:lua-users.org

论坛:http://www.luaer.cn/

在线中文手册:http://manual.luaer.cn

Lua技巧(性能),local/table/string/gc  https://segmentfault.com/a/1190000004372649 

1.Lua中...可表示可选参数,但是跟arg的区别有些大啊!而且如果在一个函数内同时使用...和arg的话,...有效、arg会变成nil(2014.7.17 看skynet代码时发现,arg在5.1跟5.2貌似有些区别,最好是只在获取命令行参数用arg,获取函数可变参数用...,这样可规避问题。)

function func1(...)
	print(type(arg),'->',arg)
	for k,v in pairs(arg) do
		print(k,v)
	end
end

function func2(...)
	print(type(...),'->',...)
	for k,v in pairs({...}) do
		print(k,v)
	end
end

func1(1,2,3,4,5)
print(string.rep("-", 20))
func2(1,2,3,4,5)

OUTPUT:
table   ->      table: 00A6B218
1       1
2       2
3       3
4       4
5       5
n       5
--------------------
number  ->      1       2       3       4       5
1       1
2       2
3       3
4       4
5       5

[root@test-22 lua-study]# cat var.lua 
local function f(...)
    if not ... then print('empty'); return end
    local t = {}
    for i = 1, select('#',...) do
        print('i', i, select(i,...))
        t[i] = select(i,...)
    end
    for k,v in pairs(t) do print(k,v) end
end

f('a', 'b', 'c')
f()

local function f2(a,...)
    print('f2 called', a, ...)
end
f2('a', 1, 2, 3)
f2('a', table.unpack({1,2,3})) --unpack的结果全部传入
f2('a', false or table.unpack({1,2,3})) --只取upack的第一个结果
[root@test-22 lua-study]# lua var.lua 
i       1       a       b       c
i       2       b       c
i       3       c
1       a
2       b
3       c
empty
f2 called       a       1       2       3
f2 called       a       1       2       3
f2 called       a       1

2.setmetatable会返回被操纵的table

oritable = {}
local a = setmetatable(oritable, {__mode="k"})
print("oritable=", oritable)
print("setmetable(oritable,..) returned:", a)

for k,v in pairs(a) do print(k,v) end
print(string.rep('-',30))
for k,v in pairs(getmetatable(oritable)) do print(k,v) end
  
:!lua setmetatable.lua
oritable=       table: 0x1e4a830
setmetable(oritable,..) returned:       table: 0x1e4a830
------------------------------
__mode  k

3.保护某个table的metatable不被再次修改:在该table(假设名字为mytable)的元表身上设置__metatable域,这样getmetatable(mytable)就会返回所设置的内容,setmetatable(mytable)会报错

[dongsong@localhost lua-study]$ cat setmetatable.lua 
oritable = {}
local a = setmetatable(oritable, {__metatable='hello'})
print("oritable=", oritable)
print("setmetable(oritable,..) returned:", a)
print("getmetatable(oritable) returned:", getmetatable(oritable))
print("setmetatble(oritable,..) again:", setmetatable(oritable, {}))
[dongsong@localhost lua-study]$ lua setmetatable.lua 
oritable=       table: 0x238a860
setmetable(oritable,..) returned:       table: 0x238a860
getmetatable(oritable) returned:        hello
lua: setmetatable.lua:6: cannot change a protected metatable
stack traceback:
        [C]: in function 'setmetatable'
        setmetatable.lua:6: in main chunk
        [C]: ?

4.require package.path LUA_PATH

lua 5.1的官方文档 There were substantial changes in function  require due tothe new module system.However, the new behavior is mostly compatible with the old,butrequire gets the path frompackage.path insteadof from LUA_PATH.

[dongsong@localhost require_test]$ tree -a
.
├── myfile2.lua
├── mypackage
│   └── myfile.lua
└── test.lua

1 directory, 3 files
[dongsong@localhost require_test]$ cat test.lua
function test()
        package.loaded['myfile2'] = nil
        package.loaded['myfile'] = nil

        print(string.rep("=",30))
        print("package.path = ", package.path)
        print("LUA_PATH = ", LUA_PATH)
        local rt,msg =  pcall(require, "myfile2")
        if type(msg) == 'string' then
                local i,j
                i,j,msg = string.find(msg, '([^\n]+)')
        end
        print("require myfile2:", rt, msg)
        rt,msg = pcall(require, "myfile")
        if type(msg) == 'string' then
                local i,j
                i,j,msg = string.find(msg, '([^\n]+)')
        end
        print("require myfile:", rt, msg)
end

test()
LUA_PATH = "/home/dongsong/data/lua-study/require_test/mypackage/?.lua"
test()
LUA_PATH = nil
package.path = package.path .. ";/home/dongsong/data/lua-study/require_test/mypackage/?.lua"
test()

print(string.rep('=',30))
for k,v in pairs(package.loaded) do print(k,v) end
[dongsong@localhost require_test]$ 
[dongsong@localhost require_test]$ lua test.lua
==============================
package.path =  ./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua
LUA_PATH =      nil
hello,i am myfile2
require myfile2:        true    true
require myfile: false   module 'myfile' not found:
==============================
package.path =  ./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua
LUA_PATH =      /home/dongsong/data/lua-study/require_test/mypackage/?.lua
hello,i am myfile2
require myfile2:        true    true
require myfile: false   module 'myfile' not found:
==============================
package.path =  ./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua;/home/dongsong/data/lua-study/require_test/mypackage/?.lua
LUA_PATH =      nil
hello,i am myfile2
require myfile2:        true    true
hello,i am myfile
require myfile: true    true
==============================
string  table: 0xa4d2c0
debug   table: 0xa52640
package table: 0xa4db50
_G      table: 0xa4b6b0
myfile  true
io      table: 0xa4f760
os      table: 0xa50140
table   table: 0xa4cbc0
math    table: 0xa51570
coroutine       table: 0xa4d600
myfile2 true

dofile() loadfile() require()的区别

dofile()和loadfile()都不做所搜,require根据package.path来做搜索

dofile()编译文件并做执行,重复调用dofile()会重复编译和执行

loadfile()只是编译返回而不做执行,重复调用就重复编译

require()是搜索到文件并编译和执行,重复调用不会重复执行

[dongsong@localhost lua-study]$ lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> t=loadfile("t")
> t()
stdin:1: attempt to call global 't' (a nil value)
stack traceback:
        stdin:1: in main chunk
        [C]: ?
> t=loadfile("t.lua")
> t()
6
> loadfile("t.lua")()
6
> t=dofile("t.lua")
6
> print(t)
nil
> dofile("t.lua")
6
> require("t.lua")
stdin:1: module 't.lua' not found:
        no field package.preload['t.lua']
        no file './t/lua.lua'
        no file '/usr/share/lua/5.1/t/lua.lua'
        no file '/usr/share/lua/5.1/t/lua/init.lua'
        no file '/usr/lib64/lua/5.1/t/lua.lua'
        no file '/usr/lib64/lua/5.1/t/lua/init.lua'
        no file './t/lua.so'
        no file '/usr/lib64/lua/5.1/t/lua.so'
        no file '/usr/lib64/lua/5.1/loadall.so'
        no file './t.so'
        no file '/usr/lib64/lua/5.1/t.so'
        no file '/usr/lib64/lua/5.1/loadall.so'
stack traceback:
        [C]: in function 'require'
        stdin:1: in main chunk
        [C]: ?
> require("t")    
6
> require("t")
> 
[dongsong@localhost lua-study]$ cat t.lua
a = {1,2,3,4,5,6}
print(table.getn(a))

require返回值的问题:默认返回true,如果require的lua文件有return,则以其return的值作为require的返回值

[dongsong@localhost skynet]$ cat t.lua
a = {1,2,3,4,5}
print("i am required")
[dongsong@localhost skynet]$ lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> t=require "t"
i am required
> =t
true
> =package.loaded["t"]
true
> 
==============================================================
[dongsong@localhost skynet]$ cat t.lua
a = {1,2,3,4,5}
print("i am required")
return a
[dongsong@localhost skynet]$ lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> pk=require "t"
i am required
> =pk
table: 0x1427320
> =package.loaded["t"]
table: 0x1427320
> for k,v in pairs(pk) do print(k,v) end
1       1
2       2
3       3
4       4
5       5

5.注意elseif和else if的区别,后者在else下面的chunk里面启了新的if块,需要有与之对应的end

6.ipairs vs pairs

[dongsong@localhost lua-study]$ cat pairs.lua 
math.randomseed(os.time())
t = {}
for i = 1,10 do t[i] = i*i end
for i = 1,10 do
        local v = math.random(1000)
        t[v] = v*v
end
print("ipairs(t):")
print(string.rep('v',30))
for k,v in ipairs(t) do print(k,v) end
print(string.rep('^',30))
print("pairs(t):")
print(string.rep('v',30))
for k,v in pairs(t) do print(k,v) end
print(string.rep('^',30))
[dongsong@localhost lua-study]$ 
[dongsong@localhost lua-study]$ lua pairs.lua 
ipairs(t):
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
1       1
2       4
3       9
4       16
5       25
6       36
7       49
8       64
9       81
10      100
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pairs(t):
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
1       1
2       4
3       9
4       16
5       25
6       36
7       49
8       64
9       81
10      100
580     336400
852     725904
854     729316
678     459684
804     646416
188     35344
346     119716
824     678976
771     594441
511     261121
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

7.判断table是否为空

if next(myTable) == nil then
   -- myTable is empty
end

参见:http://stackoverflow.com/questions/1252539/most-efficient-way-to-determine-if-a-lua-table-is-empty-contains-no-entries

8.貌似Lua没有类似于 php中的print_r()/var_dump(); python中的pprint.pprint() 这种函数。下面写了个简单的:

[root@test-22 lua-study]# cat pprint.lua 
function pprint(var, tostr)
    local duplicateTable = {}
    local rstr = ''
    local function realfunc(var, stack)
        local function myprint(...)
            rstr = rstr .. string.rep("\t",stack)
            for _, s in pairs({...}) do
                rstr = rstr .. s
            end
        end
        
        if type(var) ~= "table" then
            if type(var) == 'string' then
                myprint(' "'..tostring(var)..'" ')
            else
                myprint(tostring(var))
            end
        else
            --duplicate detect
            if duplicateTable[var] then
                myprint(tostring(var))
                return
            else
                duplicateTable[var] = 1
            end
            --print data
            myprint(tostring(var), "\n")
            if var.__pprint and type(var.__pprint)=='function' then --把日志按照table返回(每行一个元素)
                local tstrs = var:__pprint()
                for _, s in pairs(tstrs) do myprint(s,'\n') end
            else
                myprint("{")
                local nilflag = true
                for k,v in pairs(var) do
                    if nilflag then
                        rstr = rstr .. '\n'
                        nilflag = false
                    end
                    realfunc(k, stack+1)
                    if type(v) == "table" and next(v) ~= nil then
                        rstr = rstr .. '=>\n'
                        realfunc(v, stack+2)
                    elseif type(v) ~= "table" then
                        if type(v) == 'string' then
                            rstr = rstr .. '=>' .. ' "'..tostring(v)..'" '
                        else
                            rstr = rstr .. '=>' .. tostring(v)
                        end
                    else
                        rstr = rstr .. '=>' .. tostring(v) .. '{}'
                    end
                    rstr = rstr .. '\n'
                end
                myprint("}")
            end
        end
    end
    realfunc(var, 0)
    rstr = rstr .. '\n'
    if tostr then return rstr else io.write(rstr) end
end

local d = {a=1, b=2, c={1,2,3,4}}
local tmpd = {x=1,y={m=1,n=2}}
d[tmpd] = {1,2,3,4,5,6,7,8,9,{"hello","world"}}
d["hello"] = {}
d["dup"] = d
d[d] = "dup2"
d.xx = {a=111, b=22,
        __pprint = function(self)
            local t = {}
            table.insert(t, string.format('a=%d',self.a))
            table.insert(t, string.format('b=%d',self.b))
            return t
        end
        }
print(pprint(d, true))
[root@test-22 lua-study]# lua pprint.lua 
table: 0x7f88e70
{
        table: 0x7f8bc60
        {
                 "y" =>
                        table: 0x7f8bca0
                        {
                                 "m" =>1
                                 "n" =>2
                        }
                 "x" =>1
        }=>
                table: 0x7f8bd30
                {
                        1=>1
                        2=>2
                        3=>3
                        4=>4
                        5=>5
                        6=>6
                        7=>7
                        8=>8
                        9=>9
                        10=>
                                table: 0x7f892f0
                                {
                                        1=> "hello" 
                                        2=> "world" 
                                }
                }
         "xx" =>
                table: 0x7f89480
                a=111
                b=22

         "c" =>
                table: 0x7f8bc20
                {
                        1=>1
                        2=>2
                        3=>3
                        4=>4
                }
         "b" =>2
        table: 0x7f88e70=> "dup2" 
         "dup" =>
                table: 0x7f88e70
         "hello" =>table: 0x7f89330{}
         "a" =>1
}


9.for迭代. 说白了,for中的表达式返回(函数,状态常量,控制变量),每次循环用“状态常量”和“控制变量”作为参数调用“函数”,返回值赋给变量列表(第一项是下次循环的控制变量)。而多变量赋值和多参数赋值都遵循不足用nil补的原则。

[dongsong@localhost lua-study]$ cat iterator.lua 
local function allwords()
    local line = io.read()   -- current line
    local pos = 1            -- current position in the line
    return function ()       -- iterator function
       while line do        -- repeat while there are lines
           local startpos, endpos = string.find(line, "%w+", pos)
           if startpos then         -- found a word?
              pos = endpos + 1   -- next position is after this word
              return string.sub(line, startpos, endpos) -- return the word
           else
              line = io.read()  -- word not found; try next line
              pos = 1       -- restart from first position
           end
       end
       return nil    -- no more lines: end of traversal
    end
end

io.input("test.txt")
for word in allwords() do
        print(word)
end
[dongsong@localhost lua-study]$ lua iterator.lua 
function
NumberOfG
local
count
0
for
n
in
pairs

10.把table当普通c数组使用(PS: 交互模式下用=xx就可以直接打印变量xx,而不是必须用print(),这么简单的事情今天才发现,我了个大擦 2014.5.9)

> t = {}
> table.insert(t, 123)
> t[#t+1] = 456
> = t[1]
123
> = t[2]
456

用#table获取table的普通数组段的大小,这里有个小坑,须慎重!

> =a
table: 0xfa52c0
> for k,v in pairs(a) do print(k,v) end
1       1
2       2
3       3
> a[1] = nil
> 
> for k,v in pairs(a) do print(k,v) end
2       2
3       3
> =#a
3
> a = {}
> a[2] = 2
> a[3] = 3
> =#a
0

上述的问题其实是因为table的普通数组部分被扩了,同时说明,普通数组部分的删除操作需要注意:

置nil之后数组部分大小没有改变(用#取到普通数组部分大小、不过用pairs和ipairs却无法遍历到相同数目的元素);

而remove操作不同,它会改变数组部分大小同时会改变key和value的映射

> t={1,2,3,4}
> t
> =t
table: 0x15173e0
> =#t
4
> table.remove(t,2)
> =#t
3
> for k,v in pairs(t) do print(k,v) end
1       1
2       3
3       4
> table.insert(t,10)
> for k,v in pairs(t) do print(k,v) end
1       1
2       3
3       4
4       10

追加于2015.7.29

7849(sxh) 2015-07-29 16:11:56
local a = {}
a[2] = 1
a[3] = 1
a[4] = 1
print(#a)
猜猜这个打印几?
4281(xds) 2015-07-29 16:11:55
0 或者 4 
7849(sxh) 2015-07-29 16:12:36
4

7849(sxh) 2015-07-29 16:22:42
它有个规则: 如果key的元素个数大于对应个数幂大小的一半,则生成对应幂长度的数组
a[2] = 2 a[3] = 3
0~1 0个元素 0 > 2^0 / 2 不成立 数组长度0
0~2 1个元素 1 > 2^1 / 2 不成立 数组长度0
0~4 2个元素 2 > 2^2 / 2 不成立 数组长度0 
7849(sxh) 2015-07-29 16:23:19
也就是说 # 和中间有没有nil 基本没啥关系
7849(sxh) 2015-07-29 16:23:28
#只是单纯的返回数组部分长度吧

11.垃圾收集,数据清理,释放资源,c++对象析构

http://www.lua.org/manual/5.2/manual.html#2.5.1

local CMD = setmetatable({}, { __gc = function() netpack.clear(queue) end })

12.关于table遍历的问题

The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. You may however modify existing fields. In particular, you may clear existing fields.
也就是说,在遍历过程中不能新增KEY,其他可以随便整
 

13.Lua date and time
参见 http://www.lua.org/pil/22.1.html

1>os.time(timeTable) 年月日必须指定,其他可选,时分秒默认是12:00:00.

2>os.date("*t",unittime) 得到的table中wday是:周日~周六->1~7

    os.date("%w",unixtime)得到的字符串是:周日~周六-> 0~6

3>os.date("*t",unixtime)得到的table中isdst是指是否使用夏时制,第一次了解这个概念,比较有意思(http://zh.wikipedia.org/wiki/%E5%A4%8F%E6%97%B6%E5%88%B6)

[dongsong@localhost lua-study]$ cat weekend.lua 
function getWeekZeroTime(time)
    local zeros = os.date("return {year = %Y, month = %m, day = %d, week = %w}", time)
    local zerot = loadstring(zeros)()
    local weekv = zerot.week > 0 and (zerot.week - 1) or 6
    zerot.week = nil
    zerot.hour = 0 --warning: zerot.hour default 12
    return os.time(zerot) - weekv*24*3600
end

function func(time)
    local zerot = os.date('*t',time)
    for k,v in pairs(zerot) do print(k,v) end
    local w = tonumber(os.date('%w',os.time()))
    print('%w->week:'..w)
    print('*t->week:'..zerot.wday)
    w = w>0 and w-1 or 6
	--or
	--w = (zerot.wday>1) and (zerot.wday-2) or 6
    zerot.hour, zerot.min, zerot.sec = 0, 0, 0
    return os.time(zerot) - w*24*3600
end

local t = os.time()
print(getWeekZeroTime(t))
print(string.rep('-',30))
print(func(t))
[dongsong@localhost lua-study]$ 
[dongsong@localhost lua-study]$ lua weekend.lua 
1402848000
------------------------------
hour    19
min     43
wday    4
day     18
month   6
year    2014
sec     45
yday    169
isdst   false
%w->week:3
*t->week:4
1402848000

14.luarocks(http://luarocks.org/) 类似于python的easy_install

[dongsong@localhost ~]$ luarocks --help
lua: /usr/local/bin/luarocks:3: module 'luarocks.loader' not found:
        no field package.preload['luarocks.loader']
        no file './luarocks/loader.lua'
        no file '/usr/share/lua/5.1/luarocks/loader.lua'
        no file '/usr/share/lua/5.1/luarocks/loader/init.lua'
        no file '/usr/lib64/lua/5.1/luarocks/loader.lua'
        no file '/usr/lib64/lua/5.1/luarocks/loader/init.lua'
        no file './luarocks/loader.so'
        no file '/usr/lib64/lua/5.1/luarocks/loader.so'
        no file '/usr/lib64/lua/5.1/loadall.so'
        no file './luarocks.so'
        no file '/usr/lib64/lua/5.1/luarocks.so'
        no file '/usr/lib64/lua/5.1/loadall.so'
stack traceback:
        [C]: in function 'require'
        /usr/local/bin/luarocks:3: in main chunk
        [C]: ?
[dongsong@localhost ~]$ lua 
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> =package.path
./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib64/lua/5.1/?.lua;/usr/lib64/lua/5.1/?/init.lua
> package.path = package.path..";/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua"
> require "luarocks.loader"
[dongsong@localhost ~]$ export LUA_PATH='/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua' 
[dongsong@localhost ~]$ echo $LUA_PATH
/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua
[dongsong@localhost ~]$ luarocks --help
LuaRocks 2.1.2, a module deployment system for Lua
NAME
        /usr/local/bin/luarocks - LuaRocks main command-line interface
SYNOPSIS
        /usr/local/bin/luarocks [--from=<server> | --only-from=<server>] [--to=<tree>] [VAR=VALUE]... <command> [<argument>] 
...

如何让lua自己去找到这个库,也就是不用每次都重设lua_path呢?

    At start-up, Lua initializes this variable with the value of the environment variable LUA_PATH or with a default path defined in luaconf.h, if the environment variable is not defined. Any ";;" in the value of the environment variable is replaced by the default path.

可见,除了在.bash_profile中设置LUA_PATH环境变量以外,还可以直接把需要追加的路径加到lua的配置文件中:我的机器是/usr/include/luaconf.h

15.luaprofiler(http://luaprofiler.luaforge.net/manual.html) 类似于测试c++程序的google-perftools. 暂时还没实际使用过。

16.print(t) string.format('%s',t) tostring(t) 对于table t, 默认会输出“table address", 这里调用的是元表的__tostring方法,如果改写了这个方法,那么要获取一个table的地址就不容易了(google没找到解决办法,还是Python容易,直接id(t)就行了),所以要想得到地址可以在改写__tostring方法之前用tostring(t)获取后放在t身上。(剑雄客户端middleclass区分同类型粒子的不同实例就是这么干的)

17.Lua 垃圾收集 GC

http://blog.csdn.net/yuanlin2008/article/details/8558103 简明的文章

18.关于pcall和异常传播

对可能有异常的lua函数f使用pcall(f),那么f内出现异常也不会中断程序

如果在lua中调用自己编写的c lib的函数f,而函数内有异常,那么程序会在异常处中断,就算pcall(f)程序还是会中断

19.lua判断空格等空串

[dongsong@localhost lua-study]$ cat emptystr.lua 
function isBlank(x)
  return not not x:find("^%s*$")
end
print(isBlank('  '))
print(isBlank('  \n'))
print(isBlank('\t '))
print(isBlank('; '))
[dongsong@localhost lua-study]$ lua emptystr.lua 
true
true
true
false

20.优先级从高到低 http://www.lua.org/pil/3.5.html

             ^
             not  - (unary)
             *   /
             +   -
             ..
             <   >   <=  >=  ~=  ==
             and
             or

21.闭包(2015.4.30),跟python类似(参见http://blog.csdn.net/xiarendeniao/article/details/6774520  <item61>),前两天客户端同事在for外面定义变量a,每次给a赋值并为a常见一个button(细节不了解,应该是个闭包用于回调),结果所有button点击时发了相同的数据。下面这个小程序对闭包的解释应该够明了了。

[dongsong@localhost lua-study]$ cat upvalue_test_2.lua 
local function func()
    local funcs = {}
    local a
    for index = 1, 5 do
        a = index
        local function func_enclosing()
            io.write(string.format('enclosing func %s %d\n', tostring(func_enclosing), a))
        end
        table.insert(funcs, func_enclosing)
    end
    return funcs
end

local funcs = func()
for _, tfunc in pairs(funcs) do
    io.write(tostring(tfunc), '\n  ')
    tfunc()
end
[dongsong@localhost lua-study]$ lua upvalue_test_2.lua 
function: 0x13ce160
  enclosing func function: 0x13ce160 5
function: 0x13cec60
  enclosing func function: 0x13cec60 5
function: 0x13cdd70
  enclosing func function: 0x13cdd70 5
function: 0x13ce750
  enclosing func function: 0x13ce750 5
function: 0x13ce790
  enclosing func function: 0x13ce790 5

22.sleep

linux & windows. cpu消耗大
function Sleep(n)
   local t0 = os.clock()
   while os.clock() - t0 <= n do end
end

linux
function Sleep(n)
   os.execute("sleep " .. n)
end

windows
function Sleep(n)
   if n > 0 then os.execute("ping -n " .. tonumber(n + 1) .. " localhost > NUL") end
end

23.热更时获取upvalue

local func = packetHandler[opCodes.G2D_ARENA_CHAR_JOIN]
local isMainThread = false
for index = 1, 10 do
        local upname, upvalue = debug.getupvalue(func, index)
        if not upname then break end
        if upname == 'charIdToRank' and next(upvalue) then isMainThread = true; break end
end
if not isMainThread then print("i'm not main thread"); return end
print("i'm main thread")
--do return end

24.lua bit32 (5.3版不提倡使用)  对于大于32bit的整数高位被清除了

> a = 0x7fffffffffffffff
> =a
9223372036854775807
> =bit32.band(a,0x7ffffffffffffff0)
4294967280
> return bit32.band(0xffffffff,0xfffffff0)        
4294967280

25.for 语法制造for作用域之内有效的local变量

[root@test-22 lua-study]# cat fortest.lua 
local function test()
    local m, n = 1, 1
    print(string.format('---m(%s) n(%s)', m, n))
    while m < 10 do print(string.format('while m(%s)', m)); m = m+1 end
    for n = 1, 10 do print(string.format('for n(%s)', n)) end
    print(string.format('---m(%s) n(%s)', m, n))
end

test()
[root@test-22 lua-study]# lua fortest.lua 
---m(1) n(1)
while m(1)
while m(2)
while m(3)
while m(4)
while m(5)
while m(6)
while m(7)
while m(8)
while m(9)
for n(1)
for n(2)
for n(3)
for n(4)
for n(5)
for n(6)
for n(7)
for n(8)
for n(9)
for n(10)
---m(10) n(1)

26.对大table中的同一value做多次赋值时,先local出来避免多次hash取值,这应该是常识了,今天(207.5.17)看到其他组居然无视。让我差点以为自己想多了...

[root@test-22 lua-study]# cat hash_profile.lua 
local t = {}
local num = 0
local aimk = nil
while num < 100000 do
	local k = math.random(1000000)
	if not t[k] then
		t[k] = {a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8, i=9}
		num = num + 1
	end
	if num == 50000 then aimk = k end
end

local function f1()
	t[aimk].a = 11
	t[aimk].b = 12
	t[aimk].c = 13
	t[aimk].d = 14
	t[aimk].e = 15
	t[aimk].f = 16
	t[aimk].g = 17
	t[aimk].h = 18
	t[aimk].i = 19
end

local function f2()
	local tt = t[aimk]
	tt.a = 11
	tt.b = 12
	tt.c = 13
	tt.d = 14
	tt.e = 15
	tt.f = 16
	tt.g = 17
	tt.h = 18
	tt.i = 19
end

local function profile(f)
	local external = require'external'
	local t1 = external.getTickCount()
	for _ = 1, 10000000 do f() end
	local t2 = external.getTickCount()
	return t2-t1
end

print(string.format('f1 %sms', profile(f1)))
print(string.format('f2 %sms', profile(f2)))
print(string.format('f1 %sms', profile(f1)))
print(string.format('f2 %sms', profile(f2)))
print(string.format('f1 %sms', profile(f1)))
print(string.format('f2 %sms', profile(f2)))
[root@test-22 lua-study]# lua hash_profile.lua 
f1 4300ms
f2 2386ms
f1 4300ms
f2 2385ms
f1 4299ms
f2 2386ms

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值