OpenResty 从入门到实战
温铭
OpenResty 软件基金会第一任主席,Apache APISIX 项目 VP
20903 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 52 讲
结束语 (1讲)
OpenResty 从入门到实战
15
15
1.0x
00:00/00:00
登录|注册

10 | JIT编译器的死穴:为什么要避免使用 NYI ?

string.find
string.dump
string.char
string.byte
string 库函数
unpack() 函数
pairs() 函数
无法编译的原语
不完善
机器代码生成
默认打开优化选项
封装函数
jit.v
jit.dump
数字下标访问
避免使用
数组下标访问
PCRE JIT
ngx.re.find
plain 模式
PCRE JIT
ngx.re.gsub
JIT 编译器
性能优化
自动化检测
避免在热代码路径使用
OpenResty API
resty -j v
jit.v
jit.dump
pairs() 函数
unpack() 函数
string.find() 函数
string.gsub() 函数
LuaJIT
Not Yet Implemented
总结
如何检测 NYI
NYI 的替代方案
NYI
JIT编译器的死穴

该思维导图由 AI 生成,仅供参考

你好,我是温铭。
上一节,我们一起了解了 LuaJIT 中的 FFI。如果你的项目中只用到了 OpenResty 提供的 API,没有自己调用 C 函数的需求,那么 FFI 对你而言并没有那么重要,你只需要确保开启了 lua-resty-core 即可。
但我们今天要讲的 LuaJIT 中 NYI,却是每一个使用 OpenResty 的工程师都逃避不了的关键问题,它对于性能的影响举足轻重。
你可以很快使用 OpenResty 写出逻辑正确的代码,但不明白 NYI,你就不能写出高效的代码,无法发挥 OpenResty 真正的威力。这两者的性能差距,至少是一个数量级的。

什么是 NYI?

那究竟什么是 NYI 呢?先回顾下我们之前提到过的一个知识点:
LuaJIT 的运行时环境,除了一个汇编实现的 Lua 解释器外,还有一个可以直接生成机器代码的 JIT 编译器。
LuaJIT 中 JIT 编译器的实现还不完善,有一些原语它还无法编译,因为这些原语实现起来比较困难,再加上 LuaJIT 的作者目前处于半退休状态。这些原语包括常见的 pairs() 函数、unpack() 函数、基于 Lua CFunction 实现的 Lua C 模块等。这样一来,当 JIT 编译器在当前代码路径上遇到它不支持的操作时,便会退回到解释器模式。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

