Perl技术分离一部分代码以独立运行是什么?

时间:2013-02-19 16:55:16

标签: perl process fork

我没有参与接近操作系统的编程技术,但据我所知,当在Perl中并行执行某些操作时,选择的武器是fork,可能还有一些基于它的有用模块。 fork的文档页面说:

Does a fork(2) system call to create a new process running the same program at the same point.

因此,拥有一个消耗大量内存并为一个小任务调用fork的大型应用程序意味着将有2个大的perl进程,而第二个将浪费资源只是为了完成一些简单的工作。

所以,问题是:做什么(或如何使用fork,如果它是唯一的方法),以便让独立的代码部分独立运行,只消耗它需要的资源

只是一个非常简单的例子:

    use strict;
    use warnings;

    my @big_array = ( 1 .. 2000000 );  # at least 80 MB memory
    sleep 10;  # to have time to inspect easely the memory usage

    fork();
    sleep 10;  # to have time to inspect easely the memory usage

并且子进程也消耗80+ MB。

要明确:与这个分离的代码进行通信或以某种方式使用其结果并不重要,只是为了可以说“嘿,为我运行这个简单的任务背景,让我继续我的繁重工作......并且不要浪费我的资源!“在运行繁重的perl应用程序时。

4 个答案:

答案 0 :(得分:3)

您的分叉进程实际上并没有使用80MB的驻留内存。该内存的很大一部分将从父进程共享 - “借用”,直到父进程或子进程写入,此时 copy-on-write 语义将导致内存实际被复制。

如果您想完全放下行李,请在叉子中运行exec。这将用不同的可执行文件替换子Perl进程,从而释放内存。如果您不需要将任何内容传达给父母,那也是完美的。

答案 1 :(得分:3)

fork()exec()是你的兔子。您fork()创建一个新流程(这是一个相当便宜的操作,请参见下文),然后exec()替换您运行较小的大perl。这看起来像这样:

use strict;
use warnings;
use 5.010;

my @ary = (1 .. 10_000_000);

if (my $pid = fork()) {
    # parent
    say "Forked $pid from $$; sleeping";
    sleep 1_000;
} else {
    # child
    exec('perl -e sleep 1_000');
}

@ary只是用来填补原始进程的内存。)

我说fork()相对便宜,即使它确实复制了整个原始流程。这些陈述没有冲突;设计fork的人注意到了同样的问题。副本是惰性的,也就是说,只复制实际更改的位。

如果您发现您希望这些流程能够相互通信,那么您将开始进入更复杂的IPC领域,并且已经编写了许多书籍。

答案 2 :(得分:1)

没有办法只分配流程足迹的一部分,所以通常的解决方法归结为:

    在父进程中运行内存密集型代码之前
  1. fork
  2. 使用systemopen HANDLE,'|-',...启动单独的流程。当然,这个新进程不会从其父进程继承任何数据,因此您需要以某种方式将数据传递给该子进程。

答案 3 :(得分:1)

在大多数操作系统上实现的

fork()非常有效。它通常使用一种称为写时复制的技术,意味着页面最初是共享的,直到一个或其他进程写入它们。此外,您的许多进程内存仍然是只读映射文件。

仅仅因为一个进程在fork()之前使用80MB并不意味着之后两者将使用160.首先它将只有一小部分超过80MB,直到每个进程开始弄脏更多页面。 / p>