完整课程入口:996 全套课程体系 | Lua 学习路径 | 幂尔框架 mirs.cn
LuaJIT 的 JIT 编译对多数代码是加速,但特定形态的函数被编译后反而更慢:偶尔回调一次的函数(编译成本收不回)、依赖解释器副作用的逻辑、与调试钩子冲突的代码。jit.off 提供函数级与全局级的关闭开关,知道"哪里该关"与知道"哪里该开"同样重要。
local function rareCallback(...)
jit.off(true, true) -- 关闭当前函数与其内部循环的编译
-- 一次性回调逻辑
end
-- 或对指定函数整体关闭
jit.off(someHeavySetupFn, true)
jit.off(fn, true) 关闭指定函数的编译,第二个参数同时作用于其内嵌套函数。适用判断:函数调用频率低于每秒 1 次且单次耗时低于 1ms 的,编译收益接近于零,显式关闭可省去 trace 录制的开销。
jit.off()(无参数)关闭整个 VM 的 JIT。两个合理场景:一是调试期——trace 行为干扰断点与变量观察时临时关闭;二是兼容期——发现某批代码在 JIT 下触发引擎 bug(LuaJIT 2.0 时代的已知问题),在修复前整体回退。长期全局关闭等于放弃 LuaJIT 的核心价值,属于最后手段。
每个"该不该关"的问题用三步回答:第一步,jit.attach 或 -jv 确认该函数的 trace 状态(编译成功率);第二步,对照测试——开与关各跑 1000 次取平均耗时;第三步,只有关闭后更快(或为了绕开 bug)才写入 jit.off,并把原因写进注释。某项目的统计结论:全局开启 JIT 下,约 85% 的函数受益、10% 无差异、5% 反而变慢——jit.off 的价值就是精准处理那 5%。反向操作 jit.on(fn, true) 可对关闭的区域重新开启,配置集中管理便于整体回退。
jit.off 与 trace abort 的关系容易混淆:abort 是编译失败退回解释执行,jit.off 是主动声明不编译。排查时先用 -jv 看 abort 记录,确认某函数反复录制反复失败后,再对它显式 jit.off,避免无意义的重复录制开销。两者配合使用的项目实测能减少两成左右的调度损耗。