JIT编译器的死穴:避免使用NYI JIT编译器的Not Yet Implemented(NYI)在OpenResty中是一个关键问题,影响性能。本文介绍了NYI的概念和影响,以及在实际开发中避免使用NYI的替代方案。作者提到了几个典型的NYI函数,如string.gsub()、string.find()、unpack()和pairs(),并分别介绍了它们的替代方案。对于string.gsub()函数,可以使用OpenResty自己的API ngx.re.gsub,并开启PCRE的JIT选项;对于string.find()函数,需要区分固定字符串和正则表达式的查找,并使用ngx.re.find()来完成;对于unpack()函数,建议使用数组下标的方式来访问;而对于pairs()函数,作者指出没有等价的替代方案,建议尽量避免使用或者改用数字下标访问的数组。读者需要注意优先使用OpenResty提供的API,避免使用NYI原语,并确保避免在代码热路径上使用NYI原语。此外,文章还介绍了如何使用LuaJIT自带的jit.dump和jit.v模块来自动检测代码中使用到的NYI,以及如何简单验证使用resty。通过具体的例子和替代方案,帮助读者更好地理解和规避NYI原语的使用,以提高性能。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《OpenResty 从入门到实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(23)

  • 最新
  • 精选
  • 对于一个OpenResty入门者一开始讲这些性能和低层的知识有些枯燥了,毕竟还没写过几个OpenResty的实例,对性能的差异没什么感觉,基础知识还没掌握全更难深入底层。有如学习java的初学者一开始就看《Java编程思想》。可否尝试在后面的实际例子中引出这些知识点。

    作者回复: 后面会专门介绍 OpenResty 的 Lua API。LuaJIT 的这些内容有个印象即可。

    2019-06-17
    21
  • 燕羽阳
    1. lua的语法比较简单,如果有编程基础的话,一天就可以入门了。推荐大家两本书《lua程序设计》lua入门必备,《lua设计与实现》深入解释器虚拟机的原理。 2. 之前写过一点openresty和kong,但是从没注意过性能问题。今天的NYI,老师讲的非常棒,完整的实战方案,超赞👍 3.我对jit完全不熟悉,请问老师,jit是按照函数为单位来编译么?函数中有一个NYI,整个函数就是解释运行么?

    作者回复: 是按照原语来编译的,也就是 `ipairs` 、`string.find` 这种的颗粒度,并不是你自己写的 function

    2019-06-17
    2
    7
  • helloworld
    老师,下面这个设置lua库的搜索路径的代码,最后为什么要拼接package.path本身啊? package.path = "../myLuaTest/myLuaCode/?.lua;"..package.path

    作者回复: package.path 是默认的查找路径,你可以单独把它 print 出来看下里面的值。不拼接的话,就把默认查找路径全都覆盖掉了。

    2019-06-17
    4
  • Geek_89bbab
    希望老师分享一下写 openresty代码时用什么编辑器比较好,代码补全,定义跳转,引用跳转等如何配置。老师你们写openresty的时候是怎么来做的?直接vim操作,还是有更智能些的IDE?

    作者回复: 现在还没啥好用的编辑器,我用的是 vs code

    2019-06-17
    4
  • NEVER SETTLE
    经常会发现openresty运行一段时间,性能会差很多。然后reload一下性能会好很多。这个问题一直困扰很久了,不知道如何进行排查。 以前两天的情况,高峰期CPU使用率超过了60%,然后reload一下,CPU使用率就降为30%。

    作者回复: 需要用火焰图分析下 on-cpu 才行

    2019-06-19
    3
  • 涉蓝
    对于初学者是不是 要先学 lua -> luajit -> openresty api -> 其他第三方包 按这种先把 文档啥的都扒一遍才行呢? 我对于使用有点疑惑,openresty可以做 网站普通后端语言可以做的事 譬如连数据库做前端页面 但这显然并不是它主要适合的部分吧 毕竟其他后端语言一大把,文档生态库好的多的是 所以是API 网关的 开发 或者 nginx 无法配置热修改的 补充吗?

    作者回复: 这个问题其实要回到 OpenResty 诞生的那个时候来看, 2007 年,支持同步非阻塞的语言凤毛麟角。 即使是现在,后端语言可以达到 OpenResty 这种性能级别的也不多。 API 网关和软 WAF 算是开发者的自然选择,OpenResty 其实能做的不止这些。

    2019-06-17
    2
  • Forturn
    楼上说的有道理,目前还没掌握基本的语法,还不会写一些基本的功能,就去学底层的东西,有点摸不着头脑,也不懂这些。不知道后面会不会具体事例

    作者回复: 看不懂没有关系,重要的是记得有LuaJIT 和 NYI 这个东西,后面遇到问题方便查找。

    2019-06-17
    2
  • KoALa
    教程中反复提到了“LuaJIT 的作者目前处于半退休状态”,感觉这个情况很不乐观啊...

    作者回复: Kong 和 OpenResty 的团队中,都有人在逐步接手。开源项目只要有人在使用,就不会死掉,不用担心。

    2019-07-25
    1
  • 莫然
    pairs的例子稍作修改,如下: local t = {} for i=1,100 do t[i] = i end for j=1,10 do for k,v in pairs(t) do -- end end jit.log里输出的是:[TRACE 1 t.lua:123 loop] 如果改成如下代码: for j=1,100 do for k,v in pairs(t) do -- end end jit.log里输出的是: [TRACE 1 t.lua:123 loop] [TRACE --- t.lua:128 -- NYI: bytecode 72 at t.lua:129] [TRACE --- t.lua:128 -- NYI: bytecode 72 at t.lua:129] 为什么循环10的时候没有NYI的提示?

    作者回复: LuaJIT 的优化是随机触发的,要足够热才可能尝试去优化

    2019-07-11
    1
  • John
    老师,我在用op实现一个自定义逻辑的风控系统,想请教一下动态配置生效的问题,如何在不reload的情况下使配置生效,我想了两个办法:1,使用全局变量存储配置文件,提供一个api更新全局变量;2,使用ngx.shared.DICT,将配置文件存储在共享内存中。请问是否合理,或者是否有其它思路

    作者回复: 你可以使用一个 timer,定时的查询是否有新的配置,并把新配置写到类似 shared dict 的缓存中。

    2019-06-18
    2
    1
收起评论
显示
设置
留言
23
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部