在 2016年4月16日星期六 UTC+8上午3:40:03,agentzh写道:
Hello!
2016-04-13 18:11 GMT-07:00 Guanglin Lv:
> 1. 统一一个location入口,直接proxy_pass走,避免调用ngx.exec
> 2. 优化ngx.var API的调用,上下文信息传递使用ngx.ctx
ngx.ctx 也应尽量减少使用,因为 ngx.ctx 也涉及元表操作。
嗯,用的不多,不过我的用法是ngx.ctx.my_ctx是一个比较大的表,access阶段填充,后续balancer和header_filter阶段使用。
不知道是否合理哈;
>
> C/Lua层面的火焰图如附件所示。
>
从你的 C 级别火焰图上看,有如下的优化方法:
1. 尽量多地让你的热 Lua 代码路径被 JIT 编译。具体做法是:尽量使用 lua-resty-core 库,避免在热代码路径上使用
LuaJIT 的 NYI 原语 [1]. 从火焰图上看,你的绝大部分 Lua 代码都是被 LuaJIT 解释执行的,并没有被 JIT
编译(显示为那些 lj_BC_xxx 的函数帧)。
受教了,以前完全没考虑过这点,最近详细了解了下NYI,并做了下优化,几乎部分逻辑都重构了;(⊙﹏⊙)b
2. 尽量使用 table.new() 原语来预分配你的 Lua table,以避免 Lua table 的自动生长(火焰图中对应
rehashtab 和 lj_tab_resize 帧)。
嗯,已优化了; 有个疑问,loca t= {"a","b","c'}这种定义时就赋值好的表,是否也必要优化呢;
3. 启用 luajit 的 dual number 模式,以避免昂贵的浮点数到字符串的转换(火焰图中对应 lj_strfmt_num
帧)。具体做法是使用下面的命令重新编译 OpenResty:
./configure --with-luajit-xcflags="-DLUAJIT_NUMMODE=2"
值得一提的是,最新的 LuaJIT 2.1 包含了一个优化过的浮点数字符串化的实现,而并没有再使用性能较差的 glibc
里面的实现。不过最新的 OpenResty 还没有包含这么新的 LuaJIT.
目前我想到的浮点数到字符串转换的地方只有,我在header_filter阶段设置了两个处理耗时的响应头。
做到这些之后,你的 Lua 部分的损耗应该可以降低一半,甚至更多。
[1] http://wiki.luajit.org/NYI
目前尽可能优化了NYI、table后,性能上升了1千左右,达到每秒7600多,火焰图如附件。
另外请教一下,为何在init_by_lua阶段调用了require "resty.core"后性能会好非常多?而且在lua层面的火焰图里也几乎看不到业务层代码调用栈了。
反之,性能会下降很多,而且不稳定。lua层面火焰图有几乎全部的业务代码调用栈。
这是啥原理啊?是不是只在init阶段这样就好了,还是每个阶段都需要require "resty.core"
Thanks.
Attachment:
lua_land_flame_graph.svg
Description: image/svg
Attachment:
c_land_flame_graph.svg
Description: image/svg