我没有参与接近操作系统的编程技术,但据我所知,当在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应用程序时。
答案 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)
没有办法只分配流程足迹的一部分,所以通常的解决方法归结为:
fork
system
或open HANDLE,'|-',...
启动单独的流程。当然,这个新进程不会从其父进程继承任何数据,因此您需要以某种方式将数据传递给该子进程。答案 3 :(得分:1)
fork()
非常有效。它通常使用一种称为写时复制的技术,意味着页面最初是共享的,直到一个或其他进程写入它们。此外,您的许多进程内存仍然是只读映射文件。
仅仅因为一个进程在fork()
之前使用80MB并不意味着之后两者将使用160.首先它将只有一小部分超过80MB,直到每个进程开始弄脏更多页面。 / p>