我在工作中繼承了一些代碼,我試圖改進它。我的Perl技能有點缺乏,所以會喜歡一些幫助!爲什麼Parallel :: Loops程序耗盡我的內存?
本質上,該腳本是SNMP輪詢數千個節點的網絡以更新其本地接口索引緩存。我發現它正在耗盡內存和失敗的問題。代碼如下(大量減少,但我想你會得到JIST)
use strict;
use warnings;
use Parallel::Loops;
my %snmp_results;
my $maxProcs = 50;
my @exceptions;
my @devices;
my %snmp_results;
my $pl = Parallel::Loops->new($maxProcs);
$pl->share(\%snmp_results, \@exceptions);
load_devices();
get_snmp_interfaces();
sub get_snmp_interfaces {
$pl->foreach(\@devices, sub {
my ($name, $community, $snmp_ver) = @$_;
# Create the new ifindex cache, and return an array reference to the new entries
my $result = getSNMPIFFull($name, $community, $snmp_ver);
if (defined $result && $result ne "") {
my %cache = %{$result};
print "Got cache for $name\n";
# Build hash of all the links polled through SNMP
# [ifindex, ifdesc, ifalias, ifspeed, ip]
for my $link (keys %cache) {
$snmp_results{$name}{$cache{$link}[0]} = [$cache{$link}[0], $cache{$link}[1], $cache{$link}[2], $cache{$link}[3], $cache{$link}[4]];
}
}
else {
push(@exceptions, "Unable to poll $name - $community - $snmp_ver");
}
});
}
這個特定的VM具有RAM alloctable的3.1GB和怠速關於83MB的使用時,該腳本沒有運行。如果我將maxProcs降到25,它會很好地完成,但由於設備數量和延遲太多,這個腳本可能會花費很長時間,所以寧願保持高並行性!
我有一種感覺,$pl->share()
與每個分叉進程共享不斷擴大的%snmp_results
,因爲它不讀取/修改其他條目,因此不需要修改其他條目:只需添加新條目即可。有沒有更好的方法可以做到這一點?
我也對my %cache = %{$result};
略有不確定。如果這只是創建一個散列指針然後很酷,但如果它正在做一個副本,那也有點浪費!
任何幫助將不勝感激!
您是否確定這是完整的代碼?它看起來像'@ devices'還沒有被聲明。該程序不應該編譯。關於'%cache':它是在'if'內聲明的。 Perl中'my'的_Lexical_變量總是存在於封閉的_scope_中,在這種情況下,它是'if'的'{}'塊。因此,在循環的每次迭代中,它都會創建一個全新的'$ result'和'%cache',一旦它們超出scope_,GC將照顧它們。但'%cache'確實沒有必要。你可以用'$ result - > {foo}'替換每個'$ cache {foo}'。儘管我不知道「分享」。 – simbabque
是的,@devices正在宣佈,剛剛在這篇文章的瘦身。抱歉! – Lokicat
我也很滿意替代方法。我之前的這個人一直在寫數據庫的結果,但由於他不得不打開,在每個分支中寫入和關閉數據庫,由於無法打開文件,往往會失敗。 – Lokicat