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'
因此,除非我使用substr()的这个特殊功能,否则最好使用substr?
我一直在咆哮吗?
答案 0 :(得分:16)
您可以使用Readonly::XS
在变量上设置SvREADONLY
标记,但这不会提高效率。效率来自于选择正确的算法,而不是通过编译器提示。如果您希望代码更快/使用更少的内存,请对其进行分析(请参阅Devel::NYTProf
)。当您发现瓶颈时,要么在其中使用不同的算法,要么切换为使用XS
。
另外,如果你打算尝试优化某些东西,请确保结果真的更快,这里是substr vs unpack:
Rate unpack substr
unpack 2055647/s -- -74%
substr 7989875/s 289% --
以下是基准代码。
#!/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;
答案 1 :(得分:7)
使用好的算法,除非有必要,否则不进行优化。如果是,请分析您的代码并对您的更改进行基准测试。现在是根据需要考虑XS或Inline :: C的好时机。
use constant Foo => 'bar';
由perl编译器创建a minimal subroutine that can be inlined。您还可以创建自己的可内联常量函数
典型的perl习语会进行一些“额外”复制:
sub foo {
my $bar = shift;
..do stuff with $bar...
}
许多人没有意识到Perl通过引用将参数传递给子例程。 @_
包含别名到子例程的参数。
因此,您可以通过直接使用@_
来避免复制您的参数:
foo( $big_scalar );
sub foo {
..do stuff with $_[0]...
.. sneakily risk modifying $big_scalar ..
}
当然,这是有风险的,因为如果修改该值,您将修改调用值。仅在需要保存BIG文件副本时使用此选项。 (或者你明确想要修改一个调用参数。)
如果我需要移动一大块数据,但我不打算修改它,我通常会明确地通过引用传递它,而不是弄乱@_
;
foo( \$big_scalar );
sub foo {
my $bar = shift;
... do stuff with $$bar ...
... can modify $big_scalar, but the pass by ref is explicit ...
}
至少这就是唐纳德克努特所说的那句名言。这句话有很多智慧。
不正确的优化(声称是优化的代码,但不是)也非常糟糕。
首先要明确代码。 请务必对代码进行分析以找出瓶颈。 请务必对优化进行基准测试,以确保它们正常工作。 记录您的优化代码,保留一些基准代码 - 明天的编译器可能不会像今天那样响应。
答案 2 :(得分:3)
我正在使用Chas,首先对您的代码进行基准测试和分析。我真的怀疑字符串复制是你的瓶颈,你会浪费很多时间来获得微薄的收益。即使字符串复制似乎确实是瓶颈,首先在代码中查找有缺陷的算法。 Perl优于C和Java的潜在性能提升之一是因为它编写代码的速度非常快,因此可以为您提供足够的额外时间来分析和优化并改进算法。
如果字符串复制确实是您的瓶颈,请考虑简单地将大字符串作为引用传递。 C中字符串指针的道德等价物。这将阻止复制。请记住在使用它们之前取消引用它们。
sub foo {
my $ref = shift;
print $$ref;
}
$string = "Some string";
foo(\$string);
答案 3 :(得分:0)
我记得读过一些文章(如果你可以发表评论请注释),你可以提示perl你不会修改某些变量,因此它会删除额外的行李,否则你需要修改它等等? / p>
假设你在谈论'use constant ......',我是否正确?