Parallel-ForkManager,DBI.比之前分叉更快,但仍然太慢

Mik*_*min 1 perl performance fork dbi

我有一个非常简单的任务来更新数据库.

my $pm = new Parallel::ForkManager(15);
for my $line (@lines){
    my $pid = $pm->start and next;
    my $dbh2 = $dbh->clone();
    my $sth2 = $dbh2->prepare("update db1 set field1=? where field2 =?");           
    my ($field1, $field2) = very_slow_subroutine();
    $sth2->execute($field1,$field2);
    $pm->finish;        
} 
 $pm->wait_all_children;    
Run Code Online (Sandbox Code Playgroud)

我可以使用$ dbh2-> do,但我怀疑这是一个缓慢的原因.

有趣的是,它看起来很快就开始了这15个过程(或者我指定的任何过程),但是在那之后急剧减速,仍然明显快于没有分叉,但我希望更多......

编辑:

very_slow_subroutine是sub,它从Web服务获得答案.该服务可以在几秒到几秒的时间内回答.我要问十万次......我想做一个叉子的原因.

如果这很重要 - 我在Linux上.

Sch*_*ern 6

Parallel :: ForkManager不会让事情变得更快,它只是让你多次同时运行你的代码.为了从中获益,您必须设计并行代码.

这样想吧.你需要10分钟才能到达商店,购物,装车,回来和卸载它.你需要得到5个负载.你可以在50分钟内完成.这是串行工作.10分钟*5次一个接一个= 50分钟.

假设你有四个朋友可以帮忙.你们都在同一时间开始营业.仍然有5次旅行,他们仍然需要10分钟,但因为你并行完成,总时间只有10分钟.

但是,无论你需要做多少次旅行或者有多少朋友可以提供帮助,它都不会少于10分钟.这就是为什么这个过程快速启动,每个人都进入他们的汽车并开车到商店,但一段时间没有任何事情发生,因为每个人仍然需要10分钟才能完成他们的工作.

这里也是一样的.你的循环体需要X时间才能运行.如果你迭代它Y次,它将需要X*Y现实世界的人类时间来运行.如果你并行运行Y次,理想情况下运行只需要X次.每个并行工作者仍然必须在X时间内执行循环的整个主体.

为了进一步加快速度,你要分手的一大瓶颈very_slow_subroutine,使并行工作.您的SQL非常简单,您应该将精力集中在优化和并行性上.

假设商店非常接近,它只有1分钟的车程(这是你的SQL更新),但购物,装货和卸货需要9分钟(这是very_slow_subroutine).如果相反,你有5辆车和15个朋友.每辆车装3个人.开车往返商店将需要同一时间,但现在有三个人一起工作,只需4分钟即可完成购物,装卸.现在每次旅行需要5分钟而不是10分钟.

这代表了重新设计very_slow_subroutine以并行完成其工作.如果它只是一个大循环,你可以在这个循环上放置更多的工人.如果是一系列慢速操作,则必须重新设计它以利用并行执行.

如果你使用太多的工人,你可能会阻塞系统,这取决于瓶颈是什么.如果它受CPU限制并且你有2个CPU内核,你可能会看到性能提升最多3到5个工作者(这(cores * 2)+1是一个很好的经验法则),之后性能会下降,因为CPU花费更多时间在进程之间切换而不是做工作.如果瓶颈是IO,或者通常是数据库和网络调用的外部服务,您可以看到很多工作人员在解决问题时的效率很高.当一个进程正在等待磁盘或网络操作时,其他进程可以使用您的CPU.