Benchmark - Perl コードの実行時間のベンチマークを行なう
use Benchmark qw(:all) ;
timethis ($count, "code");
# Use Perl code in strings...
timethese($count, {
'Name1' => '...code1...',
'Name2' => '...code2...',
});
# ... or use subroutine references.
timethese($count, {
'Name1' => sub { ...code1... },
'Name2' => sub { ...code2... },
});
# cmpthese can be used both ways as well
cmpthese($count, {
'Name1' => '...code1...',
'Name2' => '...code2...',
});
cmpthese($count, {
'Name1' => sub { ...code1... },
'Name2' => sub { ...code2... },
});
# ...or in two stages
$results = timethese($count,
{
'Name1' => sub { ...code1... },
'Name2' => sub { ...code2... },
},
'none'
);
cmpthese( $results ) ;
$t = timeit($count, '...other code...')
print "$count loops of other code took:",timestr($t),"\n";
$t = countit($time, '...other code...')
$count = $t->iters ;
print "$count loops of other code took:",timestr($t),"\n";
# enable hires wallclock timing if possible
use Benchmark ':hireswallclock';
Benchmark モジュールは、コードの実行時間を計測する手助けをするルーチン群を カプセル化するものです。
timethis - コードを何回か実行する
timethese - いくつかのコードを何回か実行する
cmpthese - timethese の結果を比較表として表示する
timeit - コードを実行し、時間を計測する
countit - コードの塊を与えられた時間内に何回実行できるかを調べる
現在時刻を返します。 例えば:
use Benchmark;
$t0 = new Benchmark;
# ... your code here ...
$t1 = new Benchmark;
$td = timediff($t1, $t0);
print "the code took:",timestr($td),"\n";
$Benchmark::debug フラグを設定することによって、デバッグを有効にしたり、
無効にしたりします:
debug Benchmark 1;
$t = timeit(10, ' 5 ** $Global ');
debug Benchmark 0;
繰り返し回数を返します。
以下のルーチンは、Benchmark モジュールを使うときに、現在の名前空間へ エクスポートされます:
引数: COUNT は、ループの実行回数で、CODE は実行するコードです。 CODE は、コードリファレンスか eval される文字列のどちらかです; どちらの場合も呼び出し側のパッケージで実行されます。
返り値: Benchmark オブジェクトを返します。
CODE を COUNT 回繰り返した時間を計ります。
CODE は eval する文字列か、コードリファレンスです;
どちらの場合でも CODE は呼び出し側のパッケージで実行されます。
結果は、TITLE に引き続いて時間、という形で STDOUT に出力されます。
TITLE が指定されない場合、デフォルトは "timethis COUNT" です。
STYLE は出力形式で、後述する timestr() に記述されています。
COUNT はゼロや負数も指定できます: これは、実行する CPU 秒の最低値 を 意味します。 ゼロはデフォルトの 3 秒を意味します。 例えば、最低 10 秒実行するには:
timethis(-10, $code)
あるいは、2 つのコードの断片を最低 3 秒実行するには:
timethese(0, { test1 => '...', test2 => '...'})
CPU 秒は UNIX 用語で、実(時計)時間や子プロセスで使われた時間ではなく、 プロセス自身のユーザー時間にシステム時間を加えたものです。 0.1 秒より小さい値は指定できません (例えば、もし COUNT として -0.01 を 指定すると、致命的ランタイム例外が発生します)。
CPU 秒は 最低 時間であることに注意してください:
CPU スケジューリングと、その他の OS の要素がこの試みを
複雑にしているので、ほんのもう少し多くの時間が使われます。
しかし、ベンチマーク出力は $code の 1 秒当たりの実行数を表示します;
これは実際にかかった時間より興味深い数字のはずです。
Benchmark オブジェクトを返します。
CODEHASHREF は、キーとして名前、値として eval する文字列かコードリファレンスを 含むハッシュへのリファレンスです。 CODEHASHREF のそれぞれの (KEY, VALUE) ペアについて、このルーチンが 呼び出されます
timethis(COUNT, VALUE, KEY, STYLE)
このルーチンは KEY の文字列比較順で呼び出されます。
COUNT は 0 や負数になることがあります; timethis() を参照してください。
名前をキーとした、Benchmark オブジェクトのハッシュリファレンスを返します。
二つの Benchmark 時間の差を、timestr() に渡すのに適した Benchmark オブジェクトで返します。
TIMEDIFF オブジェクトの時間を要求された STYLE で整形した
文字列を返します。
TIMEDIFF は timediff() で返されるのと同様の
Benchmark オブジェクトであることを想定しています。
STYLE は 'all', 'none', 'noc', 'nop', 'auto' のいずれかです。 'all' は利用可能な五つの時間(「壁時計」時間、ユーザ時間、 システム時間、子プロセスのユーザ時間、子プロセスのシステム時間)を それぞれ表示します。 'noc' は二つの子プロセスの時間以外の全てを表示します。 'nop' は壁時計時間と二つの子プロセスの時間だけを表示します。 'auto' (これがデフォルトです) は、子プロセスの時間が両方とも 0 の場合は 'noc' として振る舞い、それ以外では 'all' として振る舞います。 'none' は何も出力しません。
FORMAT は、時間を表示するために使われる printf(3)-形式のフォーマット指定子 (先頭の '%' 抜き)です。 デフォルトは '5.2f' です。
以下のルーチンは、明示的にインポートを要求することで、現在の名前空間へ エクスポートされます:
キャッシュされている、空ループを COUNT 回回した時間をクリアします。
全てのキャッシュされた時間をクリアします。
状況に応じて timethese() を呼び出し、それから比較表を出力します。
これは:
cmpthese( -1, { a => "++\$i", b => "\$i *= 2" } ) ;
以下のような表を出力します:
Rate b a
b 2831802/s -- -61%
a 7208959/s 155% --
この表は遅いものから早いものの順にソートされ、それぞれのテスト間の 速度のさを百分率で表示します。
cmpthese には timethese() が返すデータ構造体を渡すことも出来て:
$results = timethese( -1, { a => "++\$i", b => "\$i *= 2" } ) ;
cmpthese( $results );
両方の結果セットを見たいときに使えます。 最初の引数が bless されていないハッシュリファレンスの場合、これは RESULTSHASHREF です; それ以外の場合はこれは COUNT です。
Returns a reference to an ARRAY of rows, each row is an ARRAY of cells from the above chart, including labels. こうすると: (TBT)
my $rows = cmpthese( -1, { a => '++$i', b => '$i *= 2' }, "none" );
以下のようなデータ構造を返します:
[
[ '', 'Rate', 'b', 'a' ],
[ 'b', '2885232/s', '--', '-59%' ],
[ 'a', '7099126/s', '146%', '--' ],
]
注意: この結果値は、timethese() の結果構造体を返していた
以前のバージョンとは異なります。
もしそれがほしいなら、上述した timethese...cmpthese の 2 文の
記述法を使ってください。
Incidently, note the variance in the result values between the two examples; this is typical of benchmarking. If this were a real benchmark, you would probably want to run a lot more iterations. (TBT)
Arguments: TIME is the minimum length of time to run CODE for, and CODE is the code to run. CODE may be either a code reference or a string to be eval'd; either way it will be run in the caller's package. (TBT)
TIME is not negative. countit() will run the loop many times to
calculate the speed of CODE before running it for TIME. The actual
time run for will usually be greater than TIME due to system clock
resolution, so it's best to look at the number of iterations divided
by the times that you are concerned with, not just the iterations.
(TBT)
返り値: Benchmark オブジェクトです。
空ループのための時間のキャッシュを無効にします。 これにより、Benchmark にコードの時間を計る毎に空ループの時間を 再計算することを強制します。
空ループのための時間のキャッシュを有効にします。 異なる COUNT が使われる毎に 1 回だけ、COUNT 回の空ループの所要時間が 計算されます。
二つの Benchmark 時間の和を、timestr() に渡すのに適した Benchmark オブジェクトで返します。
If the Time::HiRes module has been installed, you can specify the
special tag :hireswallclock for Benchmark (if Time::HiRes is not
available, the tag will be silently ignored). This tag will cause the
wallclock time to be measured in microseconds, instead of integer
seconds. Note though that the speed computations are still conducted
in CPU time, not wallclock time.
(TBT)
データは、time 関数や times 関数による値のリストとして:
($real, $user, $system, $children_user, $children_system, $iters)
(各々の繰り返しごとではなく) ループ全体を秒数で計測して蓄えられます。
計時は、time(3) と times(3) を使って行なわれます。
コードは、呼び出し元のパッケージで実行されます。
空ループ (繰り返し数は同じですが、空のループ) の時間が、実際のループの 時間から差し引かれます。
計算された空ループの実行時間は、繰り返しの数をキーとして、 キャッシュされます。 キャッシュ化は、以下のようなサブルーチンの呼び出しで制御できます:
clearcache($key);
clearallcache();
disablecache();
enablecache();
キャッシュ化はデフォルトではオフです; これは(普通はわずかですが) 正確性を減少させ、普通はたいして実行時間に影響を与えないからです。
例えば、
use Benchmark qw( cmpthese ) ;
$x = 3;
cmpthese( -5, {
a => sub{$x*$x},
b => sub{$x**2},
} );
とすると、以下のようなものが出力されます:
Benchmark: running a, b, each for at least 5 CPU seconds...
Rate b a
b 1559428/s -- -62%
a 4152037/s 166% --
一方
use Benchmark qw( timethese cmpthese ) ;
$x = 3;
$r = timethese( -5, {
a => sub{$x*$x},
b => sub{$x**2},
} );
cmpthese $r;
は以下のようなものが出力されます:
Benchmark: running a, b, each for at least 5 CPU seconds...
a: 10 wallclock secs ( 5.14 usr + 0.13 sys = 5.27 CPU) @ 3835055.60/s (n=20210743)
b: 5 wallclock secs ( 5.41 usr + 0.00 sys = 5.41 CPU) @ 1574944.92/s (n=8520452)
Rate b a
b 1574945/s -- -59%
a 3835056/s 144% --
Benchmark は、Exporter からは当然継承を行なっていますが、その他の クラスからは継承を行ないません。
Comparing eval'd strings with code references will give you inaccurate results: a code reference will show a slightly slower execution time than the equivalent eval'd string. (TBT)
実際の時間の計時は、time(2) を使って行なわれますので、精度は 秒程度しかありません。
perl では、空ループの方が短いテストよりも時間がかかる場合があるので、 短いテストでは、結果が負数になる場合があります; 以下のようにしてみてください:
timethis(100,'1');
空ループのシステム時間は、実際のコードを含むループのシステム時間よりも 多少多くかかることがあるため、最終的に差がゼロより小さくなることが あるのです。
Devel::DProf - a Perl コードプロファイラ
Jarkko Hietaniemi <jhi@iki.fi>, Tim Bunce <Tim.Bunce@ig.co.uk>
September 8th, 1994; by Tim Bunce. (TBT)
March 28th, 1997; by Hugo van der Sanden: added support for code references and the already documented 'debug' method; revamped documentation. (TBT)
April 04-07th, 1997: by Jarkko Hietaniemi, added the run-for-some-time functionality. (TBT)
September, 1999; by Barrie Slaymaker: math fixes and accuracy and
efficiency tweaks. Added cmpthese(). A result is now returned from
timethese(). Exposed countit() (was runfor()).
(TBT)
December, 2001; by Nicholas Clark: make timestr() recognise the style 'none'
and return an empty string. If cmpthese is calling timethese, make it pass the
style in. (so that 'none' will suppress output). Make sub new dump its
debugging output to STDERR, to be consistent with everything else.
All bugs found while writing a regression test.
(TBT)
September, 2002; by Jarkko Hietaniemi: add ':hireswallclock' special tag. (TBT)
February, 2004; by Chia-liang Kao: make cmpthese and timestr use time statistics for children instead of parent when the style is 'nop'. (TBT)
November, 2007; by Christophe Grosjean: make cmpthese and timestr compute time consistently with style argument, default is 'all' not 'noc' any more. (TBT)