我有php应用程序应该管理(导出)大量(大量)数据,并且必须在生产中完成...所以我需要尽可能降低内存使用率(主要标准)。
简单地说App在周期中导出数据,比如
for($fileCounter=0;$fileCounter<=70;$fileCounter++) {
... HERE a lot of (more than 1K lines) huge work, many variables a lot of DB queries from another databases etc ...
}
我不想在这里展示完整的逻辑,因为它可能需要花费很多时间给其他人,这不是主要观点。
重点是,为什么如果我在每次迭代期间unset()
所有新创建的变量,它不会减少内存使用量?像这样
for($fileCounter=0;$fileCounter<=70;$fileCounter++) {
// optimization purpose
$vars_at_start = array_keys(get_defined_vars());
echo memory_get_peak_usage(true) . PHP_EOL;
... huge logic ...
$vars_at_end = array_diff($vars_at_start, array_keys(get_defined_vars()));
foreach($vars_at_end as $v) unset($v);
unset($vars_at_end);
}
以及如何减少内存使用量?如果我需要使用这么多查询,变量等等。
P.S。代码不是我的:)我不想从头开始重写它,我只是在寻找优化方向。
没有变量清理内存使用是下一个(它是在每次迭代开始时测量)
23592960
Started: 0 - 12:58:26
Ended: 13:00:51
877920256 (difference 854'327'296)
Started: 1 - 13:00:51
Ended: 13:03:39
1559494656 (difference 681'574'400)
并使用变量清理
23592960
Started: 0 - 12:47:57
Ended: 12:50:20
877920256 (difference 854'327'296)
Started: 1 - 12:50:20
Ended: 12:53:16
1559756800 (difference 681'836'544)
根据我的阅读,PHP有很多理由泄漏内存......就像这个https://bugs.php.net/bug.php?id=48781
有一个名为valgrind的工具可以提供帮助,去尝试一下:)
答案 0 :(得分:2)
尽管unset()没有释放PHP进程占用的内存,但它确实释放它以供PHP脚本本身使用。
因此,如果你在一个循环中创建一个10M大小的变量10次并在循环结束时取消设置(或重写)它,那么内存消耗应该低至10M +所有其他变量到底循环。
如果它增长 - 那么,在你不想表现的完整逻辑中的某个地方就会出现泄漏。
答案 1 :(得分:0)
因为PHP会自动完成 当不再使用变量时,PHP会自行取消它。
答案 2 :(得分:0)
因为unset
没有释放内存。它只是释放变量。但是,如果该变量指向某种复杂的结构,那么PHP的内存管理无法弄清楚如何释放,它就不会。
答案 3 :(得分:0)
$vars_at_end = array_diff($vars_at_start, array_keys(get_defined_vars()));
foreach($vars_at_end as $v) unset($v);
unset($vars_at_end);
整个代码块正在处理变量的副本(甚至副本),因此它会增加大量内存。 您未设置的所有内容都是foreach循环中的副本副本。
您需要取消设置您使用的实际变量
答案 4 :(得分:0)
如果您挖掘循环中使用的主变量的代码并取消设置它们,那么您将真正减少引用计数并减少到0,然后您将释放存储以供重用。然而,正如troelskyn所暗示的那样,现有代码可以通过许多方式使数据元素具有非零引用。经典的方法是,如果您的代码使用引用,那么您可以创建循环引用链,除非明确地断开循环,否则永远不会回收它们。即使有一个用于保存结果的全局数组也会占用内存。
很抱歉,但是你的陈述:
我不想在这里展示完整的逻辑,因为它可能需要花费很多时间给其他人,这不是主要观点。
错了。在PHP中,如果您想了解为什么不将存储返回到内存池,那么必须查看代码。
答案 5 :(得分:0)