Perl标竿测试模块:测量与比较 Perl 程序的执行时间
Perl 的标竿测试(Benchmark)模块可以让程序设计者很方便的测量程序的执行时间,本文将介绍这个模块的使用方式。
一般所谓的标竿测试(Benchmark)就是在特定的环境中,测试程序的执行效能,常用的测试指针有程序的执行时间、耗费的内存或 IO 的频率等等,根据这些测试数据,就可以比较不同的程序之间的效能差异。

由于操作系统、软硬件与机器当时的状况都会影响程序的执行效能,另外机器上所安装的 Perl 版本与其编译时的选项(例如 iThreads 会让 Perl 程序的整体效能提升)也都会有所影响,因此如果要比较不同程序之间的差异,只有在相同的执行环境下来测试才有意义。
Perl 的 Benchmark 是用来测量与比较程序执行时间的模块,以下是这个模块的安装与使用方式。
安装
Benchmark 是 Perl 的标准模块之一,您的系统如果有安装 Perl 的环境,通常就可以直接使用了。您可以使用这行指令看看您的系统是否有安装 Benchmark:
- perl -e 'use Benchmark'
如果没有出现任何错误信息,那就表示您的系统已经安装好 Benchmark 模块了,而如果没有安装 Benchmark 的话,就会出现类似这样的信息:
- Can't locate Benchmark.pm in @INC (you may need to install the Benchmark module) (@INC contains: /etc/perl /usr/local/lib/perl/5.18.2 /usr/local/share/perl/5.18.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.18 /usr/share/perl/5.18 /usr/local/lib/site_perl .) at -e line 1.
- BEGIN failed--compilation aborted at -e line 1.
如果在 Ubuntu Linux 下,可以使用 apt 安装:
- sudo apt-get install libbenchmark-timer-perl
基本测试
如果只是单纯要测试程序的执行时间,可以使用 new 这个方法(method):
- #!/usr/bin/perl
- use Benchmark;
# 测试开始
- $t0 = Benchmark->new;
# 要测试的源程序
- $c++ for 1 .. 10000000;
# 测试结束
- $t1 = Benchmark->new;
- $td = timediff($t1, $t0);
- print "The code took:", timestr($td), "\n";
输出为
The code took: 1 wallclock secs ( 1.20 usr + 0.07 sys = 1.27 CPU)
另外也可以使用 timeit() 来进行重复测试,再计算平均的执行时间,这样可以减少系统状态不同所造成的误差:
- #!/usr/bin/perl
- use Benchmark;
# 重复测试次数
$count = 10;
# 重复测试 $count 次指定的源程序
- $t = timeit($count, sub {
- $c++ for 1 .. 10000000;
- });
- print "$count loops of the code took:", timestr($t), "\n";
输出为
10 loops of the code took: 6 wallclock secs ( 6.12 usr + 0.41 sys = 6.53 CPU) @ 1.53/s (n=10)
这个输出中除了有执行时间的信息之外,还有平均每秒执行的次数与执行的总次数。
另外有一个 timethis() 函数,它的功能跟 timeit() 类似,不过它会将测试结果自动输出至 STDOUT:
- #!/usr/bin/perl
- use Benchmark;
- $count = 10;
# 测试并输出结果至 STDOUT
- $t = timethis($count, sub {
- $c++ for 1 .. 10000000;
- });
输出为
timethis 10: 9 wallclock secs ( 8.58 usr + 0.64 sys = 9.22 CPU) @ 1.08/s (n=10)
timethis() 的第一个 $count 参数如果指定为负数,则代表最短的 CPU 执行时间,例如:
- #!/usr/bin/perl
- use Benchmark;
# 至少让 CPU 执行 8 秒
- $count = -8;
- $t = timethis($count, sub {
- $c++ for 1 .. 10000000;
- });
输出为
timethis for 8: 9 wallclock secs ( 8.08 usr + 0.58 sys = 8.66 CPU) @ 1.27/s (n=11)
如果 $count 参数指定为 0,则会以默认的 3 秒来执行(等同于 -3)。
比较不同的程序
标竿测试除了测量单一个程序的执行时间之外,最常见的状况就是比较不同程序之间的效能差异,Benchmark 模块中也提供了一个 timethese() 函数,可以同时测量与比较多个程序的执行时间:
- #!/usr/bin/perl
- use Benchmark;
# 同时测量与比较两个程序,至少执行 5 秒
- timethese(-5, {
- shiftAssign => sub { # 第一个程序
- my @alphabet = ('A'..'Z');
- for (my $i = 0; $i < 26; $i++){
- my $letter = shift @alphabet;
- }
- },
- equalsAssign => sub { # 第二个程序
- my @alphabet = ('A'..'Z');
- for (my $i = 0; $i < 26; $i++){
- my $letter = $alphabet[$i];
- }
- }
- }
- );
输出为
Benchmark: running equalsAssign, shiftAssign for at least 5 CPU seconds...
equalsAssign: 5 wallclock secs ( 4.71 usr + 0.36 sys = 5.07 CPU) @ 60088.56/s (n=304649)
shiftAssign: 6 wallclock secs ( 5.43 usr + 0.40 sys = 5.83 CPU) @ 50626.42/s (n=295152)
这里我们可以直接从平均每秒的执行次数看出来,equalsAssign 的效能比较好。(由于两个程序实际执行的总时间是不一样的,所以这里无法直接从两个程序的总执行次数来比较)
另一个 cmpthese() 函数的使用方式跟 timethese() 相同,不过它会输出一个执行时间的比较表,方便看出不同程序之间的差异:
#!/usr/bin/perl
use Benchmark qw/cmpthese/;
# 比较两个程序,输出比较表
- cmpthese(-5, {
- shiftAssign => sub { # 第一个程序
- my @alphabet = ('A'..'Z');
- for (my $i = 0; $i < 26; $i++){
- my $letter = shift @alphabet;
- }
- },
- equalsAssign => sub { # 第二个程序
- my @alphabet = ('A'..'Z');
- for (my $i = 0; $i < 26; $i++){
- my $letter = $alphabet[$i];
- }
- }
- }
- );
输出为
Rate shiftAssign equalsAssign
shiftAssign 56443/s -- -25%
equalsAssign 75410/s 34% --
这个输出的比较表中会依照执行的能从最慢的排到最快的,这里显示 equalsAssign 比起 shiftAssign 大约快了 34% 左右。
cmpthese() 也可以直接传入 timethese() 的结果来产生比较表:
$results = timethese( ... );
cmpthese( $results );
注意事项
以下是一些测试时的一些小技巧:
尽量让测试的程序单纯化,尽可能将不重要的部分排除,这样可以让测试的数据更精准反映出程序的执行效能。
使用 timethese() 或 cmpthese() 配合负值的 $count 来指定最短的 CPU 执行时间,这样可以减少误差,一般建议使用 5 秒以上的测试时间可以得到比准确的结果。
实际测试之前,请确认您的测试源程序是正确的,如果不确定是否有正确使用 Benchmark 模块,可以先用两小段效能差很多的测试源程序下去跑,确定 Benchmark 所得到的结果跟您预期的一样。
在测试时,重点应该放在判断执行效率最好的源程序是哪一些,而不是单单只看执行的总时间,这样才比较容易获得一个最佳化的程序。
本文来源 我爱IT技术网 http://www.52ij.com/jishu/12411.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
