2012-11-07 66 views
1

我有一個工作perl腳本,它可以掃描一個目錄並使用imgsize http://dktools.sourceforge.net/imgsize.html來獲取png文件的寬度等。有沒有人有加快這個過程的任何提示(現在,每1000個文件平均5分鐘)?我只是想知道如果代碼可以優化一些如何。謝謝。在perl中加速foreach循環

use strict; 
use warnings; 

use File::Find; 

my @files; 
my $directory = '/Graphics/'; 
my $output_file = '/output_file'; 
my $max_height = 555; 
my $count = 0; 

open (OUTPUT, '>>', $output_file); 

find(\&wanted, $directory); 

foreach my $file (@files) { 
     if ($file =~ /\.png$/) { 
       my $height = `imgsize $file | cut -d\'\"\' -f4`; 
       if ($height > $max_height) { 
         print OUTPUT "$file\n"; 
       } 

       $count++; 

       my $int_check = $count/1000; 
       if ($int_check !~ /\D/) { 
         print "processed: $count\n"; 
       } 
     } 
} 

print "total: $count\n"; 
close (OUTPUT); 
exit; 

sub wanted { 
    push @files, $File::Find::name; 
    return; 
} 

解決方案:原來我是能夠使用Image::Info模塊。我從每5分鐘處理1000張圖片到每12秒。以下是相關的代碼片段,如果有人感興趣:

use Image::Info qw(image_info); 

    foreach my $file (@files) { 
      if ($file =~ /\.png$/) { 
        my $output = image_info($file); 
        my $height = ${$output}{height}; 

        if ($height > $max_height) { 
          print OUTPUT "$file\n"; 
        } 

        $count++; 

        my $int_check = $count/1000; 
        if ($int_check !~ /\D/) { 
          print "processed: $count\n"; 
        } 
      } 
    } 
+4

你是否描述過腳本? [DeveL :: NYTProf](http://p3rl.org/Devel::NYTProf)非常適合分析。 – choroba

+0

我假設瓶頸是'imgsize'應用程序。你可以嘗試並行運行多個實例。見例如[Parallel :: ForkManager](http:// p3rl/Parallel :: ForkManager) – ElPaco

+0

謝謝@choroba我會研究一下。 –

回答

8

您顯示的Perl代碼可能不是罪魁禍首。你可以用Devel::NYTProf來描述它,就像@choroba所說的那樣。但我敢打賭,大多數情況下,金錢來源於每個圖像分兩個外部進程(imgsizecut)。您應該查看可以檢索圖像高度而不運行任何外部進程的Perl模塊。想到像Image::Info這樣的模塊。

+0

是的,我可能應該看看其他模塊。我忽略的一個問題是,這些圖像不包含元數據,從而否定Image :: Info的可能性。 –

+1

我不知道'Image :: Info'如何在內部工作,但是每個圖像都必須至少將其大小存儲在其標題中。否則,它不能被解碼(除非這些信息存儲在外部,它似乎不是你的情況)。所以如果'Image :: Info'不適合你的圖像,那麼其他人應該仍然能夠解析這些重要的標題。 –

+0

啊,我不知道這些圖像,謝謝你的額外信息。 –

2

在循環中啓動外部進程通常是讓事情變得緩慢的好方法。啓動另一個流程需要花費很大的成本,如果您爲每張圖片都做這件事,那麼您將很快注意到成本。您還打電話給cut,這意味着每次循環都需要兩次調用。

因此,第一步將執行cut使用本地Perl字符串操作所執行的操作,並因此消除每個循環的一個進程啓動。

不幸的是,完全消除流程成本的唯一方法是在進程中完成所有任務,這意味着您需要一個可以從Perl調用的庫,它可以讀取圖像並獲取其大小。我還沒有嘗試過,但Perl::ImageMagick可能值得一看,而且我確定還有其他人。

您也可以嘗試拆分自己的進程,或者使用fork或線程,並讓每個子進程並行執行一部分負載,但是可能會遇到系統中I/O可用性問題。

+0

感謝馬修,但沒有'Perl :: ImageMagick'可用於此,但顯然我可以查看其他模塊。 –