本教程演示了在OpenResty中对用户Lua代码进行基准测试的正确方法和错误方法。

1
2
3
cd ~
mkdir time-lua
cd time-lua/

首先,要保证我们的CPU始终处于全速运转状态。

1
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

截图2

它通常默认取值powersave而我们需要设置成 performance

对一些Lua代码进行计时的最简单方法是使用time命令和resty命令。

1
time resty -e 'ngx.re.find("hello, world.", [[\w+\.]], "jo")'

截图4

但这种方法有一个问题。resty命令本身有一个启动和退出的开销。

1
time resty -e ''

截图6

我们可以看到在这台机器上的开销大约有11毫秒。

相反,我们应该使用OpenResty提供的ngx.now Lua API函数。

1
restydoc -s ngx.now

截图8

让我们把我们的Lua代码放到一个名为./bench.lua的文件中,以便更好地阅读。

我们进行以下编辑:

1.首先,我们要确保nginx里面的缓存时间是最新的。 2.然后我们记录的开始时间有毫秒的精度。 3.然后把我们前面提到的正则匹配调用。 4.然后我们再更新缓存时间。 5.最后,通过做时间减法输出经过的时间。 6.让我们保存文件。

1
2
3
4
5
ngx.update_time()
local begin = ngx.now()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
ngx.update_time()
ngx.say("elapsed seconds: ", ngx.now() - begin)

截图15

然后运行resty这个shell命令。

1
resty bench.lua

截图18

它记录的延迟时间大约是1毫秒。但我们很快就会发现它很不准确。

正确的方法是在bench.lua文件中做如下编辑:

1.把调用放到一个名为target的Lua函数中。 2.然后先调用这个函数100次作为热身。现在这个target函数应该在这个循环执行完后进行JIT编译。 3.然后在定时码区域里面,我们反复调用1000万次。 4.最后我们计算平均时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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)

截图25

我们现在再次运行这个脚本。

1
resty bench.lua

截图26

我们可以看到,每次调用仅仅是30纳秒左右。比之前的结果快了很多很多倍!

实际上,我们可以进一步确保在我们给代码计时之前,没有死掉的GC对象还没有被回收,只要在第一个ngx.update_time()调用之前插入以下一行代码。只需在第一个ngx.update_time()调用之前插入以下一行代码。

1
collectgarbage()

截图29

在这里,我们强制执行一个完整的GC周期,然后再记录开始时间。

但是,它对我们这里的例子没有什么帮助。这是因为我们的定时代码无论如何也不会创建很多GC对象。

我们可以通过避免不必要的Lua表查找操作,使target函数更快。

1
2
3
4
5
local re_find = ngx.re.find

local function target()
re_find("hello, world.", [[\w+\.]], "jo")
end

截图33

但这里的差别可能比较小。

截图35

这就是我今天要讲的内容。希望你觉得有趣。

如果你喜欢这个视频,请订阅我们的 YouTube 频道B 站频道。谢谢!

关于本文和关联视频

本文和相关联的视频都是完全由我们的 OpenResty Demo 系统从一个极简单的剧本文件自动生成的。

关于作者

章亦春是开源项目 OpenResty® 的创始人,同时也是 OpenResty Inc. 公司的创始人和 CEO。他贡献了许多 Nginx 的第三方模块,相当多 Nginx 和 LuaJIT 核心补丁,并且设计了 OpenResty XRay 等产品。

关注我们

如果您觉得本文有价值,非常欢迎关注我们 OpenResty Inc. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:

我们的微信公众号

翻译

我们提供了英文版原文和中译版(本文) 。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!