ThinkPHP3.2日志内存开销源于Log::record()将日志持续追加至静态数组self::$Log,默认不设LOG_WRITE_INTERVAL导致请求结束才一次性刷盘,若高频调用且未显式调用Log::save(),数组不断增长引发内存膨胀。

要查看ThinkPHP3.2中内存开销的记录流程,必须定位到其日志写入机制的核心——Log::record()方法如何将日志暂存于内存数组并最终刷盘,否则仅看配置或调用日志接口无法发现内存持续增长的根源。
确认日志是否启用内存缓冲
打开 thinkphp/Extend/Library/Think/Log.class.php,查找 record() 方法体内的关键逻辑:它会先将日志内容追加进静态属性 $Log(即 self::$Log[] = $log;),而非立即写入文件。该行为由 LOG_WRITE_INTERVAL 常量控制,默认未定义,因此全程走内存累积路径。
这一步不可跳过——若项目中自定义了 LOG_WRITE_INTERVAL = 100,则每100条日志自动落盘并清空数组;但ThinkPHP3.2官方默认不设此常量,【$Log 数组会随请求生命周期不断增长,直到脚本结束才一次性 flush】。
定位内存累积触发点
在入口文件 index.php 顶部添加临时调试代码:
立即学习“PHP免费学习笔记(深入)”;
register_shutdown_function(function() { echo 'Log count: ' . count(Think\Log::$Log) . ', Mem: ' . round(memory_get_usage(true)/1024/1024, 2) . " MB\n"; });
访问任意页面,观察终端或响应体输出。若 Log count 超过 500 或内存增量超过 2MB,说明日志已成内存负担主因。
注意:此统计不含 G() 打点数据,仅反映 Log::record() 的累积量;G() 的内存开销在另一静态数组中独立维护。
追踪日志写入时机
第一步:搜索项目中所有 Log::record(、trace(、Think\Log::save() 的调用位置;
第二步:检查是否在循环、钩子函数(如 _initialize)、模板标签({:trace()})中高频调用;
第三步:确认 Log::save() 是否被显式调用——只有该方法才会触发 file_put_contents($filename, implode("", self::$Log)) 并重置 self::$Log = array();
第四步:若未手动调用 save(),则整个请求周期内 self::$Log 不释放,且每次 record() 都增加新元素,【字段越多、SQL 日志越全、堆栈越深,单条日志字符串越大,内存膨胀越快】。



















