使用Perl字符串表现

时间:2010-06-23 18:38:56

标签: performance perl string concatenation string-concatenation

我一直在运行很多Perl代码,以这种方式打破长串:

my $string = "Hi, I am a very long and chatty string that just won't";
$string .= " quit.  I'm going to keep going, and going, and going,";
$string .= " kind of like the Energizer bunny.  What are you going to";
$string .= " do about it?";

从我的Java背景中,构建一个像这样的字符串将是一个禁忌的表现。 Perl也是如此吗?在我的搜索中,我已经读过在字符串数组上使用join是连接字符串的最快方法,但是当你想要分解字符串以便于阅读时呢?写作是否更好:

my $string = "Hi, I am a very long and chatty string that just won't" .
    " quit.  I'm going to keep going, and going, and going," .
    " kind of like the Energizer bunny.  What are you going to" .
    " do about it?";

或者我使用join,或者应该如何使用?

7 个答案:

答案 0 :(得分:15)

Camel book, p 598

  

首选加入(“”,...)到一系列   连接字符串。多   连接可能会导致字符串   多次来回复制。   连接运算符可以避免这种情况。

答案 1 :(得分:11)

要添加到此线程还有一件事尚未提及 - 如果可以,请避免加入/连接这些字符串。许多方法将字符串的列表作为参数,而不仅仅是一个字符串,因此您可以单独传递它们,例如:

print "this is",
    " perfectly legal",
    " because print will happily",
    " take a list and send all the",
    " strings to the output stream\n";

die "this is also",
    " perfectly acceptable";

use Log::Log4perl :easy; use Data::Dumper;
INFO("and this is just fine",
    " as well");

INFO(sub {
    local $Data::Dumper::Maxdepth = 1;
    "also note that many libraries will",
    " accept subrefs, in which you",
    " can perform operations which",
    " return a list of strings...",
    Dumper($obj);
 });

答案 2 :(得分:10)

我做了基准! :)

#!/usr/bin/perl

use warnings;
use strict;

use Benchmark qw(cmpthese timethese);

my $bench = timethese($ARGV[1], {

  multi_concat => sub {
    my $string = "Hi, I am a very long and chatty string that just won't";
    $string .= " quit.  I'm going to keep going, and going, and going,";
    $string .= " kind of like the Energizer bunny.  What are you going to";
    $string .= " do about it?";
  },

  one_concat => sub {
    my $string = "Hi, I am a very long and chatty string that just won't" .
    " quit.  I'm going to keep going, and going, and going," .
    " kind of like the Energizer bunny.  What are you going to" .
    " do about it?";
  },

  join => sub {
    my $string = join("", "Hi, I am a very long and chatty string that just won't",
    " quit.  I'm going to keep going, and going, and going,",
    " kind of like the Energizer bunny.  What are you going to",
    " do about it?"
    );
  },

} );

cmpthese $bench;

1;

结果(在我的iMac上使用Perl 5.8.9):

imac:Benchmarks seb$ ./strings.pl 1000
Benchmark: running join, multi_concat, one_concat for at least 3 CPU seconds...
      join:  2 wallclock secs ( 3.13 usr +  0.01 sys =  3.14 CPU) @ 3235869.43/s (n=10160630)
multi_concat:  3 wallclock secs ( 3.20 usr + -0.01 sys =  3.19 CPU) @ 3094491.85/s (n=9871429)
one_concat:  2 wallclock secs ( 3.43 usr +  0.01 sys =  3.44 CPU) @ 12602343.60/s (n=43352062)
                   Rate multi_concat         join   one_concat
multi_concat  3094492/s           --          -4%         -75%
join          3235869/s           5%           --         -74%
one_concat   12602344/s         307%         289%           --

答案 3 :(得分:3)

两个示例之间的主要性能差异在于,在第一个示例中,每次调用代码时都会发生连接,而在第二个示例中,常量字符串将由编译器折叠在一起。

因此,如果这些示例中的任何一个将在循环或多次调用的函数中,则第二个示例将更快。

这假设字符串在编译时是已知的。如果您在运行时构建字符串,如fatcat1111所述,join运算符将比重复连接更快。

答案 4 :(得分:2)

在我的基准测试中,join仅比重新分配的连接快一点,而且只在短字符串列表上。没有重新分配的连接速度明显快于任何一个。在较长的列表中,join的表现明显比连接重新分配更糟糕,可能是因为参数传递开始主导执行时间。

4 strings:
          Rate   .= join    .
.=   2538071/s   --  -4% -18%
join 2645503/s   4%   -- -15%
.    3105590/s  22%  17%   --
1_000 strings:
         Rate join   .=
join 152439/s   -- -40%
.=   253807/s  66%   --

因此,就你的问题而言,.比执行时间更快.=,尽管不够,但通常值得担心。可读性几乎总是比性能更重要,.=通常是更易读的形式。

这是一般情况;正如sebthebert's answer所示,.在常量连接的情况下比.=快得多,我很想将其视为一种规则。

(顺便说一句,基准测试基本上是显而易见的形式,我不想在这里重复代码。唯一令人惊讶的是从<DATA>创建初始字符串以便为常量折叠。)

D'A

答案 5 :(得分:1)

使用你更喜欢的任何一个;这些在perl中的表现完全相同。 Perl字符串与Java字符串不同,可以就地修改。

答案 6 :(得分:-1)

您不需要执行任何操作,您可以轻松地将整个字符串一次性分配给变量。

my $string = "Hi, I am a very long and  chatty string that just won't
 quit.   I'm going to keep going, and going,  and going,
 kind of like the Energizer  bunny.  What are you going to
 do  about it?";