如何修复PHP中的内存泄漏

2022-08-30 23:35:06

我的 PHP 应用程序具有可以导入记录的导入脚本。

目前,它正在从CSV文件导入。它读取 CSV 文件的每一行,使用 fgetcsv 一次一行,对于每一行,它对该记录执行大量处理,包括数据库查询,然后转到下一行。它不需要不断积累更多的内存。

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

CSV文件本身只有几兆 - 发生的另一个处理做了很多字符串比较,差异等。我有大量的代码在操作它,很难想出一个“最小的再现样本”。

寻找和解决此类问题有哪些好方法?

发现问题的原因

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

可能还有其他内存泄漏来源,但我相当确定这是我问题的原因。


答案 1

如果您确实怀疑脚本中只有一两个内存泄漏导致其崩溃,则应执行以下步骤:

  • 更改为小大小,如 500KBmemory_limit
  • 注释掉除应用于每行的处理步骤之一之外的所有处理步骤。
  • 对整个 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";

最坏的情况是,您的所有处理步骤都效率适中,您需要优化所有这些步骤。


答案 2

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

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

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


推荐