多线程 – Perl线程中的垃圾收集

前端之家收集整理的这篇文章主要介绍了多线程 – Perl线程中的垃圾收集前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这个问题是好奇心,因为下面的两个项目之一有效.

我正在使用Image :: Magick调整大量照片的大小.为了节省一些时间,我在自己的线程中处理每张照片,并使用信号量来限制同时工作的线程数.最初我允许每个线程一次运行,但脚本会快速为所有照片分配3.5 GB(我只有2GB可用),并且由于所有交换到磁盘,脚本将比正常情况慢5倍.

工作的信号量版本代码如下所示:

  1. use threads;
  2. use Thread::Semaphore;
  3. use Image::Magick;
  4.  
  5. my $s = Thread::Semaphore->new(4);
  6. foreach ( @photos ) {
  7. threads->create( \&launch_thread,$s );
  8. }
  9. foreach my $thr ( reverse threads->list() ) {
  10. $thr->join();
  11. }
  12.  
  13. sub launch_thread {
  14. my $s = shift;
  15. $s->down();
  16. my $image = Image::Magick->new();
  17.  
  18. # do memory-heavy work here
  19.  
  20. $s->up();
  21. }

这样可以快速分配500MB,运行得非常好而不需要更多. (线程以相反的顺序连接以构成一个点.)

我想知道是否可能会同时启动80个线程并阻塞大部分线程,所以我改变了我的脚本以阻止主线程:

  1. my $s = Thread::Semaphore->new(4);
  2. foreach ( @photos ) {
  3. $s->down();
  4. threads->create( \&launch_thread,$s );
  5. }
  6. foreach my $thr ( threads->list() ) {
  7. $thr->join();
  8. }
  9.  
  10. sub launch_thread {
  11. my $s = shift;
  12. my $image = Image::Magick->new();
  13.  
  14. # do memory-heavy work here
  15.  
  16. $s->up();
  17. }

此版本开始正常,但逐渐累积原始版本使用的3.5GB空间.它比一次运行所有线程更快,但仍然比阻塞线程慢一点.

我的第一个猜测是,在调用join()之前,线程使用的内存不会被释放,并且因为它是阻塞的主线程,所以在它们全部被分配之前不会释放任何线程.但是,在第一个工作版本中,线程以或多或少的随机顺序传递保护,但以相反的顺序连接.如果我的猜测是正确的,那么,除了四个正在运行的线程之外,还应该等待任何时候加入(),并且此版本也应该更慢.

那么为什么这两个版本如此不同呢?

解决方法

您不需要创建超过4个线程.一个主要的好处是,这意味着减少了76个Perl解释器的副本.而且,由于所有线程在或多或少同时完成,因此收割顺序相当没有实际意义.
  1. use threads;
  2. use Thread::Queue qw( );
  3. use Image::Magick qw( );
  4.  
  5. use constant NUM_WORKERS => 4;
  6.  
  7. sub process {
  8. my ($photo) = @_;
  9. ...
  10. }
  11.  
  12. {
  13. my $request_q = Thread::Queue->new();
  14.  
  15. my @threads;
  16. for (1..NUM_WORKERS) {
  17. push @threads,async {
  18. while (my $photo = $request_q->dequeue()) {
  19. process($photo);
  20. }
  21. };
  22. }
  23.  
  24. $request_q->enqueue($_) for @photos;
  25. $request_q->enqueue(undef) for 1..NUM_THREADS;
  26. $_->join() for @threads;
  27. }

猜你在找的Java相关文章