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

09 | 为什么 lua-resty-core 性能更高一些?

性能优化方法
避免写出不能被JIT的代码
FFI的性能提升
比较lua-nginx-module和lua-resty-core
API实现
性能优化
内存泄漏问题
资源管理原则
性能更高
使用FFI重新实现API
无法被JIT优化
参数传递
ngx_http_lua_ngx_decode_base64
可被JIT跟踪并优化
交互部分用Lua实现
与 LuaJIT中的FFI相比
调用 C 函数
调用已有的 C 函数和数据结构
嵌入式开发语言
下一步
性能测试
lua-resty-core开启
LuaJIT FFI GC
lua-resty-core
Lua CFunction
LuaJIT FFI
Lua C API
Lua
为什么 lua-resty-core 性能更高一些?

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

你好,我是温铭。
前面两节课我们说了,Lua 是一种嵌入式开发语言,核心保持了短小精悍,你可以在 Redis、NGINX 中嵌入 Lua,来帮助你更灵活地完成业务逻辑。同时,Lua 也可以调用已有的 C 函数和数据结构,避免重复造轮子。
在 Lua 中,你可以用 Lua C API 来调用 C 函数,而在 LuaJIT 中还可以使用 FFI。对 OpenResty 而言:
在核心的 lua-nginx-module 中,调用 C 函数的 API,都是使用 Lua C API 来完成的;
而在 lua-resty-core 中,则是把 lua-nginx-module 已有的部分 API,使用 FFI 的模式重新实现了一遍。
看到这里你估计纳闷了:为什么要用 FFI 重新实现一遍?
别着急,让我们以 ngx.base64_decode 这个很简单的 API 为例,一起看下 Lua C API 和 FFI 的实现有何不同之处,这样你也可以对它们的性能有个直观的认识。

Lua CFunction

我们先来看下, lua-nginx-module 中用 Lua C API 是如何实现的。我们在项目的代码中搜索 decode_base64,可以找到它的代码实现在 ngx_http_lua_string.c 中:
lua_pushcfunction(L, ngx_http_lua_ngx_decode_base64);
lua_setfield(L, -2, "decode_base64");
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Lua-resty-core 是一个性能更高的工具,通过使用 FFI 重新实现了 `lua-nginx-module` 中的部分 API,并且可以被 JIT 跟踪并进行优化。文章介绍了 Lua C API 和 FFI 的实现对比,以及 LuaJIT FFI GC 的使用原则,强调了在使用 FFI 时需要注意内存管理和内存泄漏问题。此外,还提到了 OpenResty 提供的测试和调试工具,如 Valgrind、lj-gc 和 lgc 等,帮助开发者定位和解决内存问题。文章内容涉及技术细节丰富,适合对 OpenResty 和 LuaJIT 感兴趣的开发者阅读学习。 在比较 Lua C API 和 FFI 的实现中,FFI 的方式不仅代码更简洁,而且可以被 LuaJIT 优化,因此是更优的选择。实际上,CFunction 的实现方式已经被 OpenResty 废弃,相关的实现也从代码库中移除了。新的 API 都通过 FFI 的方式在 `lua-resty-core` 仓库中实现。在 OpenResty 2019 年 5 月份发布的 1.15.8.1 版本前,`lua-resty-core` 默认是不开启的,而这不仅会带来性能损失,更严重的是会造成潜在的 bug。因此,建议历史版本的用户手动开启 `lua-resty-core`。在 1.15.8.1 版本中,已经增加了 `lua_load_resty_core` 指令,默认开启了 `lua-resty-core`。 除了重新实现了部分 lua-nginx-module 项目中的 API,`lua-resty-core` 还实现了不少新的 API,如 ngx.ssl、ngx.base64、ngx.errlog、ngx.process、ngx.re.split、ngx.resp.add_header、ngx.balancer、ngx.semaphore 等。文章最后指出,虽然 FFI 高效,但并非性能银弹,主要原因是可以被 JIT 追踪并优化。如果写的 Lua 代码不能被 JIT,而是需要在解释模式下执行,那么 FFI 的效率反而会更低。建议读者进行性能测试比较 lua-nginx-module 和 lua-resty-core 中存在的 API,以了解 FFI 的性能提升。

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

