什么是Perl技术来分离独立运行的部分代码?
我没有涉及到接近操作系统的编程技术,但正如我所知,当涉及到在Perl中并行执行某些操作时,选择的武器是什么是Perl技术来分离独立运行的部分代码?,perl,process,fork,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,意味着将有两个大型perl进程,而第二个进程将浪费资源,只做一些简
fork
,可能还有一些基于它构建的有用模块。fork
的文档页面显示:
Does a fork(2) system call to create a new process running the same program at the same point.
因此,拥有一个消耗大量内存的大型应用程序,并为一个小任务调用fork
,意味着将有两个大型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应用程序时。没有办法只留下进程占用空间的一个子集,因此通常的解决方法归结为:
fork
在父进程中运行内存密集型代码之前system
或打开句柄“|-”,…
启动单独的进程。当然,这个新进程不会从其父进程继承任何数据,因此您需要以某种方式将数据传递给这个子进程您的分叉进程实际上没有使用80MB的驻留内存。该内存的很大一部分将共享-“借用”父进程,直到父进程或子进程写入该进程,此时写时复制语义将导致实际复制内存 如果您想完全放下行李,请在您的叉子中运行
exec
。这将用不同的可执行文件替换子Perl进程,从而释放内存。如果您不需要与家长进行任何沟通,这也非常完美。fork()
toexec()
是您的小兔子。您可以使用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()
ing相对便宜,尽管它复制了整个原始过程。这些说法没有冲突;设计fork
的人也注意到了同样的问题。复制是惰性的,也就是说,只复制实际更改的位
如果你发现你想让进程彼此对话,你将开始进入更复杂的IPC领域,关于这个领域已经有很多书写过了。fork()
在大多数操作系统上实现是非常有效的。它通常使用一种称为“写时复制”的技术,这意味着页面最初是共享的,直到一个或另一个进程写入页面。另外,很多进程内存都将是只读映射文件
仅仅因为一个进程在
fork()之前使用80MB,并不意味着之后两个进程将使用160 MB。首先,在每个进程开始弄脏更多页面之前,它只会超过80MB的一小部分。子进程将继承其父进程的所有属性。我认为没有真正的方法可以通过分叉来解决这个问题。使用fork
不是强制性的。任何技术都是可以接受的,甚至调用system
。不确定词法变量是否共享。当两个进程都在运行时,我在ps
的RES/SHR列中得到了这些值:48m/1776和46m/156(1M数组元素)。对不起,它应该是top
而不是上面注释中的ps
,在调用exec()之前,它不会在很短的时间内复制内存吗
然后在子进程终止后释放内存?毕竟,如果一切都收敛于调用system/exec,那么甚至不需要使用fork:)。。好的,对于exec
它是必需的,但是system(“…&”)代码>似乎可以完成这项工作well@ArtM如上所述,这是一个懒惰的副本。和<代码>系统('.&…)是<代码> FoK())/>代码>后面是“代码>执行”(<)>代码>,外壳被夹在中间只是为了咧嘴笑,还有一点脆弱性。做这件事的方法不止一种;在Linux上,PID>1的每个进程都是通过fork(最初是init)创建的。例如,如果您在终端中运行某个东西,bash(或其他什么)将分叉来执行它。写时复制语义确保这是有效的。我认为应该等到至少一个进程开始脏化。。。或smth逻辑上等同于此。这个my@big=(1..1000000)
只是一个简单的通用示例代码,它可能会更复杂,并扩展到整个代码空间。谢谢你的介入。