php 如何在PHP中的数组之后释放内存?unset 和 = null 似乎不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18122369/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to free memory after array in PHP? unset and = null seems to not working
提问by user2663733
I ve got a 16 MB size CSV file and try to parse it, and do some stuff, but script run out of memory after some time. I realize that this code generate around 200 MB of used space and unset is not working.
我有一个 16 MB 大小的 CSV 文件并尝试解析它,并做一些事情,但脚本在一段时间后内存不足。我意识到这段代码生成了大约 200 MB 的已用空间,并且 unset 不起作用。
$countRows = 1;
var_dump("3. ".memory_get_usage()." beginDiff: ".(memory_get_usage() - $this->startingMemory));
while(($row = fgetcsv($fp, 300000, ';', '"')) !== FALSE)
{
if ($row == '')
continue;
if($firstRow == true)
{
foreach($row as $k => $v)
{
$this->columnMapping[$k] = trim(mb_strtolower($v));
}
$firstRow = false;
continue;
}else
{
foreach($row as $k => $v)
{
$row[$this->columnMapping[$k]] = $v;
unset($row[$k]);
}
}
...
//$this->theirCategoriesToProducts[$row['kategorie']][]['kodproduktu'] = $row['kodproduktu'];
$this->theirCategoriesToProducts[$row['kategorie']][] = $row;
}
var_dump("3,5. ".memory_get_usage()." beginDiff: ".(memory_get_usage() - $this->startingMemory));
...
var_dump("7. - before unset total: ".memory_get_usage()." beginDiff: ".(memory_get_usage() - $this->startingMemory));
unset($this->theirCategoriesToProducts);
var_dump("8. - after unset total: ".memory_get_usage()." beginDiff: ".(memory_get_usage() - $this->startingMemory));die;
Generating this output:
生成此输出:
string '3. 72417440 beginDiff: 34730040' (length=31)
string '3,5. 292748528 beginDiff: 255061136' (length=36)
string '7. - before unset total: 299039360 beginDiff: 261351984' (length=55)
string '8. - after unset total: 297364432 beginDiff: 259677056' (length=54)
With setting that variable equals null is the output very similar. But switching comments between this two lines
设置变量等于 null 是输出非常相似。但是在这两行之间切换注释
$this->theirCategoriesToProducts[$row['kategorie']][]['kodproduktu'] = $row['kodproduktu'];
//$this->theirCategoriesToProducts[$row['kategorie']][] = $row;
Will output:
将输出:
string '3. 72417784 beginDiff: 34730040' (length=31)
string '3,5. 81081984 beginDiff: 43394248' (length=34)
string '7. - before unset total: 87256544 beginDiff: 49568824' (length=53)
string '8. - after unset total: 85581520 beginDiff: 47893800' (length=52)
So its about 200 MB of "lost" memory (almost half of dedicated).
所以它大约有 200 MB 的“丢失”内存(几乎是专用的一半)。
Recursive function unseting all parts of arrays eat more memory, than was able to free so crashed also.
递归函数取消设置数组的所有部分会占用更多的内存,比能够释放的内存还多,因此也崩溃了。
In script is never used that array with & so there should be no references to other variables.
在脚本中,从不使用带有 & 的数组,因此不应该引用其他变量。
File is closing right after 3.5 dump.
文件在 3.5 转储后立即关闭。
Any other ideas, how to unset that array?
任何其他想法,如何取消设置该数组?
回答by Gadoma
As of PHP > 5.3 there are some Garbage Collectionmechanisms available, so theoretically you could think of something like the example in the docs
从 PHP > 5.3 开始,有一些垃圾收集机制可用,所以理论上你可以想到类似文档中的例子
//Memory cleanup for long-running scripts.
gc_enable(); // Enable Garbage Collector
var_dump(gc_enabled()); // true
var_dump(gc_collect_cycles()); // # of elements cleaned up
gc_disable(); // Disable Garbage Collector
But unfortunately, in your case you have to bear in mind that (according to Can I trigger PHP garbage collection to happen automatically if I have circular references?) the garbage collector "will not run, for example, when the memory limit is about to hit. As a result, your script can still abort when hitting memory limit only because PHP is too dumb to collect the cycles in that case!".
但不幸的是,在您的情况下,您必须记住(根据如果我有循环引用,我可以触发 PHP 垃圾收集自动发生吗?)垃圾收集器“将不会运行,例如,当内存限制即将达到命中。因此,您的脚本在达到内存限制时仍然可以中止,只是因为 PHP 太笨了,无法在这种情况下收集周期!”。
In the end, you can try using GC, but it possibly won't solve your problem.
最后,您可以尝试使用 GC,但它可能无法解决您的问题。
So, what else is there to try? Try splitting your master data array that you import into smaller chunks and import them sequentially one after another. Fetch the chunks in a loop always into the same variable and then loop through it to process the records.
那么,还有什么可以尝试的呢?尝试将您导入的主数据数组拆分成更小的块,然后一个接一个地依次导入。始终将循环中的块提取到同一个变量中,然后循环遍历它以处理记录。
回答by Raymond Nijland
The PHP function fgetcsv
is bad because the server need to store the complete file in the memory better read one line store it
PHP 功能fgetcsv
不好,因为服务器需要将完整的文件存储在内存中,最好读取一行存储
And php arrays use alot of memory because array's in php arrays are implemented as "hashmaps" or a "hashtable" you could use splFixedArray
(real C or C++ array) if you don't need string's as key
并且 php 数组使用大量内存,因为 php 数组中的数组被实现为“hashmaps”或“hashtable”,splFixedArray
如果您不需要字符串作为键,您可以使用(真正的 C 或 C++ 数组)
splFixedArray
(you need atleast php 5.3 to use it) are known to use 40% off the total what php array needed.
splFixedArray
(您至少需要 php 5.3 才能使用它)已知使用 php 数组所需总数的 40%。
回答by Halcyon
You can use unset
to deletevariables allowing them to be garbage collected.
您可以使用unset
来删除变量,允许他们进行垃圾回收。
$foo = "bar";
unset($foo);
var_dump($foo); // null
Overall just keep track of what you're keeping references to. Maybe you don't need to keep track of everything. A while
-loop allows you to be memory efficient, just carrying over what you need for each line.
总体而言,只需跟踪您要引用的内容。也许您不需要跟踪所有内容。一个while
-loop让你成为高效存储,只是结转您所需要的每一行。
Some scripts actually just need a lot of memory to run, it's not too crazy to increase the memory limit, but only do this if it's actually needed.
有些脚本实际上只需要大量内存来运行,增加内存限制并不太疯狂,但只有在确实需要时才这样做。
回答by Milan
In this case problem was found in skipped lines. Inside one of using function was hidden function assigning every part of array to caching global variable. Removing this caching variable solved the problem.
在这种情况下,问题是在跳过的行中发现的。在 using 函数中,隐藏函数将数组的每一部分分配给缓存全局变量。删除这个缓存变量解决了这个问题。