那天和人讨论一个简单的应用:集合减法,即给定集合 A 和 B ,计算 C = A - B, 也就是说求属于A但不属于B的元素。集合A和B使用数组来存储,元素仅限于整数。 求计算方法。
Perl自身没有集合运算函数,为了这一个功能也犯不上去安装CPAN模块, 所以我们考虑了以下几个方案:
- 利用foreach作最直白的循环来判断
- 利用grep代替foreach
- 将元素用逗号连接之后用正则表达式匹配
- 将数组转化成散列之后判断
四种方法都能实现,但效率如何?本以为使用foreach应该是最快的, 没想到测试之后发现散列居然是最快的。
Rate use grep use regexp use foreach use hash use grep 359/s -- -58% -63% -90% use regexp 861/s 140% -- -11% -77% use foreach 965/s 169% 12% -- -74% use hash 3769/s 950% 338% 291% --
如果元素不是整数而是随机的字符串,正则表达式的效率会急剧下降,而散列依然能保证领先的地位。 看来Perl的散列算法不可小觑啊。
阅读全文 »Devel::SmallProf 是个很好用的模块,可以方便地测量出代码每一行的执行时间,以便进一步优化。
例如以下程序,文件名为 prof_sample.pl。
#!/usr/bin/perl
my $str = "0";
for (my $i = 0; $i < 100; $i++) {
$str =~ s/\d+/($&+1)/e;
print $str."\n";
}
该程序的功能是输出整数 1 到 100。当然实际写程序时可不要用这么低效率的方法。 安装 Devel::SmallProf 之后我们来测量一下它每一行代码的执行时间。
perl -d:SmallProf prof_sample.pl
执行之后会在当前目录下生成一个 smallprof.out 文件,其内容如下:
================ SmallProf version 1.15 ================
Profile of prof_sample.pl Page 1
=================================================================
count wall tm cpu time line
0 0.000000 0.000000 1:#!/usr/bin/perl
0 0.000000 0.000000 2:
1 0.000006 0.000000 3:my $str = "0";
101 0.006418 0.010000 4:for (my $i = 0; $i < 100; $i++) {
200 0.002581 0.000000 5: $str =~ s/\d+/($&+1)/e;
100 0.001509 0.000000 6: print $str."\n";
1 0.000003 0.000000 7:}
前三列的数字分别为执行次数、消耗时间、消耗CPU时间。
如果你的程序使用 use 语句引用了其他模块,那么所有被引用的程序都将被分析,生成一个长长的报告。这时可以使用下面的命令来迅速找到耗时最长的命令。
sort -k 2nr,2 smallprof.out | less
