10

我一直在运行许多以这种方式分解长字符串的 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,或者应该怎么做?

4

7 回答 7

16

骆驼书,第 598 页

更喜欢 join("", . ..) 而不是一系列连接的字符串。多个连接可能会导致字符串来回复制多次。连接运算符避免了这种情况。

于 2010-06-23T18:46:14.627 回答
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);
 });
于 2010-06-23T21:06:27.867 回答
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;

结果(在我的带有 Perl 5.8.9 的 iMac 上):

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%           --
于 2010-06-23T23:56:37.967 回答
3

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

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

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

于 2010-06-23T20:12:44.420 回答
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 的回答所表明的那样,.它比常量串联的情况要快得多.=,我很想将其视为一项规则。

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

D'A

于 2010-06-24T04:01:49.507 回答
1

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

于 2010-06-23T18:41:31.643 回答
-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?"; 
于 2010-06-23T20:59:58.737 回答