Perl 使用WWW::Mechanize的内存泄漏
我用Perl编写了这个脚本,在运行几分钟后,它出现了一个Perl 使用WWW::Mechanize的内存泄漏,perl,out-of-memory,www-mechanize,Perl,Out Of Memory,Www Mechanize,我用Perl编写了这个脚本,在运行几分钟后,它出现了一个“内存不足”错误。我看不到任何循环引用,也不知道为什么会发生这种情况 use feature 'say'; use WWW::Mechanize; use HTML::TreeBuilder::XPath; use utf8; $url = "some url"; my $mech = new WWW::Mechanize; $mech->get($url); my $html = HTML::TreeBuil
“内存不足”
错误。我看不到任何循环引用,也不知道为什么会发生这种情况
use feature 'say';
use WWW::Mechanize;
use HTML::TreeBuilder::XPath;
use utf8;
$url = "some url";
my $mech = new WWW::Mechanize;
$mech->get($url);
my $html = HTML::TreeBuilder::XPath->new_from_content($mech->content);
my $html2;
do {
for $item ($html->findnodes('//li[@class="dataset-item"]'))
{
my $title = $item->findvalue('normalize-space(.//a[2])');
next unless $title =~ /environmental impact statement/i;
my $link = $item->findvalue('.//a[2]/@href');
$mech->get($link);
$html2 = HTML::TreeBuilder::XPath->new_from_content($mech->content);
my @pdflinks = $html2->findvalues('//a[@title="Go to external URL"]/@href');
my $date = $html2->findvalue('//tr[th="Date Created"]/td');
for $pdflink (@pdflinks)
{
next unless $pdflink =~ /\.pdf$/;
$mech->get($pdflink);
$mech->save_content($filename = $mech->response->filename);
say "Title: $title\nDate: $date\nFilename: $filename\n";
}
}
if ($nextpage = $html->findvalue('//ul[@class="pagination"]/li/a[.="»"]/@href'))
{
say "Next Page: $nextpage\n";
$mech->get("some site" . $nextpage);
$html = HTML::TreeBuilder::XPath->new_from_content($mech->content);
}
} while ($nextpage);
say "Completed.";
因为默认情况下,其用户代理在浏览时保留所有历史记录
- 堆栈深度=>
$value
Devel::Size qw(total_Size)
我跟踪$mech
的大小,以查看它在每个pdf之后增加了几十kB。剧本显然有很多匹配项;我退出了测试,因为它占用了10%的内存(磁盘上有几十个超过1 Gb的文件)
一种解决方案是为每个$item
实例化一个新对象。这在原则上是浪费,但实际上不会增加太多开销,同时会限制最大大小
或者重置它,或者限制它的堆栈深度。由于代码似乎根本不需要返回到以前的状态,因此实际上不需要任何堆栈,因此删除它的解决方案非常好
评论
- 准确地说,脚本中没有“漏洞”;它只需要越来越多的内存
- 始终做到
使用严格代码>和
使用警告代码>位于脚本顶部
- 最好不要使用间接对象语法来实例化对象(
),而是使用普通的方法调用(newpackage
),以避免在某些情况下处理歧义。请参见和中的说明以及和中的故障示例Package->new
my$mech=WWW::Mechanize->new(堆栈深度=>0)代码>几分钟后,我在磁盘上积累了大约Gb的pdf文件(perl的内存使用一直在剪辑)——我猜:mech对象在不断浏览的过程中保存了所有这些内容。iTesting…@zdim我想我上面的评论已经解决了这个问题。在Mechanize文档中,它建议如果您的内存被占用(关于测试的说明我提到:问题的初始版本提供了URL),它确实需要使用utf8
,因为>
字符。使用使用utf8没有害处代码>即使只使用ASCII字符集中的字符。@ikegami当然,原则上我是在评论一个不必要的(我认为)杂注。@ikegami(奇怪的是,没有杂注,脚本运行得很好…?)