我正在尝试编写一个递归脚本,使用forks解析大目录以获得更好的性能。举一个简单的例子,假设我想要运行不超过10个并发分支的DFS,比如
#!/usr/bin/perl
use warnings;
use strict;
use Parallel::ForkManager;
my $pm = Parallel::ForkManager->new(10);
&proc_dir("/some/large/directory");
$pm->wait_all_children;
sub proc_dir {
my $path = shift;
my(@child_dirlist);
if(opendir(DIR, $path)) {
my @d = grep { -d "$path/$_" } readdir(DIR);
@child_dirlist = map { "$path/$_" } @d;
closedir(DIR);
}
foreach my $d (@child_dirlist) {
my $pid = $pm->start and next; #This will fail within child processes
&proc_dir($d);
$pm->finish;
}
}
但是Parallel::ForkManager
要求如果你想从子进程中分出更多的进程,你就会初始化另一个ForkManager
,这种情况在这种情况下会破坏使用一个进程的目的。我已经尝试了其他一些模块/方法来做到这一点,但是没有取得任何成功,将叉子的数量限制在一些#/阈值并让它们以递归的方式工作。想知道是否有人设法解决类似的问题或知道一个简单的解决方法。
编辑:请假设我已经测试了足够的CPU和I / O负载不是少数叉子的问题。
答案 0 :(得分:3)
我认为你不会意识到这种方法所带来的好处。您将简单地分叉无限数量的进程,直到您压倒机器为止。您的目标不是使用单个PFM实例,而是加快处理速度。
为此,我建议您查看File :: Find模块。这是一个与查找相关的Perl实现,很可能是您正在寻找的内容。
如果我理解您的示例代码,您只需查找目录,因此运行find2perl将为File :: Find生成包装脚本:
find2perl /usr/share/emacs/ -type d
将创建以下脚本(稍微减少):
#!/usr/bin/perl
use File::Find ();
# for the convenience of &wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name = *File::Find::name;
*dir = *File::Find::dir;
*prune = *File::Find::prune;
# Traverse desired filesystems
File::Find::find({wanted => \&wanted}, '/usr/share/emacs/');
exit;
sub wanted {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
(($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
-d _
&& print("$name\n");
}
在您想要的()子程序中,您可以随心所欲。它显示比查找更快,当然如果你将逻辑应用于每个文件并在脚本中执行,而不是在子进程中执行它。
如果要在多个进程中中断处理,我建议使用Parallel :: ForkManager迭代顶级子目录。
顺便说一句,我不担心实例化多个PFM对象。这是你最不担心的事情。每个子进程递归实现10个子进程的风险更大。
还有一件事:如果您仍想继续使用递归PFM方法,您可以尝试在Benchmark工具中相互运行这两种实现。