为什么带有Parallel :: Loops的程序会耗尽我的记忆?

时间:2016-03-02 00:44:58

标签: perl parallel-processing

我在工作中继承了一些代码,我试图改进。我的Perl技能有点缺乏,所以会喜欢一些帮助!

本质上,此脚本是SNMP轮询由数千个节点组成的网络,以更新其本地接口索引缓存。我发现它遇到了一个问题,它耗尽了它的记忆而失败了。代码如下(严重减少,但我认为你会得到这个小说)

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");
        }
    });
}

此特定虚拟机具有3.1GB的ram可分配值,并且在此脚本未运行时闲置约83MB。如果我将maxProcs降低到25,它会很好但是这个脚本已经花了很长时间,因为设备数量很多+延迟,所以宁愿保持高并行度!

我感觉$pl->share()正在与每个分叉进程共享不断扩展的%snmp_results,这绝对没有必要,因为它没有读取/修改其他条目:只是添加新的条目。我有更好的方法吗?

我对my %cache = %{$result};也有点不确定。如果这只是创建一个指针作为哈希然后很酷,但如果它正在复制,那也有点浪费!

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

可以在CPAN here中找到该模块的文档。

有一部分谈论表演:

  

此外,如果每个循环子返回大量数据,则需要这样做   被传达回父进程,并再次传达给父进程   除非循环体做一些,否则超过并行性能增益   繁重的工作。

您可能正在内存中移动变量的完整副本,如果要轮询的MIB和机器数量足够大,则推到机器的限制。

由于您正在做的是I / O密集型任务而不是可以从并行CPU处理中受益的CPU任务,我会重新考虑启动这么多(50!)线程进行轮询的方法。

  • $maxProcs的程序运行到1到5个进程,看看它的行为方式。对代码进行一些分析,附上Devel::NYTProf以检查您消耗时间的位置,以及增加进程数量实际上是否会带来更好的性能。
  • 使用Parallel::Loops重新考虑此任务。使用use threads [1]和不同线程(use threads::shared)之间共享的哈希值可以获得更好的性能。

道歉,如果这可能是一个评论。由于存在所有限制,因此难以从SO开始:(

如果您已经找到了解决方案,那么如果您能与我们分享您的发现,那就太棒了。我之前不知道Parallel::Loops,我想我可以给它一些用途。