PhpStorm Memory Profiler 跟踪对象创建、引用关系和变量生命周期,不显示总内存;需 Xdebug 启用 debug 模式及 collect_params=4、collect_return=1,仅支持 CLI;Retained Size 比 Shallow Size 更关键;__PHP_Incomplete_Class 表明反序列化类缺失。

PhpStorm Memory Profiler 能看到什么
它不显示 PHP 进程总内存(比如 memory_get_peak_usage() 那种),而是跟踪对象创建、引用关系和变量生命周期,帮你定位“谁在持续占着内存不放”。典型场景包括:循环中反复 new 对象没 unset、静态属性缓存了大量数据、闭包意外捕获了大数组。
Memory Profiler 依赖 Xdebug 的 xdebug.mode=debug,develop(不是 profile)且必须启用 xdebug.collect_params=4 和 xdebug.collect_return=1,否则只看到“某函数分配了内存”,看不到具体是哪个变量、哪行代码。
- 仅对 CLI 运行的脚本有效 —— Web 请求无法触发 Memory Profiler,PhpStorm 的
Run → Profile按钮底层调用的是php -dxdebug.mode=debug ... - 结果里“Retained Size”比“Shallow Size”更重要:前者是你删掉这个对象后能真正释放的内存,后者只是对象自身字段占的字节
- 如果看到大量
__PHP_Incomplete_Class实例,说明 unserialize 时类定义缺失,反序列化失败但内存已分配
为什么点“Profile”没弹出内存报告
常见原因是 CLI 和 Web 使用了不同 php.ini,而 Memory Profiler 只读 CLI 配置。先确认 PhpStorm 用的 CLI 解释器路径:Ctrl+Alt+S → PHP → CLI Interpreter → Configuration file,然后打开该文件检查:
-
xdebug.mode必须包含debug(如xdebug.mode=debug,develop),profile模式下 Memory Profiler 不工作 -
xdebug.collect_params=4缺失会导致无法追踪参数级内存分配(尤其数组/对象传参) -
xdebug.max_nesting_level太小(默认 256)会提前中断采集,建议设为500或更高 - 目录
/tmp/xdebug若被 PHP-FPM 的clear_env清掉环境变量,可能导致xdebug.output_dir无效 —— 改用项目内绝对路径更稳,比如/var/www/myapp/runtime/xdebug
如何看懂 Memory Profiler 的“Object Tree”视图
打开报告后,默认是 “Live Objects” 列表,但真正有用的是右键某个类名 → Show Retained Objects 进入 “Object Tree”。这里每条路径代表一个存活对象的引用链:
立即学习“PHP免费学习笔记(深入)”;
- 路径末尾的
→ [array]或→ [object]是实际内存占用者;中间的→ Closure或→ static property是“卡住它不释放”的根因 - 若发现
Doctrine\ORM\EntityManager下挂了数百个Proxy对象,大概率是没调用$em->clear()导致一级缓存堆积 - 搜索框输入
String或ArrayObject能快速过滤高频分配类型,结合 “Allocated” 列看单次分配大小,而非只盯总量
Memory Profiler 抓不到内存泄漏?试试这个组合
某些泄漏(比如全局变量引用、扩展层资源未释放)Xdebug 本身不感知。这时要配合手动采样 + 对比:
- 在疑似泄漏前加
echo memory_get_usage() . "\n";,泄漏后加一次,差值就是粗略增长量 - 用
gc_collect_cycles()强制触发 GC 后再查memory_get_usage(),如果差值大幅缩小,说明是 PHP 引用计数机制导致的“假泄漏” - 对长期运行的 CLI 命令(如队列消费者),在循环开头加
if (gc_enabled()) gc_collect_cycles();,能缓解周期性内存爬升 - 如果
memory_get_peak_usage()持续上涨且gc_collect_cycles()无效,问题可能在 C 扩展(如 Redis、cURL)——需换用valgrind --tool=memcheck深挖
strace -e trace=brk,mmap,munmap 或系统级工具交叉验证。



















