Perl性能:为什么聪明的技巧表现更差?

pac*_*tie 0 perl

我找到了一个聪明的技巧来为字符串预分配内存,但是下面的代码片段比没有技巧的情况下表现更差(通过用语句注释掉语句)vec($str, 0x100000, 8)=0;.

use Time::HiRes qw( gettimeofday );
my $big = "a" x 100;
my $str = "";
vec($str, 0x100000, 8)=0;
$ts = getTS();
for ($i=0; $i < 1000000; $i ++) {
    $str = "";
    for ($j=0; $j<100; $j++) {
        $str .= $big;
    }
}

printf "took %f secs\n", getTS() - $ts;

sub getTS {
    my ($seconds, $microseconds) = gettimeofday;
    return $seconds + (0.0+ $microseconds)/1000000.0;
}
Run Code Online (Sandbox Code Playgroud)

凭借巧妙的技巧,它需要9.1秒.如果没有巧妙的技巧,它需要7.8秒.

聪明的技巧应该更快,因为它不需要这么多realloc().知道为什么吗?

Bor*_*din 5

我建议你应该避免聪明的伎俩.Perl对字符串内存的处理在十年内得到了极大的改进:它现在按比例将每个字符串预先扩展到其原始大小,并保留在程序重复相同行为时分配的任何内存

通过使用词法变量并避免使用C风格的for循环,您可以从算法中再挤出10%的性能

此外,Time::HiRes已经提供tv_interval了计算两次调用之间的差异gettimeofday

use strict;
use warnings 'all';

use Time::HiRes qw/ gettimeofday tv_interval /;

my $big = 'a' x 100;

my $start = [ gettimeofday ];

for my $i (1 .. 1_000_000 ) {

    my $str;

    for my $j ( 1 .. 100 ) {
        $str .= $big;
    }
}

my $end = [ gettimeofday ];

printf "took %.3f secs\n", tv_interval( $start, $end );
Run Code Online (Sandbox Code Playgroud)

产量

took 8.324 secs
Run Code Online (Sandbox Code Playgroud)


顺便提一下,在 ARM处理器上运行Android 7.1.2的Pixel C 平板电脑上运行的相同程序返回21.683秒.我觉得这很不错.