1

ucm2.plスクリプトを実行して、巨大なディレクトリ構造をスキャンしています(ディレクトリはローカルにマップされたネットワークドライブです)。2つのperlスクリプトucm1.plとucm2.plがあります。私はさまざまな引数に対してucm2.plを並列に実行しており、ucm1.plを介して呼び出されます。

ucm1.pl-

    #!/usr/bin/perl
    use strict; 
    use warnings;
    use Parallel::ForkManager;

    my $filename ="intfSplitList.txt"; #(this will have list of all the input files. eg intfSplit_0....intfSplit_50)
     my $lines;
     my $buffer;
        open(FILE, $filename) or die "Can't open `$filename': $!";
        while (<FILE>) {
            $lines = $.;
        }
        close FILE;
    print "The number of lines in $filename is $lines \n";


    my $pm = Parallel::ForkManager->new($lines); #(it will set the no. of parallel processes)

    open (my $fh, '<', "intfSplitList.txt") or die $!;
    while (my $data = <$fh>) {
      chomp $data;

      my $pid = $pm->start and next;

     system ("perl ucm2.pl -iinput.txt -f$data");  
#(call the ucm2.pl) #(input.txt file will have search keyword and $data will have intfSplit_*.txt files)

      $pm->finish; # Terminates the child process
    }

ucm2.plコード-

#!/usr/bin/perl
use strict;
use warnings;  
use File::Find;
use Getopt::Std;
#getting the input parameters
getopts('i:f:');

our($opt_i, $opt_f);
my $searchKeyword     = $opt_i;                               #Search keyword file.
my $intfSplit         = $opt_f;                               #split file
my $path              = "Z:/aims/";                           #source directory
my $searchString;                                             #search keyword

open FH, ">log.txt";                                          #open the log file to write

print FH "$intfSplit ". "started at ".(localtime)."\n";       #write the log file

open (FILE,$intfSplit);                                       #open the split file to read

while(<FILE>){

   my $intf= $_;                                             #setting the interface to intf
   chomp($intf);
   my $dir = $path.$intf;
   chomp($dir);
   print "$dir \n";                                              
   open(INP,$searchKeyword);                         #open the search keyword file to read

   while (<INP>){      

   $searchString =$_;                           #setting the search keyword to searchString
   chomp($searchString);
   print "$searchString \n";
   open my $out, ">", "vob$intfSplit.txt" or die $!; #open the vobintfSplit_* file to write

#calling subroutine printFile to find and print the path of element
find(\&printFile,$dir);                                       

#the subroutine will search for the keyword and print the path if keyword is exist in file.
sub printFile {
   my $element = $_;

   if(-f $element && $element =~ /\.*$/){ 

      open my $in, "<", $element or die $!;
      while(<$in>) {
         if (/\Q$searchString\E/) {
            my $last_update_time = (stat($element))[9];
            my $timestamp  = localtime($last_update_time);
            print $out "$File::Find::name". "     $timestamp". "     $searchString\n";
            last;
          }
        }
      }
    }
  }
}
print FH "$intfSplit ". "ended at ".(localtime)."\n";         #write the log file

すべてが正常に実行されていますが、単一のキーワード検索でも非常に長い時間実行されています。誰かがパフォーマンスを改善するためのより良い方法を提案できますか?

前もって感謝します!!

4

1 に答える 1

1

Perl の複数のインスタンスを実行すると、多くの不要なオーバーヘッドが追加されます。これを変更することを提案した、以前の質問に対する私の回答をご覧になりましたか?

また、前に述べたように、ここで不必要な繰り返しがあります。検索キーワード ファイルを複数回開いて処理する理由はありません。キーワード ファイルを開き、キーワードを配列に入れる 1 つのサブを作成できます。次に、これらのキーワードを検索を行う別のサブに渡します。

一度に複数のキーワードを検索することで、複数のキーワードの検索を大幅に高速化できます。キーワードを取得するには、次のようにします。

my @keywords = map {chomp;$_} <$fh>;
my $regex = "(" . join('|', map {quotemeta} @keywords) . ")";

これで、次のような単一の正規表現ができました: (\Qkeyword1\E|\Qkeyword2\E). ファイルを 1 回検索するだけでよく、どのキーワードが一致したかを確認したい場合は、 の内容を確認するだけです$1。1 つのキーワードの場合は高速化されませんが、多数のキーワードの検索は、1 つのキーワードの検索とほぼ同じ速度になります。

ただし、最終的には、ネットワーク上の巨大なディレクトリ構造を検索している場合、速度を上げるには限界があるかもしれません。

更新:チョッピングを修正しました。ありがとうアモン。

于 2013-02-01T10:50:56.303 に答える