PHP 内存分析器:定位线上 PHP 进程中最大的内存对象
要找出运行中的 PHP 进程到底把内存耗在哪里,用 OpenResty XRay 剖析它即可:它会挂载到未经修改的进程上,按占用内存对存活的 PHP 对象排序,并通过数据引用路径把最大的那个对象追溯到确切的源码行——无需修改代码,也无需重启。
本教程将结合 OpenResty XRay 的引导式分析,以及我们自己发明的 PHP 对象内存分布火焰图,完整演示这一过程——案例中,一个 controller 持有的单个 40MB 的 HTML 字符串就是元凶。
现象: PHP 进程在 top 中占用大量内存
先运行 top 命令查看内存占用。可以看到,这个 php 进程消耗了最多的内存——超过了 37MB 的 RSS。
让我们运行 ps 命令来查看这个进程的更多细节。可以看到,这个进程使用的 PHP 二进制可执行文件,是 Linux 发行版自带的。
我们可以使用 OpenResty XRay 来检查这个未经修改的进程。系统可以对它进行实时分析,并找出内存具体耗费在哪里。
用 OpenResty XRay 引导式分析找出最大的 PHP 对象
在浏览器中打开 OpenResty XRay 的 Web 控制台,确保当前分析的机器是正确的。进入 “Guided Analysis” 页面,这里可以看到 OpenResty XRay 能诊断的各类问题。
选择 “High memory usage”,选中之前的 PHP 应用以及 top 标记出来的那个进程(占用超过 35MB RSS 的那个),保持 PHP 和 C/C++ 两个语言级别都选中,然后开始分析。经过一到两轮分析后,OpenResty XRay 会自动生成一份报告。在 PHP-Land 下,它会展示占用最多内存的 PHP 内存对象引用路径。
可以看到,网页的 HTML 源码字符串占用了约 40MB 的内存资源。
productPage 是 controller 的一个属性,用于储存这个字符串。
Illuminate\Routing\Route 类的主要功能是将 URL 请求映射到 controller 方法。
这条数据引用路径,是从下面这张 PHP 语言级别的 GC 对象内存分布火焰图中自动推导出来的。
把最大的对象追溯到它的源码行
从引用路径中复制 productPage 属性,跳转到 PHP 应用的源代码目录,用 grep 命令搜索包含 productPage 变量标识符的文件。
这是赋值语句的源码行号——ProdController.php 第 40 行。
用编辑器打开源文件。这里是定义属性的地方。
跳转到第 40 行。$this->productPage = file_get_contents($file_path) 这条语句一次性把整个页面读入内存,从而创建了这个大内存对象。我们建议改用流式响应对内存使用进行优化。
用 Insights 报告自动监控 PHP 进程内存
OpenResty XRay 也可以自动监控在线进程并显示分析报告。在 “Insights” 页面中,您可以找到以日和周为周期的报告,这样您就不必手动运行引导式分析了——当然,“Guided Analysis” 对于应用的开发和演示仍然很有用。
常见问题
如何找出哪个 PHP 进程占用了最多内存?
运行 top 命令——php 进程会显示为占用内存最多的那个,本例中超过 37MB。运行 ps 查看更多细节;这里它是 Linux 发行版自带的标准 PHP 二进制。随后 OpenResty XRay 会分析这个进程,找出内存具体耗费在哪里。
可以在不修改代码、不重启的情况下剖析 PHP 内存占用吗?
可以。OpenResty XRay 会实时分析未经修改的、运行中的 PHP 进程——本例中就是 Linux 发行版自带的标准 PHP 二进制。因为它直接作用于原样的进程,所以您无需修改或重启应用就能看清内存去向。
什么是 PHP 内存对象引用路径?
它是指向占用最多内存的对象的引用路径——本例中,就是存储在某个 controller 的 productPage 属性中、近 40MB 的 HTML 字符串,以及负责将请求映射到该 controller 的 Route 类。OpenResty XRay 会从 PHP 语言级别的 GC 对象内存分布火焰图中自动推导出这条路径。
如何降低某个大 PHP 对象导致的高内存占用?
把最大的对象追溯到创建它的源码行——本例中,就是那条对 productPage 属性赋值、创建了大内存对象的语句。OpenResty XRay 的报告建议改用流式响应来优化内存使用。
关于 OpenResty XRay
OpenResty XRay 是一个动态追踪产品,它可以自动分析运行中的应用,以解决性能问题、行为问题和安全漏洞,并提供可行的建议。在底层实现上,OpenResty XRay 由我们的 Y 语言驱动,可以在不同环境下支持多种不同的运行时,如 Stap+、eBPF+、GDB 和 ODB。
关于作者
章亦春是开源 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. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:
翻译
我们提供了英文版原文和中译版(本文)。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!
































