Perl进程之间共享的只读内存

时间:2012-10-03 14:06:27

标签: perl memory process shared readonly

我希望让我的Perl程序使用多个核心。它逐步读取查询输入,并将其中的块与每个运行的从文件加载的只读数据结构进行比较。该数据结构通常是几千兆字节,是一小组压缩字符串,用于小型C例程。当进程被分叉时,所有内容都被复制,这在多核计算机上快速打开RAM。我尝试了几个非标准模块,但都会导致速度变慢和/或破坏RAM。我认为,对于只读数据,Perl不会坚持要复制。其他语言可以做到。有没有人有想法?

3 个答案:

答案 0 :(得分:2)

Fork通常不会复制内存,直到它被修改(在写入或COW上搜索副本)。您确定正确测量内存使用情况吗?从free中减去值之前/之后而不是使用top。

编辑 - 示例脚本

尝试使用以下设置运行以下内容:     ./fork_mem_usage 5 10000     ./fork_mem_usage 25 10000     ./fork_mem_usage 5 100000     ./fork_mem_usage 25 100000

如果第一次增加大于后续增加,那么fork正在使用copy-on-write。几乎可以肯定的是(当然除了Windows)。

#!/usr/bin/perl
use strict;
use warnings;

my $num_kids  = shift @ARGV;
my $arr_size  = shift @ARGV;
print "$num_kids x $arr_size\n";

my @big_array = ('abcdefg') x $arr_size;
die "Array wrong length" unless ($arr_size == @big_array);

print_mem_usage('Start');

for my $i (1..$num_kids) {
    my $pid = fork();
    if ($pid) {
        if ($i % 5 == 0) {
            print_mem_usage($i);
        }
    }
    else {
        sleep(5);
        exit;
    }
}

print_mem_usage('End');
exit;

sub print_mem_usage {
    my $msg = shift;
    print "$msg: ";
    system q(free -m | grep buffers/cache | awk '{print $3}');
}

答案 1 :(得分:0)

编辑&总结:

threads::shared是一个选项,我一直非常错误。在创建线程时,甚至会复制共享数据结构。这确实很糟糕,因此我可以总结Perl完全无法进行内存密集型计算。


当进程fork时,内核会复制整个进程。驻留在RAM中的所有内容都是重复的。没有语言可以解决这个问题。但是,您可以尝试内存映射,也可以使用线程。

Perl线程是fork仿真,但您可以将变量声明为线程之间的共享:

use threads;
use threads::shared;

my $sharedVariable :shared = 0;

my @worker;

for my $i (1 .. 6) {
   push @worker, threads->create(\&worker_sub);
}

$_->join() foreach @worker;

sub worker_sub {
   sleep rand 5;
   print $sharedVariable, "\n";
}

如果在一个线程中更新$sharedVariable,则更改也会传播到其他线程。如果用

替换print语句,可以看到这个
print threads->tid, "-->", ++$sharedVariable, "\n";

答案 2 :(得分:0)

您可以使用Cache :: FastMmap存储共享数据。我听说有人用这个用于IPC不用于缓存,并且这个缓存在进程之间共享。其中很大一部分是用C语言编写的。不要忘记在初始化中添加'raw_values = 1'。可以压缩缓存中的值,这样如果你有足够的CPU和数据压缩,它会给你带来很多内存。

速度非常快,这里有一些基准:http://cpan.robm.fastmail.fm/cache_perf.html

  

因为Cache :: FastMmap mmap是进程内存空间中的共享文件,这可以使每个进程看起来都很大,即使它只是在使用缓存的所有进程之间共享的mmap内存,甚至可能被交换如果缓存使用率很低,则输出。

     

然而,操作系统会认为你的过程非常大,这可能意味着你打了一些之前设定的BSD :: Resource或'ulimits',你认为它是理智的,但现在不是了,所以要注意。