luajit与NYI

什么是LuaJIT

标准 Lua 出于性能考虑,也内置了虚拟机,所以 Lua 代码并不是直接被解释执行的,而是先由 Lua 编译器编译为字节码(Byte Code),然后再由 Lua 虚拟机执行。

LuaJIT 的解释器会在执行字节码的同时,记录一些运行时的统计信息,比如每个 Lua 函数调用入口的实际运行次数,还有每个 Lua 循环的实际执行次数。当这些次数超过某个随机的阈值时,便认为对应的 Lua 函数入口或者对应的 Lua 循环足够热,这时便会触发 JIT 编译器开始工作。JIT 编译器会从热函数的入口或者热循环的某个位置开始,尝试编译对应的 Lua 代码路径。编译的过程,是把 LuaJIT 字节码先转换成 LuaJIT 自己定义的中间码(IR),然后再生成针对目标体系结构的机器码。

由于是机器码,LuaJIT编译的代码会比原先运行的快

所以很多时候优化Lua代码,就是使热路径上的代码尽量都能够被JIT优化。

什么是NYI

NYI的全称就是Not Yet Implemented,即还没有被LuaJIT追踪并优化的Lua代码,由于LuaJIT作者处于半退休状态,所以这部分代码暂时不会支持。

如何找出自己代码里有多少NYI?

可以在init_by_lua中添加以下两行代码

local v = require "jit.v"
v.on("/tmp/jit.log")

运行压力测试工具,一定量后,就会在/tmp/jit.log文件里输出NYI的部分
jit.v 模块的输出里如果有类似下面这种带编号的 TRACE 行,则指示成功编译了的 trace 对象,例如

[TRACE 6 shdict.lua:126 return]

这个 trace 对象编号为 6,对应的 Lua 代码路径是从 shdict.lua 文件的第 126 行开始的。

编译失败的如下面的例子

[TRACE --- waf.lua:321 -- NYI: bytecode 51 at raven.lua:107]

该输出的意思是说从waf.lua的321行开始输出,直到raven.lua的107行遇到NYI而停止,51字节码的意思可由以下代码查看

$ /usr/local/openresty/luajit/bin/luajit-2.1.0-alpha ljbc.lua 51
opcode 51:
FNEW

NYI

具体有哪些NYI,可以查看官网http://wiki.luajit.org/NYI
个人用的比较多的是string库

函数 编译 备注
string.byte yes
string.char 2.1
string.dump never
string.find 2.1 partial 只有字符串样式查找(没有样式)
string.format 2.1 partial 不支持 %p 或 非字符串参数的 %s
string.gmatch no
string.gsub no
string.len yes
string.lower 2.1
string.match no
string.rep 2.1
string.reverse 2.1
string.sub yes
string.upper 2.1

其中大部分string库函数都可以用ngx.re库替代,而且ngx.re库支持LuaJIT和PCRE JIT
例如:

newstr, n, err = ngx.re.gsub(subject, regex, replace, options?)

把options设为jo即可
尽量使用openresty提供的api

posted @ 2020-04-28 09:00  抟九  阅读(1043)  评论(1编辑  收藏  举报