我正在制作 2 个 fork 。
我有两个案例:
- 我只记下每个 fork 的时间
- 我记下每个 fork 的时间,然后执行一些步骤,例如请求一个网站。
根据我的理解,在这两种情况下,两个 child 的开始时间差异应该在相同的范围内。但在这两种情况下,存在很大差异。
case1代码:
use Parallel::ForkManager;
use WWW::Mechanize;
use LWP::UserAgent;
use Time::HiRes qw/gettimeofday/;
use Time::Format qw/%time/;
use POSIX qw( strftime );
use Time::HiRes qw( gettimeofday );
$count = 2;
$pm = new Parallel::ForkManager( $count );
for ( 1 .. $count ) {
print "$_ ";
my ( $secs, $microsecs ) = gettimeofday();
print
strftime( "%H:%M:%S", localtime( $secs ) ) .
sprintf(".%04d", $microsecs / 10 );
print "\n";
$pm->finish;
}
$pm->wait_all_children; ## wait for the child processes
输出:
1 20:53:25.41494
2 20:53:25.65602
所以,基本上我想使用 Perl 进行一些机械化操作,但我需要所有子级同时开始执行,但这里不是这种情况。我需要将近 1000 个 child 同时开始执行。请改进我的代码,或提供更好的实现方法。
最佳答案
您不创建任何子进程!!!在循环的开头添加以下内容:
$pm->start and next;
您现在最关心的似乎是吞吐量(1000 请求/秒),而不是请求何时开始。在这种情况下,您可以通过提前创建并重用它们来完全消除启动新 worker 所需的时间。这称为工作池模型,可以找到一个简单的示例 here . (该示例使用线程,但如果愿意的话,相同的模型也可以用于进程。)
现在,即使您通过重用工作人员来消除启动工作人员所需的时间,也不会留给您太多时间来实际构建请求和处理响应。如果 完美 分布在 8 个内核中,则每个请求只会得到 8 毫秒。
1000 req/s
= 1000/8 req/s on each core
= 125 req/s on each core
= 8 ms/req
这不是很多。您可能需要优化代码。我会放弃 LWP,转而使用 Net::Curl::Multi。事实上,如果您使用 Net::Curl::Multi,所有请求都应该由一个线程(主线程?)发出,尽管您可能仍想在工作线程中准备请求和处理响应。
关于windows - 我不明白为什么在 Perl 中使用 Parallel::ForkManager 时所有 fork 的子节点不会同时启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31728293/