我有一个工作的perl脚本,它扫描一个目录并使用imgsize http://dktools.sourceforge.net/imgsize.html获取png文件的宽度等。有没有人有任何关于加快这个过程的技巧(现在,平均每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分钟处理1000个imgs到每 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";
}
}
}
答案 0 :(得分:8)
您展示的Perl代码可能不是罪魁祸首。您可以使用Devel::NYTProf对其进行分析,就像@choroba所说的那样。但我敢打赌,大部分时间来自每个图像分支两个外部进程(imgsize
和cut
)。您应该查看可以在不运行任何外部进程的情况下检索图像高度的Perl模块。想到Image::Info之类的模块。
答案 1 :(得分:2)
在循环中启动外部进程通常是让事情变得缓慢的好方法。启动另一个流程需要付出很大的代价,如果你为每个图像做这件事,你会很快注意到这个成本。你也在调用cut
,这意味着每次循环都会进行两次调用。
因此,第一步是使用本地Perl字符串操作执行cut
所做的操作,从而消除每个循环的一个进程启动。
不幸的是,完全消除流程成本的唯一方法是在进程中执行所有操作,这意味着您需要一个可以从Perl调用的库,它可以读取图像并获取其大小。我没有尝试过,但是Perl::ImageMagick
可能值得一看,我相信还有其他人。
您还可以尝试使用fork
或线程分割您自己的进程,并让每个子进程并行执行部分加载,但您可能会遇到系统上I / O可用性问题。