Perl: очевидное-невероятное
Mar. 22nd, 2006 05:21 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Оказывается, код, содержащий меньшее количество my-переменных, может выполняться в разы дольше, чем код с большим их количеством.
Пример под катом:
Первый код работает 22 cекунды против 6 секунд второго кода, то есть, почти в 4 раза больше.
>time perl fields_hashes.pl
0.01user 0.00system 0:21.48elapsed 0%CPU (0avgtext+0avgdata 8576maxresident)k
0inputs+0outputs (541major+0minor)pagefaults 0swaps
>time perl fields_hashes.pl
0.01user 0.01system 0:05.54elapsed 0%CPU (0avgtext+0avgdata 8576maxresident)k
0inputs+0outputs (541major+0minor)pagefaults 0swaps
Кстати, варианты с
Такая вот арифметика - видимо, связанная с особенностями размещения памяти и логикой построения внутренних структур.
Update: Сделал ещё варианты с использованием blessed массивов и скаляров в качестве классов, получились предсказуемые результаты. С массивами быстрее, чем с хэшами (4.79с.). И медленнее, чем со скалярами (3.62с., даже при том, что я ввёл в конструкторе my-переменную ind, которую и bless`ил).
Что ещё интересно, с тривиальным эмулятором обращений к классам вида (пример для blessed скаляров):
, "массивный" вариант увеличивает время выполнения всего на 0.86с., что ненамного меньше "хэшовых" 1.2с (вариант с присваиванием через
Мораль: разница микроскопическая, но есть, а пользоваться надо любым удобным способом без попыток излишних оптимизаций, как завещает нам великий Wall.
Пример под катом:
- Первый код
#!/usr/bin/perl
use strict;
package Aa;
sub new {
my $class = shift;
return bless { @_ }, $class;
}
package main;
my @aaa = map( Aa->new( ind => $_ ), ( 1 .. 1000000 ) ); - Второй код
#!/usr/bin/perl
use strict;
package Aa;
sub new {
my $class = shift;
my $self = bless { @_ }, $class;
return $self;
}
package main;
my @aaa = map( Aa->new( ind => $_ ), ( 1 .. 1000000 ) );
Первый код работает 22 cекунды против 6 секунд второго кода, то есть, почти в 4 раза больше.
>time perl fields_hashes.pl
0.01user 0.00system 0:21.48elapsed 0%CPU (0avgtext+0avgdata 8576maxresident)k
0inputs+0outputs (541major+0minor)pagefaults 0swaps
>time perl fields_hashes.pl
0.01user 0.01system 0:05.54elapsed 0%CPU (0avgtext+0avgdata 8576maxresident)k
0inputs+0outputs (541major+0minor)pagefaults 0swaps
Кстати, варианты с
use fields qw(ind);
работают: - 8.78c. с конструктором вида:
my $class = shift;
my $self = fields::new( $class );
$self->{ ind } = $_[1];
return $self; - 12.25c. с конструктором вида:
my $class = shift;
my $self = fields::new( $class );
for( my $i = 0; $i < $#_; $i += 2 ) {
$self->{ $_[ $i ] } = $_[ $i+1 ];
}
return $self; - 14.51c. с конструктором вида:
my $class = shift;
my $self = fields::new( $class );
%$self = ( %$self, @_ );
return $self; - 15.62c. с конструктором вида:
my $class = shift;
my $self = fields::new( $class );
while ( my ( $key, $val ) = splice( @_, 0, 2) ) {
$self->{ $key } = $val;
}
return $self; - и 16.32c. с конструктором вида:
my $class = shift;
my $self = fields::new( $class );
my $ary = { @_ };
map( $self->{ $_ } = $ary->{ $_ }, keys %$ary );
return $self;
Такая вот арифметика - видимо, связанная с особенностями размещения памяти и логикой построения внутренних структур.
Update: Сделал ещё варианты с использованием blessed массивов и скаляров в качестве классов, получились предсказуемые результаты. С массивами быстрее, чем с хэшами (4.79с.). И медленнее, чем со скалярами (3.62с., даже при том, что я ввёл в конструкторе my-переменную ind, которую и bless`ил).
Что ещё интересно, с тривиальным эмулятором обращений к классам вида (пример для blessed скаляров):
my $sum = 0;
$$_++ for ( @aaa );
$sum += $$_ for ( @aaa );
print "$sum\n";
, "массивный" вариант увеличивает время выполнения всего на 0.86с., что ненамного меньше "хэшовых" 1.2с (вариант с присваиванием через
$self->{ ind } = $_[1];
), и также ненамного больше скалярных 0.55с. (как в приведённом выше примере обращений).Мораль: разница микроскопическая, но есть, а пользоваться надо любым удобным способом без попыток излишних оптимизаций, как завещает нам великий Wall.