1

ディレクトリをスキャンし、imgsizehttp://dktools.sourceforge.net/imgsize.htmlを使用してpngファイルの幅などを取得するPerlスクリプトが機能してい ます。このプロセスを高速化するためのヒントはありますか(現在、1000ファイルごとに平均5分です)?コードをなんらかの方法で最適化できるかどうか疑問に思っていました。ありがとう。

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分ごとに1000imgを処理することから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

2 に答える 2

8

あなたが示したPerlコードはおそらく犯人ではありません。@chorobaが言ったように、Devel::NYTProfでプロファイリングできます。imgsizeしかし、ほとんどの場合、画像(および)ごとに2つの外部プロセスをフォークすることでお金がかかると思いますcut。外部プロセスを実行せずに画像の高さを取得できるPerlモジュールを調べる必要があります。Image::Infoのようなモジュールが思い浮かびます。

于 2012-11-07T16:38:16.890 に答える
2

ループで外部プロセスを起動することは、通常、物事をゆっくりと進めるための優れた方法です。別のプロセスを開始するにはかなりのコストがかかります。すべての画像に対してそれを実行すると、コストにすぐに気付くでしょう。またcut、呼び出しているのは、ループを通過するたびに2回の呼び出しであることを意味します。

したがって、最初のステップは、cutネイティブのPerl文字列操作を使用して行う操作を実行することであり、ループごとに1つのプロセスの起動を排除します。

残念ながら、プロセスコストを完全に排除する唯一の方法は、すべてをインプロセスで実行することです。つまり、画像を読み取ってサイズを取得できるPerlから呼び出すことができるライブラリが必要です。試したことはPerl::ImageMagickありませんが、一見の価値があるかもしれませんし、他にもあると思います。

またはスレッドを使用して独自のプロセスを分割し、fork各子に負荷の一部を並行して実行させることもできますが、システムでのI/Oの可用性に問題が発生する可能性があります。

于 2012-11-07T16:41:33.113 に答える