为阻塞操作启动新线程是不好的做法(Perl)

joh*_*doe 11 perl multithreading thread-safety blocking

如果执行CPU密集型任务,我认为每个核心有一个线程是最佳的.如果你有一个4核CPU,你可以运行4个CPU密集子程序实例而不会受到任何惩罚.例如,我曾经在四核CPU上实验性地运行了四个CPU密集型算法实例.每个过程最多四次没有减少.在第五个实例中,所有实例都需要更长

阻止操作的情况如何?假设我有一个包含1,000个网址的列表.我一直在做以下事情:

(请不要介意任何语法错误,我只是嘲笑这个)

my @threads;
foreach my $url (@urlList) {    
     push @threads, async {
         my $response = $ua->get($url);
         return $response->content;   
     }
}

foreach my $thread (@threads) {
    my $response = $thread->join;
    do_stuff($response); 
}
Run Code Online (Sandbox Code Playgroud)

我基本上开始了与URL列表中的URL一样多的线程.如果有一百万个网址,则会启动一百万个主题.这是最优的,如果不是最佳线程数吗?对于可以等待的任何阻塞I/O操作(读取文件,数据库查询等),使用线程是一种很好的做法吗?

相关奖金问题

出于好奇,Perl线程的工作方式与Python相同,而且它是GIL吗?使用python来获得多线程的好处,并将所有内核用于CPU密集型任务,您必须使用多处理.

hob*_*bbs 12

出于好奇,Perl线程的工作方式与Python相同,而且它是GIL吗?使用python来获得多线程的好处,并将所有内核用于CPU密集型任务,您必须使用多处理.

不,但结论是一样的.Perl 没有一个很大的锁来保护跨越线程的解释器; 相反,它为每个不同的线程都有一个重复的解释器.由于变量属于解释器(并且只有一个解释器),因此默认情况下不会在线程之间共享数据.当显式共享变量时,它们被放置在共享解释器中,该解释器代表其他线程序列化对共享变量的所有访问.除了其他人提到的内存问题之外,Perl中的线程还存在一些严重的性能问题,以及可以共享的数据类型的限制以及使用它可以执行的操作(有关详细信息,请参阅perlthrtut) .

结果是,如果您需要并行化大量IO并且可以使其无阻塞,那么您将从事件循环模型中获得比线程更多的性能.如果你需要并行化不能非阻塞的东西,你可能会比使用perl线程更多的运气(一旦你熟悉这种代码,它也更容易调试).

也可以将两个模型结合起来(例如,使用POE :: Wheel :: RunAnyEvent :: Run,或者一个多进程应用程序将一些昂贵的工作传递给子进程有一个管理非公平孩子的父母,或者一个Node Cluster类型的设置,你有一些preforked事件的web服务器,父母只有accepts并将FD 传递给它的孩子).

但是,至少还没有银子弹.