0%

Lua

库文件地址

lua官方地址
luajit

执行原理

这里先卖个关子,有一次面试,面试官问我, objc_msgsend 可以使用C语言写吗? 当时没回答好,理论上是可以的。

我们都知道lua是解释执行语言,C是编译执行语言,最大的区别,就是C可以充分利用编译器,制作成汇编指令,效率最高。

lua解释性语言只能解释成字节码,模拟汇编,进行操作。

lua是C写的,所以 objc_msgsend 理论上也可以C实现,动态的执行方法(不同参数,不同返回值),但是效率就降低为解释执行语言的效率了。

待补充。。。。。。。。。

lua指令集

参看lopcodes.h文件,里面定义了很多指令,
还有一个重要函数,我就不贴代码了,一个方法400多行,在lvm.C文件中的luaV_execute,可以看下

1
2
3
4
/* main loop of interpreter */
for (;;) {
...这里会对不不同指令进行操作
}

一些零散的源码阅读

Lua虚拟机并不能执行我们的ifStateMent这种东西。Lua源码里的实现也是类似这种TokenType 和 结构化的 if Statement whileStatement等等,并且Lua没有生成完整的语法树。Lua源码的实现里面,它是解析一些语句,生成临时的语法树,然后翻译成指令集的。并不会等所有的语句都解析完了再翻译的。语义解析和翻译成指令集是并行的一个过程。贴一个源码里面关于语义解析的部分实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static void body (LexState *ls, expdesc *e, int needself, int line) {
/* body -> `(' parlist `)' chunk END */
FuncState new_fs;
open_func(ls, &new_fs);
new_fs.f->linedefined = line;
checknext(ls, '(');
if (needself) {
new_localvarliteral(ls, "self", 0);
adjustlocalvars(ls, 1);
}
parlist(ls);
checknext(ls, ')');
chunk(ls);
new_fs.f->lastlinedefined = ls->linenumber;
check_match(ls, TK_END, TK_FUNCTION, line);
close_func(ls);
pushclosure(ls, &new_fs, e);
}

LuaJit

iOS的luajit

  1. LuaJIT分为JIT模式和Interpreter模式
  • JIT模式: 高效的机器码级别执行, 然而不幸的是这个模式在iOS下是无法开启的,因为iOS为了安全,从系统设计上禁止了用户进程自行申请有执行权限的内存空间,因此你没有办法在运行时编译出一段代码到内存然后执行,所以JIT模式在iOS以及其他有权限管制的平台(例如PS4,XBox)都不能使用。
  • Interpreter模式:编译成中间态的字节码(bytecode), 相比之下当然比JIT慢。但好处是这个模式不需要运行时生成可执行机器码字节码是不需要申请可执行内存空间的
  1. JIT模式一定更快?不一定!
    参考下图,这里可以看到,第一,Interpreter模式是必须的,无论平台是否允许JIT,都必须先使用Interpreter执行;第二,并非所有代码都会JIT执行,仅仅是部分代码会这样,并且是运行过程中决定的。

优化

  1. Reduce number of unbiased/unpredictable branches.减少不可预测的分支代码
  2. Use FFI data structures. 如果可以,将你的数据结构用ffi实现,而不是用lua table实现
  3. Call C functions only via the FFI.尽可能用ffi来调用c函数。
  4. Use plain ‘for i=start,stop,step do … end’ loops.实现循环时,最好使用简单的for i = start, stop, step do这样的写法,或者使用ipairs,而尽量避免使用for k,v in pairs(x) do
  5. Find the right balance for unrolling.循环展开,有利有弊,需要自己去平衡
  6. Define and call only ‘local’ (!) functions within a module.
  7. Cache often-used functions from other modules in upvalues.
  8. Avoid inventing your own dispatch mechanisms.避免使用你自己实现的分发调用机制,而尽量使用內建的例如metatable这样的机制
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    -- 编程的时候为了结构优雅,常常会引入像消息分发这样的机制,然后在消息来的时候根据我们给消息定义的枚举来调用对应的实现,过去我们也习惯写成:

    if opcode == OP_1 then

    elesif opcode == OP_2 then

    ...

    -- 但在luajit下,更建议将上面实现成table或者metatable

    local callbacks = {}

    callbacks[OP_1] = function() ... end

    callbacks[OP_2] = function() ... end

    -- 这是因为表查找和metatable查找都是可以参与jit优化的,而自行实现的消息分发机制,往往会用到分支代码或者其他更复杂的代码结构,性能上反而不如纯粹的表查找+jit优化来得快
  9. Do not try to second-guess the JIT compiler.无需过多去帮jit编译器做手工优化。
  10. Be careful with aliasing, esp. when using multiple arrays.变量的别名可能会阻止jit优化掉子表达式,尤其是在使用多个数组的时候。
  11. Reduce the number of live temporary variables.减少存活着的临时变量的数量
  12. Do not intersperse expensive or uncompiled operations.减少使用高消耗或者不支持jit的操作

Lua的API

参考api文档

#define lua_open() luaL_newstate() 开启一个lua状态机

1
2
3
4
5
6
7
8
9
void lua_settable (lua_State *L, int index);
// Does the equivalent to t[k] = v,
// where t is the value at the given valid index index,
// v is the value at the top of the stack,
// and k is the value just below the top.

// This function pops both the key and the value from the stack.
// As in Lua, this function may trigger a metamethod
// for the “newindex” event (see §2.8).
  1. lua_pop(L,num)函数从栈顶开始移除。
    当num>0时从栈顶移除指定个数 。
    当num=0时栈不受影响
    当num=-1时栈中元素全部移除

  2. lua_settop函数说明
    该函数用于指定栈的高度,栈只能从栈顶压栈,不能从栈底添加数据。所以栈底的数据会保持不变。
    当新的高度大于原来的高度时,会从栈顶压入数据,压入的数据不可用(因为是随机的)。
    当新的高度小于原来的高度时,会从栈顶移除多余的元素。
    当输入参数为负数时,表示从栈顶开始的索引(最栈顶元素为-1)。该函数会移除栈顶到该元素之间的所以元素。-1则无,-2 则移除-1 。-3则移除-1,-2。以此类推。但是负数编号不能超出栈底的负数索引,超出会抛出异常。lua_pop函数及是使用了该特性。

  3. int luaL_getmetatable (lua_State L,constchartname);
    将注册表中 tname 对应的元表(参见 luaL_newmetatable)压栈。如果没有 tname 对应的元表,则将 nil 压栈并返回假。

参考

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

http://wiki.luajit.org/Numerical-Computing-Performance-Guide

深入浅出

希望对您有所帮助,您的支持将是我莫大的动力!