[英]Perl map/grep memory leak
我一直在研究工作中的perl項目,並遇到了一個奇怪的內存泄漏。 我把我的問題的根源歸結為一個人為的例子:
#!/usr/bin/perl
use strict;
use warnings;
# takes: an array reference
# returns: 1
sub g {
my ($a) = @_;
return 1;
}
# takes: nothing
# returns: the result of applying g on an array reference
sub f {
my @a = ('a') x 131072; # allocate roughly a megabyte
return g(\@a);
}
# causes a leak:
#map { f($_) } (1..100000);
# loop equivalent to map, no leak:
#my @b;
#for my $i (1..100000) {
# push @b, f($_);
#}
# causes a leak:
#grep { f($_) } (1..100000);
# loop equivalent to grep, no leak:
#my @b;
#for my $i (1..100000) {
# push @b, $i if f($_);
#}
取消注釋4個代碼塊中的1個(在子例程下面)並在監視其內存使用情況時運行腳本。 在我的機器上,使用grep或map的代碼似乎會導致內存泄漏,而“循環等效”則不會。 我的perl版本是v5.10.1,我正在運行Ubuntu。
我相信這可能是perl中的一個錯誤,但我不想在沒有關於可能的原因的另一個意見的情況下跳到一個激烈的結論。 任何人都可以解釋這種行為是否正確?
謝謝
我不知道這是否是內存泄漏。 如果我降低循環的最高值(例如,從100000到100),我可以重復使用map
/ grep
表達式而不會丟失內存。
相反,當涉及內存管理時, map
和grep
似乎更有可能是原子操作,perl在這些操作的中間不執行其垃圾收集。
Perl 5.12.0(和5.8.9)在這些表達式上確實看起來更強大(但它們似乎也更慢)。
它確實是。 但為了證明這一點,你必須將while(1){}置於可疑表達式之外 - 在perl中,曾經獲得的內存永遠不會返回到OS(但可以由perl本身重用)。 我用的是代碼
while(1){grep {f($ _)}(1..100000)}
5.8.8以下,它的大小不斷增加 - 所以,這是一個泄漏。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.