【发布时间】:2026-01-25 12:15:01
【问题描述】:
我有一个处理大型 XML 文件并将其中的数据保存到数据库中的 php 脚本。在保存到数据库之前,我使用几个类来处理和存储 PHP 脚本中的数据,并逐个节点读取 XML 以保留内存。基本上,我的文件中的循环如下所示:
while ($Reader->read()) {
$parsed++;
if (time() >= $nexttick) {
$current=microtime(true)-$ses_start;
$eta=(($this->NumberOfAds-$parsed)*$current)/$parsed;
$nexttick=time()+3;
$mem_usage=memory_get_usage();
echo "Parsed $parsed @ $current secs \t | ";
echo " (mem_usage: " . $mem_usage . " \t | ";
echo "ETA: $eta secs\n";
}
$node=$Reader->getNode();
// OMMITED PART: $node is an array, I make some processing, and check if everything exists in the array that I need in the following section
$Ad=new Ad($node); // creating an Ad object from the node
// OMMITED PART: Making some additional SQL queries, to check the integrity of the data, before uploading it to the database
if (!$Ad->update()) {
//add wasn't inserted succesfully, saving a row in a second database table, to log this information
} else {
//add succesfully inserted, saving a row in a second database table, to log this information
}
}
您注意到,循环的第一部分是一个小输出工具,每 3 秒输出一次文件的进度,还输出脚本的内存使用情况。我需要它,因为我遇到了内存问题,上次我尝试上传文件时,想弄清楚是什么在消耗内存。
当我运行这个脚本时,它的输出看起来像这样:
解析 15 @ 2.0869598388672 秒 | (mem_usage:1569552 | ETA:1389.2195994059 秒 解析 30 @ 5.2812438011169 秒 | (mem_usage:1903632 | ETA:1755.1333565712 秒 解析 38 @ 8.4330480098724 秒 | (mem_usage:2077744 | ETA:2210.7901124829 秒 解析 49 @ 11.377414941788 秒 | (mem_usage:2428624 | ETA:2310.5440017496 秒 解析 59 @ 14.204828023911 秒 | (mem_usage:2649136 | ETA:2393.3931421304 秒 解析 69 @ 17.032008886337 秒 | (mem_usage:2831408 | ETA:2451.3750760901 秒 解析 79 @ 20.359696865082 秒 | (mem_usage:2968656 | ETA:2556.8171214997 秒 解析 87 @ 23.053930997849 秒 | (mem_usage:3102360 | ETA:2626.8231951916 秒 解析 98 @ 26.148546934128 秒 | (mem_usage:3285096 | ETA:2642.0705279769 秒 解析 107 @ 29.092607021332 秒 | (mem_usage:3431944 | ETA:2689.8426286172 秒
现在,我可以肯定地知道,在我的MySQL 对象中,我有一个运行时缓存,它将一些基本选择查询的结果存储在一个数组中,以便以后快速访问。这是脚本中唯一的变量(据我所知),它在整个脚本中的大小都会增加,所以我尝试关闭此选项。内存使用量下降了,但只有一点点,而且在整个脚本中它仍在上升。
我的问题如下:
-
在长时间运行的脚本中,内存使用量的缓慢上升是 php 中的正常行为,还是我应该搜索整个代码,并尝试找出是什么占用了我的内存?
我知道通过在变量上使用
unset(),我可以释放它从内存中占用的空间,但是我是否需要使用unset(),即使我在整个过程中都覆盖了同一个变量整个文件?
用一个例子稍微改写我的第二个问题:
以下两个代码块在内存使用方面是否产生相同的结果,或者如果不是,哪一个更优化?
BLOCK1
$var = str_repeat("Hello", 4242);
$var = str_repeat("Good bye", 4242);
BLOCK2
$var = str_repeat("Hello", 4242);
unset($var);
$var = str_repeat("Good bye", 4242);
【问题讨论】:
-
Block1 和 Block2 的内存使用量相同,但 block2 会因为 $var 的取消设置和重新创建而变慢
-
slow rising of the memory usage throughout a long running script是可能的,但循环内的slow rising of the memory usage throughout a long running script很少见,除非循环正在构建一个数组或类似的......看起来循环内的某些东西正在消耗内存而不是释放它 -
嗯,这正是我所害怕的。在这种情况下,我需要逐个调试循环使用的每个函数:|
-
blackfire.io 或 xdebug 等工具可以帮助完成该过程