Performance 给Perl';是打印列表还是连接字符串?
备选方案A:Performance 给Perl';是打印列表还是连接字符串?,performance,perl,printing,Performance,Perl,Printing,备选方案A: print $fh $hr->{'something'}, "|", $hr->{'somethingelse'}, "\n"; 备选案文B: print $fh $hr->{'something'} . "|" . $hr->{'somethingelse'} . "\n"; 除非执行数百万条这样的语句,否则性能差异将无关紧要。我真的建议将注意力集中在存在性能问题的地方,而找出问题的唯一方法是分析应用程序 早熟优化是Joel和Jeff多年来一直在播客上
print $fh $hr->{'something'}, "|", $hr->{'somethingelse'}, "\n";
备选案文B:
print $fh $hr->{'something'} . "|" . $hr->{'somethingelse'} . "\n";
除非执行数百万条这样的语句,否则性能差异将无关紧要。我真的建议将注意力集中在存在性能问题的地方,而找出问题的唯一方法是分析应用程序 早熟优化是Joel和Jeff多年来一直在播客上抱怨的事情。在你知道某件事情进展缓慢之前,尝试优化它只是浪费时间 更新: 我只是做了我自己的测试 每个版本的1000000次迭代每次<1秒
对于列表版本,每个版本的10毫米迭代平均耗时2.35秒,而对于字符串concat版本,平均耗时2.1秒您是否确实尝试过对此进行分析?只需要几秒钟
在我的机器上,B似乎更快。然而,你真的应该看看。你已经在思考这个问题上浪费了太多太多的时间,这是你在任何程序运行中都无法节省的。对于像这样琐碎的问题(字符替换!),您应该等到实际出现问题时再考虑。在这三个选项中,我可能会首先选择字符串插值,然后对无法插值的表达式切换为逗号。有趣的是,这意味着我的默认选择是最慢的,但考虑到它们在速度上彼此非常接近,而且磁盘速度可能会比其他任何东西都慢,我不认为更改方法有任何真正的性能好处 正如其他人所说,编写代码,然后分析代码,然后检查您选择的算法和数据结构,这些算法和数据结构位于代码的缓慢部分,最后,查看算法和数据结构的实现。其他任何事情都是愚蠢的微观优化,浪费的时间比节省的时间多 你可能还想读书
Perl是一种高级语言,因此,您在源代码中看到的语句不会直接映射到计算机实际要做的事情。您可能会发现,
perl
的一个特定实现使一件事情比另一件事情快,但这并不能保证另一个实现会夺走这一优势(尽管它们尽量不让事情变慢)
如果您担心I/O速度,那么在您开始担心逗号和句点之前,还有许多更有趣、更有用的东西需要调整。例如,请参见下面的讨论。答案很简单,没关系。正如许多人指出的,这不会成为您的程序的瓶颈。优化这一点,使之即时发生,不太可能对您的性能产生任何影响。您必须首先配置文件,否则您只是在猜测和浪费时间 如果我们要在这上面浪费时间,至少让我们把它做好。下面是做一个现实基准测试的代码。它实际上打印并将基准信息发送给STDERR。您可以将其作为
perl benchmark.plx>/dev/null
运行,以防止输出淹没屏幕
这里有500万次迭代写入标准输出。通过使用timethers()
和cmpthese()
我们获得了所有的基准数据
$ perl ~/tmp/bench.plx 5000000 > /dev/null
Benchmark: timing 5000000 iterations of concat, list...
concat: 3 wallclock secs ( 3.84 usr + 0.12 sys = 3.96 CPU) @ 1262626.26/s (n=5000000)
list: 4 wallclock secs ( 3.57 usr + 0.12 sys = 3.69 CPU) @ 1355013.55/s (n=5000000)
Rate concat list
concat 1262626/s -- -7%
list 1355014/s 7% --
这里有500万写入临时文件
$ perl ~/tmp/bench.plx 5000000
Benchmark: timing 5000000 iterations of concat, list...
concat: 6 wallclock secs ( 3.94 usr + 1.05 sys = 4.99 CPU) @ 1002004.01/s (n=5000000)
list: 7 wallclock secs ( 3.64 usr + 1.06 sys = 4.70 CPU) @ 1063829.79/s (n=5000000)
Rate concat list
concat 1002004/s -- -6%
list 1063830/s 6% --
请注意,额外的挂钟和系统时间强调了打印内容与打印内容的重要性
列表版本大约快了5%(请注意,这与Pavel的逻辑背道而驰,Pavel的逻辑强调了试图把这些东西想清楚是徒劳的)。你说你在做成千上万的这些?让我们看看。。。100k在我的笔记本电脑上占用了146ms的挂钟时间(它的I/O很糟糕),所以你在这里能做的最好的事情就是把时间缩短7毫秒。祝贺如果你花一分钟思考这个问题,那么在你完成这段时间之前,你需要对代码进行40k次迭代。更不用说机会成本了,在那一分钟,你本可以优化更重要的东西
现在,有人会说“既然我们知道哪种方式更快,我们应该以最快的方式编写它,并在我们编写的每个程序中节省时间,从而使整个练习变得有价值!”不。它仍然占程序运行时间的一小部分,远低于衡量一条语句所占的5%。其次,这样的逻辑使您将微观优化置于可维护性之上
哦,5.8.8和5.10.0是不同的
$ perl5.8.8 ~/tmp/bench.plx 5000000 > /dev/null
Benchmark: timing 5000000 iterations of concat, list...
concat: 3 wallclock secs ( 3.69 usr + 0.04 sys = 3.73 CPU) @ 1340482.57/s (n=5000000)
list: 5 wallclock secs ( 3.97 usr + 0.06 sys = 4.03 CPU) @ 1240694.79/s (n=5000000)
Rate list concat
list 1240695/s -- -7%
concat 1340483/s 8% --
它甚至可能会根据您使用的Perl I/O层和操作系统而改变。所以整个练习都是徒劳的
微观优化是一个愚蠢的游戏。始终首先配置文件,并寻求优化您的算法。是一个优秀的剖析器
#!/usr/bin/perl -w
use strict;
use warnings;
use Benchmark qw(timethese cmpthese);
#open my $fh, ">", "/tmp/test.out" or die $!;
#open my $fh, ">", "/dev/null" or die $!;
my $fh = *STDOUT;
my $hash = {
foo => "something and stuff",
bar => "and some other stuff"
};
select *STDERR;
my $r = timethese(shift || -3, {
list => sub {
print $fh $hash->{foo}, "|", $hash->{bar};
},
concat => sub {
print $fh $hash->{foo}. "|". $hash->{bar};
},
});
cmpthese($r);
我正在执行数万个。如果你执行了很多,可能会更快。也许你想更强烈地指出差异;我看了三遍才发现选项A使用逗号,选项B使用句点。是的,我的眼睛已经老了,但还是…为什么不试试每一双,看看结果呢?有些阴谋集团对你隐瞒的并不是什么神秘的知识。看看我的各种基准测试讲座,也许还有掌握Perl中的基准测试章节,看看为什么这些数字毫无意义。好吧,我来咬一口。这些会谈是什么?我在哪里可以访问这些会谈?:)[我确实拥有一份M.P.的副本,并将重读这一章。]我不认为基准测试是圣杯,但ceterus parabus,它们可能会有一些用处,而且统计数据并不总是撒谎:)@DVK:我不知道我所有的演讲都在哪里。当我需要它们的时候,我就用谷歌搜索它们。说真的,我用谷歌搜索我自己的东西。你的评论应该是第八条规则。“8.如果你思考优化所花费的时间超过了你可能获得的收益,那么优化就结束了。”@jsoverson在非常罕见的情况下,这并不是一个简单的问题
$ perl5.8.8 ~/tmp/bench.plx 5000000 > /dev/null
Benchmark: timing 5000000 iterations of concat, list...
concat: 3 wallclock secs ( 3.69 usr + 0.04 sys = 3.73 CPU) @ 1340482.57/s (n=5000000)
list: 5 wallclock secs ( 3.97 usr + 0.06 sys = 4.03 CPU) @ 1240694.79/s (n=5000000)
Rate list concat
list 1240695/s -- -7%
concat 1340483/s 8% --
#!/usr/bin/perl -w
use strict;
use warnings;
use Benchmark qw(timethese cmpthese);
#open my $fh, ">", "/tmp/test.out" or die $!;
#open my $fh, ">", "/dev/null" or die $!;
my $fh = *STDOUT;
my $hash = {
foo => "something and stuff",
bar => "and some other stuff"
};
select *STDERR;
my $r = timethese(shift || -3, {
list => sub {
print $fh $hash->{foo}, "|", $hash->{bar};
},
concat => sub {
print $fh $hash->{foo}. "|". $hash->{bar};
},
});
cmpthese($r);