如何对Perl代码进行速度基准测试
使用Benchmark模块,对Perl代码进行速度基准测试非常简单。本文将讨论基准测试的一般方法和如何使用Benchmark模块。
什么是基准测试?
在编程中,基准测试是对某些代码在特定时间点的性能进行测量。代码性能的任何方面都可以进行基准测试:速度、内存使用和IO频率是一些常见的指标。
基准测试的限制
在基准测试中需要注意的一点是,它们受环境的影响:操作系统、硬件、软件和当前机器状态都可能影响基准测试。对于Perl代码来说,当前的Perl版本和Perl安装时使用的编译选项可以对代码性能产生重大影响。例如,如果Perl是用iThreads启用编译的,这将增加所有Perl程序的开销。因此,只有在基准测试环境相同的情况下,基准测试比较才有意义。
Perl的Benchmark模块
Benchmark 已包含在Perl核心中,因此如果您已安装Perl,则应该已经安装了Benchmark。如果您在使用类UNIX的系统上,则可以考虑安装Benchmark::Forking,因为它可以提高基准测试的准确性。Benchmark::Forking 是 Benchmark 的一个即插即用替代品,以下的所有代码示例都将与这两个模块一起工作。
计时Perl代码
当比较代码性能时,基准测试最为有趣——因此我们将关注执行此操作的方法。Benchmark提供了一个timethese
子程序,它连续执行一组Perl代码一定数量的CPU秒,然后打印出结果。让我们比较两个常用Perl操作的执行速度:使用shift内置函数进行数组赋值和直接使用等于进行数组赋值。
use strict;
use warnings;
use Benchmark qw/cmpthese timethese/;
timethese(-10, {
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 10 CPU seconds...
equalsAssign: 10 wallclock secs (10.32 usr + 0.00 sys = 10.32 CPU) @ 150112.98/s (n=1549166)
shiftAssign: 11 wallclock secs (10.43 usr + 0.00 sys = 10.43 CPU) @ 148529.82/s (n=1549166)
要关注的关键指标是每CPU秒的速率。这表明shiftAssign代码块以148,529.82/s的速度执行,而equalsAssign块执行得稍微快一点,以150,112.98/s的速度执行。请注意,每个块的测试运行了不同长的时间——因此输出中的其他数字不可直接比较。
比较Perl代码
Benchmark模块提供的cmpthese
子程序接受与上面所示的timethese
相同的参数,但它会打印出有用的比较表格,显示哪个代码块更快,以及其百分比。方便的是,它还包括每CPU秒的速率。
use strict;
use warnings;
use Benchmark qw/cmpthese timethese/;
cmpthese(-10, {
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 142529/s -- -4%
equalsAssign 148159/s 4% --
上述结果按从慢到快的顺序排列(如速率/s所示)。这个基准测试表明,equalsAssign代码块比shiftAssign代码块快4%。
其他技巧
- 尽量使用最少的代码来满足所需的行为——这将提高基准测试的准确性。
- 为
timethese
或cmpthese
指定负数作为CPU秒计数。这指定了要运行的最小CPU秒数。一些来源推荐至少-5秒以避免不准确的基准测试。 - 对结果进行合理性检查:如果您不确定,请尝试比较两个代码块,其中一个显然比另一个慢,以检查Benchmark是否返回合理的结果。
- 比较代码示例而不是单独计时:代码块的实际执行时间通常并不重要;知道哪组代码比另一组快是有用的,因为这通常是一个可重复发生的情况。
- 如果您需要更深入的基准测试,请考虑使用Devel::NYTProf。
来源
本文特别借鉴了以下几方面的信息:brian d foy的Benchmarking Perl讲义和David Golden的Adventures in Benchmarking文章。
本文最初发布在PerlTricks.com。
标签
反馈
这篇文章有什么问题吗?请通过在GitHub上打开一个issue或pull request来帮助我们。