Non ci dovrebbe essere alcuna differenza in termini di prestazioni runtime se il codice risultante è lo stesso in entrambi i casi. Questo di solito non è possibile, tuttavia, a meno che non si usi la stringa eval
per creare le subroutine. Per esempio, il codice è fornito:
... = sub { $_[0]->{$a} };
sarà sempre così leggermente più lento del codice che avrebbe scritto a mano:
sub foo { $_[0]->{'foo'} }
semplicemente perché il primo ha per ottenere il valore della variabile $ a prima di usarla come chiave dell'hash, mentre la successiva usa una costante come chiave hash. Inoltre, a parte, shift
di solito tende ad essere più veloce di $_[0]
.Ecco po 'di codice di riferimento:
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 },
});
ed i risultati sul mio sistema:
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% --
Sono così vicino che le differenze possono perdersi nel rumore, ma tra le tante prove penso che vedrete che la variante "shift manuale" è la più veloce. Ma come con tutti i microbenchmarks come questo, devi verificare il tuo scenario esatto sul tuo hardware e la tua versione di perl per essere sicuro di tutto.
E qui è eval stringa gettata nel mix.
eval "sub eval_index { \$_[0]->{'$attr'} }";
eval "sub eval_shift { shift->{'$attr'} }";
Dovrebbe essere esattamente uguali alle varianti "manuale", più o meno il rumore statistico. I miei risultati:
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% --
Anche in questo caso, questi sono tutti così vicini che avresti dovuto prendere grandi dolori ed eseguire molte prove per risolvere il segnale dal rumore. Ma la differenza tra l'utilizzo di una costante come chiave hash e l'uso di una variabile (il cui valore deve essere prima richiamato) come una chiave di hash dovrebbe essere visibile. (L'ottimizzazione shift
è un problema separato ed è più probabile che cambi in un modo o nell'altro nelle versioni precedenti o future di perl.)
'* {" get_ $ a "} = sub' ... dovrebbe funzionare anche. (Non c'è bisogno di avere '__PACKAGE__' lì dentro) –