在 OpenResty 中正确地测量 Lua 代码的执行时间
本教程演示了在 OpenResty 中对用户 Lua 代码进行基准测试的正确方法和错误方法。
cd ~
mkdir time-lua
cd time-lua/
首先,要保证我们的 CPU 始终处于全速运转状态。
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
它通常默认取值 powersave
而我们需要设置成 performance
。
对一些 Lua 代码进行计时的最简单方法是使用 time
命令和 resty
命令。
time resty -e 'ngx.re.find("hello, world.", [[\w+\.]], "jo")'
但这种方法有一个问题。resty
命令本身有一个启动和退出的开销。
time resty -e ''
我们可以看到在这台机器上的开销大约有 11 毫秒。
相反,我们应该使用 OpenResty 提供的ngx.now
Lua API函数。
restydoc -s ngx.now
让我们把我们的 Lua 代码放到一个名为 ./bench.lua
的文件中,以便更好地阅读。
我们进行以下编辑:
- 首先,我们要确保 nginx 里面的缓存时间是最新的。
- 然后我们记录的开始时间有毫秒的精度。
- 然后把我们前面提到的正则匹配调用。
- 然后我们再更新缓存时间。
- 最后,通过做时间减法输出经过的时间。
- 让我们保存文件。
ngx.update_time()
local begin = ngx.now()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
ngx.update_time()
ngx.say("elapsed seconds: ", ngx.now() - begin)
然后运行 resty
这个 shell 命令。
resty bench.lua
它记录的延迟时间大约是 1 毫秒。但我们很快就会发现它很不准确。
正确的方法是在 bench.lua
文件中做如下编辑:
- 把调用放到一个名为
target
的 Lua 函数中。 - 然后先调用这个函数 100 次作为热身。现在这个
target
函数应该在这个循环执行完后进行 JIT 编译。 - 然后在定时码区域里面,我们反复调用 1000 万次。
- 最后我们计算平均时间。
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
target()
end
ngx.update_time()
ngx.say("elapsed: ", (ngx.now() - begin) / N)
我们现在再次运行这个脚本。
resty bench.lua
我们可以看到,每次调用仅仅是 30 纳秒左右。比之前的结果快了很多很多倍!
实际上,我们可以进一步确保在我们给代码计时之前,没有死掉的 GC 对象还没有被回收,只要在第一个 ngx.update_time()
调用之前插入以下一行代码。只需在第一个 ngx.update_time()
调用之前插入以下一行代码。
collectgarbage()
在这里,我们强制执行一个完整的 GC 周期,然后再记录开始时间。
但是,它对我们这里的例子没有什么帮助。这是因为我们的定时代码无论如何也不会创建很多 GC 对象。
我们可以通过避免不必要的 Lua 表查找操作,使 target
函数更快。
local re_find = ngx.re.find
local function target()
re_find("hello, world.", [[\w+\.]], "jo")
end
但这里的差别可能比较小。
这就是我今天要讲的内容。希望你觉得有趣。 如果你喜欢这个教程,请订阅这个博客网站和我们的 YouTube 频道 或 B 站频道。谢谢!
关于本文和关联视频
本文和相关联的视频都是完全由我们的 OpenResty Showman 产品从一个简单的剧本文件自动生成的。
关于作者
章亦春是开源 OpenResty® 项目创始人兼 OpenResty Inc. 公司 CEO 和创始人。
章亦春(Github ID: agentzh),生于中国江苏,现定居美国湾区。他是中国早期开源技术和文化的倡导者和领军人物,曾供职于多家国际知名的高科技企业,如 Cloudflare、雅虎、阿里巴巴, 是 “边缘计算“、”动态追踪 “和 “机器编程 “的先驱,拥有超过 22 年的编程及 16 年的开源经验。作为拥有超过 4000 万全球域名用户的开源项目的领导者。他基于其 OpenResty® 开源项目打造的高科技企业 OpenResty Inc. 位于美国硅谷中心。其主打的两个产品 OpenResty XRay(利用动态追踪技术的非侵入式的故障剖析和排除工具)和 OpenResty Edge(最适合微服务和分布式流量的全能型网关软件),广受全球众多上市及大型企业青睐。在 OpenResty 以外,章亦春为多个开源项目贡献了累计超过百万行代码,其中包括,Linux 内核、Nginx、LuaJIT、GDB、SystemTap、LLVM、Perl 等,并编写过 60 多个开源软件库。
关注我们
如果您喜欢本文,欢迎关注我们 OpenResty Inc. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:
翻译
我们提供了英文版原文和中译版(本文) 。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!