如何在PHP中修复内存泄漏

tho*_*ter 17 php memory-leaks reference-counting

我的PHP应用程序有一个可以导入记录的导入脚本.

目前,它是从CSV文件导入的.它正在读取CSV文件的每一行,使用fgetcsv一次一行,并且对于每一行,它在该记录上进行大量处理,包括数据库查询,然后继续下一行.它不应该继续累积更多的内存.

在导入大约2500条记录之后,PHP死了,说它已超过其内存限制(132 MB左右).

CSV文件本身只有几个megs - 发生的其他处理会进行大量的字符串比较,差异等.我有大量的代码在运行它并且很难想出一个'最小的再现样品'.

找到并解决这个问题有哪些好方法?

发现问题的原因

我有一个调试类,它在运行时记录我的所有数据库查询.因此,那些长约30KB的SQL字符串留在内存中.我意识到这不适合设计为长时间运行的脚本.

可能还有其他内存泄漏源,但我很确定这是我的问题的原因.

too*_*php 7

如果你确实怀疑脚本中只有一两个内存泄漏导致它崩溃,那么你应该采取以下步骤:

  • 更改memory_limit到小东西,比如500KB
  • 注释除了应用于每一行的一个处理步骤之外的所有步骤.
  • 对整个CSV文件运行有限处理,看看它是否可以完成.
  • 逐渐添加更多步骤并观察内存使用量是否达到峰值.

例:

ini_set('memory_limit', 1024 * 500);
$fp = fopen("test.csv", 'r');
while($row = fgetcsv($fp)) {
    validate_row($row);         // step 1: validate
    // add these back in one by one and keep an eye on memory usage
    //calculate_fizz($row);     // step 2: fizz
    //calculate_buzz($row);     // step 3: buzz
    //triangulate($row);        // step 4: triangulate
}
echo "Memory used: ", memory_get_peak_usage(), "\n";
Run Code Online (Sandbox Code Playgroud)

最糟糕的情况是,您的所有处理步骤都是效率中等,您需要优化所有这些步骤.


lpf*_*eau 5

查看代码会有所帮助,但是如果你想自己调试它,看看Xdebug,它将帮助你分析你的应用程序.

当然,根据你正在做的事情,它可能会积累一些内存,尽管132MB似乎已经高达2500条记录.当然,如果需要,你可以在php.ini中调整你的内存限制.

你正在阅读的CSV文件有多大?你正在做什么对象和处理?