Nie powinno być żadnej różnicy w wydajności wykonawczego jeśli otrzymany kod jest taki sam w obu przypadkach. Zwykle nie jest to możliwe, chyba że używasz ciągu eval
do tworzenia podprogramów. Na przykład kod, który podałeś:
... = sub { $_[0]->{$a} };
będzie zawsze tak nieco wolniej niż kod byś napisany ręcznie:
sub foo { $_[0]->{'foo'} }
po prostu dlatego, że pierwszy ma dostać wartość Instrumentu zmienna $ a przed użyciem jej jako klucza do mieszania, podczas gdy późniejsza używa stałej jako swojego klucza mieszającego. Ponadto, na marginesie, shift
zwykle jest szybszy niż $_[0]
.Oto niektóre kodu odniesienia:
use Benchmark qw(cmpthese);
package Foo;
sub manual_shift { shift->{'foo'} }
sub manual_index { $_[0]->{'foo'} }
my $attr = 'foo';
*dynamic_shift = sub { shift->{$attr} };
*dynamic_index = sub { $_[0]->{$attr} };
package main;
my $o = bless { foo => 123 }, 'Foo';
cmpthese(-2, {
manual_shift => sub { my $a = $o->manual_shift },
manual_index => sub { my $a = $o->manual_index },
dynamic_shift => sub { my $a = $o->dynamic_shift },
dynamic_index => sub { my $a = $o->dynamic_index },
});
a wyniki na moim systemie:
Rate dynamic_index manual_index dynamic_shift manual_shift
dynamic_index 1799024/s -- -3% -4% -7%
manual_index 1853616/s 3% -- -1% -4%
dynamic_shift 1873183/s 4% 1% -- -3%
manual_shift 1937019/s 8% 4% 3% --
Są tak blisko, że różnice mogą zgubić się w hałas, ale na wielu próbach myślę zobaczysz że wariant "ręcznej zmiany" jest najszybszy. Ale tak jak w przypadku wszystkich mikroprocesorów takich jak ten, musisz przetestować swój dokładny scenariusz na swoim sprzęcie i swojej wersji perla, aby mieć pewność czegokolwiek.
I tutaj ciąg eval wrzucony do miksu.
eval "sub eval_index { \$_[0]->{'$attr'} }";
eval "sub eval_shift { shift->{'$attr'} }";
Powinny być dokładnie takie same, jak warianty "ręczne", plus lub minus szum statystyczny. Moje wyniki:
Rate dynamic_index manual_index dynamic_shift manual_shift eval_shift eval_index
dynamic_index 1820444/s -- -1% -2% -3% -4% -5%
manual_index 1835005/s 1% -- -1% -2% -3% -4%
dynamic_shift 1858131/s 2% 1% -- -1% -2% -3%
manual_shift 1876708/s 3% 2% 1% -- -1% -2%
eval_shift 1894132/s 4% 3% 2% 1% -- -1%
eval_index 1914060/s 5% 4% 3% 2% 1% --
Znowu te są tak blisko, że trzeba by podjąć wiele trudu i wykonywać wiele prób, aby uporządkować sygnału od szumu. Ale różnica między używaniem stałej jako klucza haszującego i używaniem zmiennej (której wartość musi najpierw zostać pobrana) jako klucz hash, powinna być widoczna. (Optymalizacja shift
jest osobnym problemem i jest bardziej prawdopodobne, że zmieni się tak czy inaczej w poprzednich lub przyszłych wersjach języka Perla.)
'* {" get_ $ a "} = sub' ... powinno również działać. (Nie trzeba mieć "__PACKAGE__" tam) –