【发布时间】:2009-06-15 21:50:32
【问题描述】:
我一直在研究几个处理大型固定宽度数据文件的 Perl 脚本,从每个数据记录中提取小的子字符串。我曾想象将提取子字符串的任务委托给方法调用会很昂贵,因为将数据记录复制到 @_ 数组会产生开销。因此,我运行以下内容来比较 (a) 直接调用 substr(),(b) 将数据记录作为字符串传递的方法调用,以及 (c) 通过引用传递数据记录的方法调用。
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...
不出所料,直接方法是最快的。然而,我惊讶地发现没有与我想象中的“数据复制”相关的惩罚。即使我将记录的宽度增加到异常的比例(例如,十亿个字符),按值和按引用基准基本相同。
似乎在向方法传递参数时,Perl 不会复制数据。我想这在进一步思考@_ 的混叠能力后是有道理的。参数通过引用而不是值传递。
但是,它是一种有限的按引用传递形式,因为@_ 中的引用不能直接分配给子例程中的局部变量。如第二组基准所示,此类分配确实会导致数据复制。
我理解正确吗?
【问题讨论】:
标签: perl