我可以告诉Perl一些数据是不可变的,以加快速度吗?

Poo*_*zer 1 optimization perl

Perl非常适合编写我通常需要做的字符串/文件解析程序.与C/C++/JAVA相比,我真正喜欢的是编写快速脚本和一次性代码所花费的时间.但是,我想学习如何加快速度.

例如,我想学习如何给Perl提供提示,以便它可以做出更好的决策 - 尤其是与字符串相关的事情.在我看来,Perl会在您执行任何操作时复制一个字符串,无论您是否真的稍后修改了该副本.这是设计的(我可以用一些魔法把它转走吗?)或者我在咆哮?

我真的想把一些字符串当作(const char *).我确信我们总是不需要所有的东西都是std :: string并且涉及到所有的包袱(让我们假设std :: string类似于Perl字符串).我可以给Perl提示在某些字符串上执行此操作吗?

我记得读过一些文章(请注释,如果你可以放置它),你可以暗示Perl你不会修改某些变量,因此它会删除额外的行李,如果你要修改它等等.

我相信Perl变量有两个内部指针指向同一个Perl变量 - 一个可以存储一个数字,另一个可以存储一个字符串(字符数组).我是否总能告诉Perl在整个过程中选择一个?我可以让Perl处理一些字符串,(const char *)以便它们不会标记修改它们所需的功能吗?

例如,我读到某处(也许是同一篇文章?)unpack()比substr()更快,因为substr()返回一个左值,所以你也可以对它进行操作.例如,如果我想用'ef'替换字符串的前两个字符,我可以写:

substr(string, 0, 2) = 'ef'; # string now begins with 'ef'
Run Code Online (Sandbox Code Playgroud)

因此,除非我使用substr()的这个特殊功能,我最好使用substr?

我一直在咆哮吗?

Cha*_*ens 16

您可以SvREADONLY在变量上设置标志Readonly::XS,但这不会提高效率.效率来自于选择正确的算法,而不是通过编译器提示.如果您希望代码更快/使用更少的内存,那么对其进行分析(请参阅参考资料Devel::NYTProf).当你发现瓶颈时,要么使用不同的算法,要么切换使用XS.

此外,如果您要尝试优化某些内容,请确保结果确实更快,这里是substr vs unpack:

            Rate unpack substr
unpack 2055647/s     --   -74%
substr 7989875/s   289%     --
Run Code Online (Sandbox Code Playgroud)

这是基准代码.

#!/usr/bin/perl

use strict;
use warnings;

use Benchmark;

my %subs = (
    unpack => sub { return unpack "a3", "foobarbaz" },
    substr => sub { return substr "foobarbaz", 0, 3 }
);

for my $sub (keys %subs) {
    print "$sub => ", $subs{$sub}(), "\n";
}

Benchmark::cmpthese -1, \%subs;
Run Code Online (Sandbox Code Playgroud)


dao*_*oad 7

一般来说:

使用好的算法,除非有必要,否则不进行优化.如果是,请分析您的代码并对您的更改进行基准测试.这是根据需要考虑XS或Inline :: C的好时机.

a(const*)char equialent:

use constant Foo => 'bar';创建一个可由perl编译器内联的最小子例程.您还可以创建自己的可内联常量函数

避免额外复制:

典型的perl习语做了一些"额外"的复制:

sub foo {
    my $bar = shift;

    ..do stuff with $bar...
}
Run Code Online (Sandbox Code Playgroud)

许多人没有意识到Perl通过引用将参数传递给子例程.@_包含子例程参数的别名.

因此,您可以通过@_直接使用来避免复制您的参数:

foo( $big_scalar );

sub foo {
    ..do stuff with $_[0]...
    .. sneakily risk modifying $big_scalar ..
}
Run Code Online (Sandbox Code Playgroud)

当然,这是有风险的,因为如果修改该值,您将修改调用值.仅在需要保存BIG文件副本时使用此选项.(或者你明确想要修改一个调用参数.)

如果我需要移动一大块数据,但我不打算修改它,我通常会明确地通过引用传递它,而不是乱用@_;

foo( \$big_scalar );
sub foo {
    my $bar = shift;
    ... do stuff with $$bar ...
    ... can modify $big_scalar, but the pass by ref is explicit ...
}
Run Code Online (Sandbox Code Playgroud)

[P]重建优化是万恶之源

至少这就是Donald Knuth所说的那句话.在这个声明中有很多智慧.

不正确的优化(声称是优化但不是优化的代码)也非常糟糕.

代码为清晰起见.请务必对代码进行分析以找出瓶颈.请务必对优化进行基准测试,以确保它们正常工作.记录您的优化代码,保留一些基准代码 - 明天的编译器可能不会像今天那样响应.

  • 并且在你做它的时候写测试."优化"代码并让它开始表现不同,真的很糟糕. (2认同)