local lua 多个_Lua 级别 CPU 火焰图介绍

在 OpenResty 或 Nginx 服务器中运行 Lua 代码如今已经变得越来越常见,因为人们希望他们的非阻塞的 Web 服务器能够兼具超高的性能和很大的灵活性。

有些人使用 Lua 完成一些非常简单的任务,比如检查和修改某些请求头和响应体数据,而有些人则利用 Lua 创建非常复杂的 Web 应用、 CDN 软件和 API 网关等等。Lua 以简单、内存占用小和运行效率高而著称,尤其是在使用LuaJIT这样的的即时编译器 (JIT) 的时候。

但有些时候,在 OpenResty 或 Nginx 服务器上运行的 Lua 代码也会消耗过多的 CPU 资源。通常这是由于程序员的编程错误,比如调用了一些昂贵的 C/C++ 库代码,或者其他原因。

要想在一个 在线的 OpenResty 或 Nginx 服务器中快速地定位所有的 CPU 性能瓶颈,最好的方法是使用OpenResty XRay产品提供的 Lua 语言级别 CPU 火焰图的采样工具。这个工具 不需要 对 OpenResty 或 Nginx 的目标进程做任何修改,也不会对生产环境中的进程产生任何可觉察的影响。

本文将解释什么是火焰图,以及什么是 Lua 级别的 CPU 火焰图,会穿插使用多个小巧且独立的 Lua 代码实例来做演示。我们将利用 OpenResty XRay来生成这些示例的火焰图来进行讲解和分析。

我们选择小例子的原因是,它们更容易预测和验证各种性能分析的结果。相同的分析方法和工具也适用于那些最复杂的 Lua 应用。

过去这几年,我们使用这种技术和可视化方式,成功地帮助了许多拥有繁忙网站或应用的企业客户。

点击申请试用 OpenResty XRay

什么是火焰图

火焰图是由 Brendan Gregg 发明的一种可视化方法,用于展示某一种系统资源或性能指标,是如何定量分布在目标软件里所有的代码路径上的。

这里的“系统资源”或指标可以是 CPU 时间、off-CPU 时间、内存使用、硬盘使用、延时,或者任何其他你能想到的资源。

而“代码路径”可以定义为目标软件代码中的调用栈轨迹。调用栈轨迹通常是由一组函数调用帧组成的,通常出现在 GDB 命令 bt 的输出中,以及 Python 或 Java 程序的异常错误信息当中。比如下面是一个 Lua 调用栈轨迹的样例:

C:ngx_http_lua_ngx_timer_at
at
cache.lua:43
cache.lua:record_timing
router.lua:338
router.lua:route
v2_routing.lua:1214
v2_routing.lua:route
access_by_lua.lua:130

在这个例子中,Lua 栈是从基帧 access_by_lua.lua:130 一路生长到顶帧 C:ngx_http_lua_ngx_timer_at。它清晰地显示了不同的 Lua 或 C 函数之间是如何相互调用的,从而构成了“代码路径”的一种近似表示。

而上文中的“所有代码路径”,实际上是从统计学的角度来看,并不是要真的要去枚举和遍历程序中的每一条代码路径。显然在现实中,后者的开销极其高昂,因为组合爆炸的问题。我们只要确保所有那些开销不太小的代码路径,都有机会出现在我们的图中,并且我们能以足够小的误差去量化他们的开销。

本文会聚焦在一种特定类型的火焰图上面。这种火焰图专用于展示 CPU 时间(或 CPU 资源)是如何定量分布在 所有的 Lua 代码路径上的。特别地,我们这里只关注 OpenResty 或 Nginx 目标进程里的 Lua 代码。自然地,这类火焰图被我们命名为“Lua 级别 CPU 火焰图”(Lua-land CPU Flame Graphs)。

本文标题图片是一个火焰图示例,后文将提供更多示例。

为什么需要火焰图

火焰图仅用一张小图,就可以定量展示所有的性能瓶颈的全景图,而不论目标软件有多么复杂。

传统的性能分析工具通常会给用户展示大量的细节信息和数据, 而用户很难看到全貌,反而容易去优化那些并不重要的地方,经常浪费大量时间和精力却看不到明显效果。

传统分析器的另一个缺点是,它们通常会孤立地显示每个函数调用的延时,但很难看出各个函数调用的上下文,而且用户还须刻意区分当前函数本身运行的时间(exclusive time)和包括了其调用其他函数的时间在内的总时间(inclusive time)。

而相比之下,火焰图可以把大量信息压缩到一个大小相对固定的图片当中(通常一屏就可以显示全)。不怎么重要的代码路径会在图上自然地淡化乃至消失,而真正重要的代码路径则会自然地凸显出来。越重要的,则会显示得越明显。火焰图总是为用户提供最适当的信息量,不多,也不少。

如何解读火焰图

对于新手而言,正确地解读火焰图可能不太容易。但通过一些简单的解释,用户就会发现火焰图其实很直观,很容易理解。

火焰图是一张二维图。y 轴显示是代码(或数据)上下文,比如目标编程语言的调用栈轨迹,而 x 轴则显示的是各个调用栈所占用的系统资源的比例。

整个 x 轴通常代表了目标软件所消耗的 100% 的系统资源(比如 CPU 时间)。x 轴上的各个调用栈轨迹的先后顺序通常并不重要,因为这些调用栈只是根据函数帧名的字母顺序来排列。

当然,也会有一些例外,例如笔者发明了一种 时序火焰图,其中的 x 轴实际上是时间轴,此时调用栈的先后顺序就是时间顺序。

本文将专注于讨论经典的火焰图类型,即图中 x 轴上的顺序并不重要。

要学会读懂一张火焰图,最好的方法是尝试解读真实的火焰图样本。下文将提供多个火焰图实例,针对 OpenResty 和 Nginx 服务器上运行的 Lua 应用,并提供详细的解释。

简单的 Lua 样例

本节将列举几个简单的有明显性能特征的 Lua 样例程序,并将使用 OpenResty XRay分析真实的 nginx 进程,生成 Lua 级别的 CPU 火焰图,并验证图中显示的性能情况。

我们将

你可能感兴趣的:(local,lua,多个)