в окне сценария кофе-скрипта Windows = = 1.9.0 не работает должным образом. просто добавьте Gemfile
gem 'coffee-script-source', '1.8.0'
и запустите
bundle update coffee-script-source
Альтернативное предложение, с которым будет намного легче справиться: вставьте строки в массив и присоедините к нему, когда вы закончите.
Да, увеличение строки в Perl приведет к повторным перераспределениям. Perl выделяет немного дополнительного пространства для строк, но только несколько байтов. Вы можете увидеть это, используя Devel :: Peek. Это перераспределение очень быстрое и часто фактически не копирует память. Доверьтесь своему диспетчеру памяти, поэтому вы программируете на Perl, а не на C. Сначала сравните его!
Вы можете предварительно выделить массивы с помощью $ # array = $ num_entries
и хешем с ключами% hash = $ num_keys
, но длина $ string = $ strlen
не работает. Вот умный трюк , который я выкопал на Perlmonks .
my $str = "";
vec($str, $length, 8)=0;
$str = "";
Или, если вы хотите попасть в XS, вы можете вызвать SvGROW ()
.
chaos ' Предложение использовать массив, а затем объединить все это будет использовать более чем вдвое больше памяти. Память для массива. Память для каждого скаляра выделяется для каждого элемента в массиве. Память для строки хранится в каждом скалярном элементе. Память на копию при присоединении. Если это приводит к более простому коду, делайте это, но не думайте, что вы экономите память.
Строки в Perl являются изменяемыми, поэтому добавление в строку НЕ приводит к штрафу за дублирование строки.
Вы можете попробовать все, что хотите, чтобы найти «более быстрый» способ, но это пахнет преждевременной оптимизацией.
Например, я собрал класс, который отвлекал тяжелую работу. Он работает отлично, но, несмотря на все свои глупые трюки, очень медленно.
Вот результат:
Rate magic normal
magic 1.72/s -- -93%
normal 23.9/s 1289% --
Да, верно, 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() ));
Да, хорошо известно, что заранее растянутые строки будут расти.
Для этого можно использовать оператор «x». Например, чтобы предварительно выделить 1000 пробелов:
$ s = "" x 1000:
Я бы пошел по пути массива / соединения:
push(@array, $crunched_bit)
А затем $ str = join ('', @array)
, если не более, чтобы иметь доступ к все элементы для отладки позже.
Я не знаю конкретно, как реализованы строки Perl, но довольно неплохо предположить, что это постоянное амортизированное время . Это означает, что даже если вы найдете способ предварительно выделить ваши строковые шансы, то, что объединенное время, которое он сэкономит для всех пользователей скрипта, будет меньше, чем время, которое вы потратили, задавая этот вопрос на переполнение стека .