He estado trabajando en varios scripts de Perl que procesan grandes archivos de datos de ancho fijo, extrayendo pequeñas subcadenas de cada registro de datos. Había imaginado que delegar la extracción de subcadenas en llamadas a métodos sería costoso debido a la sobrecarga de copiar el registro de datos en la matriz @_. Entonces ejecuté lo siguiente para comparar (a) la llamada directa a substr(), (b) la llamada al método que pasa el registro de datos como una cadena, y (c) la llamada al método que pasa el registro de datos por referencia.¿Tiene un golpe de rendimiento de copia de datos al pasar argumentos a las subrutinas de Perl?
use strict;
use warnings;
use Benchmark qw(timethese);
my $RECORD = '0' x 50000;
my $direct = sub { my $v = substr($RECORD, $_, 1) for 0..999 };
my $byVal = sub { my $v = ByVal ($RECORD, $_) for 0..999 };
my $byRef = sub { my $v = ByRef (\$RECORD, $_) for 0..999 };
sub ByVal { return substr( $_[0], $_[1], 1) }
sub ByRef { return substr(${$_[0]}, $_[1], 1) }
timethese(10000, {
direct => $direct,
byVal => $byVal,
byRef => $byRef,
});
my $byVal2loc = sub { my $v = ByVal2loc($RECORD, $_) for 0..999 };
my $byRef2loc = sub { my $v = ByRef2loc(\$RECORD, $_) for 0..999 };
sub ByVal2loc { my $arg = shift; return substr( $arg, $_[0], 1) }
sub ByRef2loc { my $arg = shift; return substr($$arg, $_[0], 1) }
timethese($ARGV[0], {
byVal2loc => $byVal2loc,
byRef2loc => $byRef2loc,
});
# Produces this output:
Benchmark: timing 10000 iterations of byRef, byVal, direct...
byRef: 19 wallclock secs...
byVal: 15 wallclock secs...
direct: 4 wallclock secs...
Benchmark: timing 10000 iterations of byRef2loc, byVal2loc...
byRef2loc: 21 wallclock secs...
byVal2loc: 119 wallclock secs...
Como era de esperar, el método directo fue el más rápido. Sin embargo, me sorprendió no encontrar ninguna penalización relacionada con la "copia de datos" que había estado imaginando. Incluso cuando aumenté el ancho del registro a proporciones estrafalarias (por ejemplo, mil millones de caracteres), los puntos de referencia de los valores por referencia y por referencia fueron básicamente los mismos.
Parece que al pasar argumentos a los métodos, Perl no copia los datos. Supongo que esto tiene sentido al reflexionar sobre el poder de alias de @_. Los argumentos se pasan por referencia, no por valor.
Sin embargo, es una forma limitada de paso de referencia por referencia, porque las referencias en @_ no se pueden asignar directamente a una variable local dentro de la subrutina. Tales asignaciones resultan en la copia de datos, como se ilustra en el segundo conjunto de puntos de referencia.
¿Lo entiendo bien?
1. Esta es la respuesta correcta. –
@Igor Krivokon: Correcto, sí, pero ya mencionado en la pregunta, al menos implícitamente. Supongo que "Sí, estás entendiendo esto correctamente"."le falta algo como respuesta. – ysth