我有一个Perl脚本可以处理大量数据.由于重复使用点(连接)运算符,有许多字符串变量从小开始但变长很长.以这种方式增长字符串会导致重复重新分配吗?如果是,是否有预先分配字符串的方法?
Sch*_*ern 15
是的,Perl生成一个字符串将导致重复重新分配.Perl为字符串分配了一些额外的空间,但只有几个字节.你可以使用Devel :: Peek看到这个.这种重新分配非常快,通常不会实际复制内存.相信你的内存管理器,这就是你用Perl而不是C编程的原因.首先对它进行基准测试!
您可以使用$#array = $num_entries和使用散列预分配数组keys %hash = $num_keys但length $string = $strlen不起作用.这是我在Perlmonks上挖出的一个聪明的伎俩.
my $str = "";
vec($str, $length, 8)=0;
$str = "";
Run Code Online (Sandbox Code Playgroud)
或者如果你想进入XS,你可以打电话SvGROW().
混乱'建议使用一个数组,然后将它们连接在一起将使用超过两倍的内存.阵列的内存.为数组中的每个元素分配的每个标量的内存.每个标量元素中保存的字符串的内存.加入时的副本内存.如果它导致更简单的代码,那么做,但不要认为你节省了任何内存.
Perl的字符串是变的,因此追加到一个字符串确实不招致串的重复处罚.
您可以尝试所有想要找到"更快"的方式,但这对于过早优化非常糟糕.
举个例子,我掀起了一个抽象出艰苦工作的课程.它运作得很完美,但它的所有愚蠢技巧都非常慢.
这是结果:
Rate magic normal
magic 1.72/s -- -93%
normal 23.9/s 1289% --
Run Code Online (Sandbox Code Playgroud)
是的,没错,Perl比我认为的可敬实施快1200%.
描述您的代码并找出真正的问题,不要尝试优化甚至不是已知问题的东西.
#!/usr/bin/perl
use strict;
use warnings;
{
package MagicString;
use Moose;
has _buffer => (
isa => 'Str',
is => 'rw',
);
has _buffer_size => (
isa => 'Int',
is => 'rw',
default => 0,
);
has step_size => (
isa => 'Int',
is => 'rw',
default => 32768,
);
has _tail_pos => (
isa => 'Int',
is => 'rw',
default => 0,
);
sub BUILD {
my $self = shift;
$self->_buffer( chr(0) x $self->step_size );
}
sub value {
my $self = shift;
return substr( $self->{buffer}, 0, $self->{_tail_pos} );
}
sub append {
my $self = shift;
my $value = shift;
my $L = length($value);
if ( ( $self->{_tail_pos} + $L ) > $self->{_buffer_size } ){
$self->{buffer} .= (chr(0) x $self->{step_size} );
$self->{_buffer_size} += $self->{step_size};
}
substr( $self->{buffer}, $self->{_tail_pos}, $L, $value );
$self->{_tail_pos} += $L;
}
__PACKAGE__->meta->make_immutable;
}
use Benchmark qw( :all :hireswallclock );
cmpthese( -10 , {
magic => sub{
my $x = MagicString->new();
for ( 1 .. 200001 ){
$x->append( "hello");
}
my $y = $x->value();
},
normal =>sub{
my $x = '';
for ( 1 .. 200001 ){
$x .= 'hello';
}
my $y = $x;
}
});
#use Data::Dumper;
#print Dumper( length( $x->value() ));
Run Code Online (Sandbox Code Playgroud)