Perlでshを呼び出した場合の実行速度

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;
}