Perlで、shを実行できますよね。
shって結構お手軽で便利なコマンドがあるので、perlの中でも使いがちがんですが、実はかなり実行速度が遅いんですよね。
こういう話をどっかで聞いていたんで、実際にテストしてみました。
このテストでは、perlでファイルをreadするときに、perl内でハンドルをopenして読み込むか、sh呼び出してcatを用いるかで比較しました。
するとこんな結果になりました。
# ./roupe_test.pl === Start!! === --- PERL_TEST(FILE Read [perl_roupe]) --- [test 1](0s .85510ms) [test 2](0s .73861ms) [test 3](0s .73888ms) [test 4](0s .74111ms) [test 5](0s .74027ms) --- PERL_TEST(FILE Read [sh_roupe]) --- [test 1](4s .-69818ms) [test 2](4s .-182927ms) [test 3](4s .-141415ms) [test 4](4s .-171225ms) [test 5](3s .855982ms) === Finish!! ===
これって結構な差ですよね。
実際にperl上でshを呼び出すときのメモリの使い方とかは、厳密にチェックしてないので、完璧なテストではないですが、目安にはなると思います。
perlでsh呼び出す方が、約50倍くらい遅いです。
これって、この処理を多様してたら、単純計算でPerlで1分の処理が、sh使ってファイルreadすると50分かかるんですよね。
意外なほどの差が出ました。
コーディングでは気をつけた方がよさそうです。
ソースは以下
#!/usr/bin/perl
use warnings;
use strict;
use Time::HiRes qw(gettimeofday);
####################
### MAIN ROUTINE ###
####################
my $count_max = 1000;
my ($i,$run_flug,$run_time);
my %type = (1,"perl_roupe",
2,"sh_roupe");
print "=== Start!! ===\n";
for ($run_flug=1 ;$run_flug<=2 ;$run_flug++)
{
print "--- PERL_TEST(FILE Read [$type{$run_flug}]) ---\n";
for ($i=1 ;$i<=2 ;$i++)
{
print "[test $i](";
if($run_flug == 1)
{
$run_time = perl_roupe($count_max);
}
elsif($run_flug == 2)
{
$run_time = sh_roupe($count_max);
}
else
{
die "=== Error!!===\n";
}
printf $run_time.")\n";
}
print "\n";
}
print "=== Finish!! ===\n";
###################
### SUB ROUTINE ###
###################
sub sh_roupe
{
local(*count_max);
my $sh_value = "";
my $count = 0;
my $run_time;
my ($Ssec,$Smicrosec) = gettimeofday;
while($count_max != $count)
{
$sh_value = `cat test.txt`;
$count++;
}
my ($Fsec,$Fmicrosec) = gettimeofday;
$run_time = $Fsec - $Ssec;
$run_time .= "s .";
$run_time .= $Fmicrosec - $Smicrosec;
$run_time .= "ms";
return $run_time;
}
sub perl_roupe
{
local(*count_max);
my $perl_value = "";
my $count = 0;
my $run_time;
my ($Ssec,$Smicrosec) = gettimeofday;
while($count_max != $count)
{
open(HANDLE, "< test.txt");
$perl_value = ;
close HANDLE;
$count++;
}
my ($Fsec,$Fmicrosec) = gettimeofday;
$run_time = $Fsec - $Ssec;
$run_time .= "s .";
$run_time .= $Fmicrosec - $Smicrosec;
$run_time .= "ms";
return $run_time;
}