全部留言(11)

  • 最新
  • 精选
  • 黑铁打野王
    nginx version: openresty/1.13.6.2 1. lua-nginx-module resty -e "local start = ngx.now(); for _ =1, 1000000000 do ngx.encode_base64('123456') end ngx.update_time(); ngx.say(ngx.now() - start)" 79.530000209808 2. lua-resty-core resty -e "require 'resty.core'; local start = ngx.now(); for _ =1, 1000000000 do ngx.encode_base64('123456') end ngx.update_time(); ngx.say(ngx.now() - start)" 8.944000005722 一个79.5s 一个8.9s

    作者回复: 差不多 10 倍的性能差异

    2019-06-18
    6
    18
  • 微风吹了个吹
    温老师, 1.15.8的opnresty默认是开启GC64的,是不是可以理解为这里ffi.C.malloc与ffi.new就没啥区别了?官方的更新日志```change: we now enable the GC64 mode by default in our bundled LuaJIT build for x86_64 architectures; this can be disabled using --without-luajit-gc64. Thanks Thibault Charbonnier for the patch```

    作者回复: 是的

    2019-06-17
    2
    7
  • HelloBug
    假设使用decode_base64函数,lua-resty-core不开启的时候,使用的函数就是lua-nginx-module中实现的,而开启的话就是使用lua-resty-core中实现的?

    作者回复: 是的

    2019-06-15
    7
  • 英雄
    看不懂

    作者回复: 知道 lua-resty-core 是使用 FFI 实现的 API 就行了,细节看不懂没有关系。

    2019-06-15
    4
  • 写点啥呢
    请问老师,ffi和cfunction的性能差异是不是主要是有LuaJIT的实时编译优化带来的?除此之外还有哪些因素导致了这两者之间的性能差异呢?

    作者回复: 主要是这个原因

    2019-08-29
    2
    1
  • HelloBug
    如何理解FFI的交互部分是用lua实现的,这部分代码可以被JIT跟踪到? LuaCFuncion:ngx_http_lua_ngx_decode_base64整个函数都不能被JIT追踪到,而函数ngx.decode_base64可以被JIT追踪到,只有里面的函数C.ngx_http_lua_ffi_decode_base不能被追踪到是吗?也就是C.ngx_http_lua_ffi_decode_base函数可以被JIT编译优化?

    作者回复: LuaJIT 是运行 Lua 代码的,自然只能 JIT 它其中的 Lua 代码,CFunction 的自然无能为力。

    2019-06-15
    2
    1
  • helloworld
    老师,lua-resty-core和lua-nginx-module各自都有哪些API,怎么查呢

    作者回复: 要分别查看这两个仓库的文档了

    2019-06-14
    1
  • Geek_e553fa
    沙发。希望多点实例。还有讲讲全局变量申请使用的一些替代方案。不是否定了不给解决办法

    作者回复: 可以使用模块中的 top level 局部变量来替代,这个后面会提到。 在 OpenResty 中所有变量都要加 local。

    2019-06-14
    1
  • 旺旺
    我是1.15.8.1版本的,用了前面同学给的代码,跑起来,时间相差很少,一个38.133000135422秒,一个37.325000047684秒。这是为啥?

    作者回复: 因为从1.15.8.1版本开始,默认开了 lua-resty-core

    2019-06-19
    4
  • geraltlaush
    跨语言调用的话,函数调用返回都是通过函数栈来传递嘛,比如go调用C,是不是有点主题无关哈,希望老师解答下
    2019-07-02
    1
收起评论
显示
设置
留言
11
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部