Is passing by reference preferrable?

M

Markus Dehmann

Is it preferrable to pass variables by reference, or does the perl
interpreter optimize things so that it's not necessary?

In other words, is the 2nd variant of the following two much more efficient?

$a = "bla";
$a = modify($a);
print $a;
sub modify { my $b = shift; $b =~ s/l/L/; return $b; }

$a = "bla";
modify(\$a);
print $a;
sub modify { my $bRef = shift; $$bRef =~ s/l/L/; }


Thanks!
Markus
 
B

Bob Walton

Markus said:
Is it preferrable to pass variables by reference, or does the perl
interpreter optimize things so that it's not necessary?

Preferable? Preferable for what? Clarity? Speed? Obfuscation?

If you want to know about speed,

use Benchmark;

and find out. It might be different on your platform and Perl
version than on others.

Both schemes have their uses, advantages and disadvantages.
Arrays and hashes are generally best passed by reference if there
is more than one argument to the sub, or if the array or hash is
large. You can read up on it in:

perldoc perlsub
....
 
X

xhoster

Markus Dehmann said:
Is it preferrable to pass variables by reference, or does the perl
interpreter optimize things so that it's not necessary?

Whether it is preferrable rarely has anything to do with how the
interpreter optimizes things. Preferred code is usually determined more by
things like correctness, intuitiveness, maintainibility, etc.

Micro-optimiztion of your code is extremely context and detail dependent,
so it is hard to make general statements.
In other words, is the 2nd variant of the following two much more
efficient?

$a = "bla";
$a = modify($a);
print $a;
sub modify { my $b = shift; $b =~ s/l/L/; return $b; }

$a = "bla";
modify(\$a);
print $a;
sub modify { my $bRef = shift; $$bRef =~ s/l/L/; }

time perl -le 'foreach(1..1e7) {$a = "bla";$a = modify($a)}; \
sub modify { my $b = shift; $b =~ s/l/L/; return $b; }'
22.640u 0.000s 0:23.24 97.4% 0+0k 0+0io 351pf+0w

time perl -le 'foreach(1..1e7) {$a = "bla";modify(\$a)}; \
sub modify { my $bRef = shift; $$bRef =~ s/l/L/; }'
16.430u 0.000s 0:17.26 95.1% 0+0k 0+0io 352pf+0w

I'd say it is slightly more efficient, not much more efficient. (Of
course, if $a was much larger, this difference could become greater. But
then again, if $a was much larger, just creating $a in the first place
would probably swamp your call involving $a.)

BTW, did you know that perl automatically passes scalars by alias (which
is kind of, but not exactly, like passing by reference) and that if you
wish to avoid copying the way to do it is by not copying elements of @_ in
the first place? (both you're "my $b = shift" and "my $bRef = shift" are
examples of such copying.)

time perl -le 'foreach(1..1e7) {$a = "bla";modify($a)}; \
sub modify { $_[0] =~ s/l/L/; }'
11.520u 0.010s 0:11.60 99.3% 0+0k 0+0io 349pf+0w

But again, micro-optimization of obviously toy code is rarely of much
value.

Xho
 
T

Tad McClellan

Markus Dehmann said:
In other words, is the 2nd variant of the following two much more efficient?


perldoc Benchmark

$a = "bla";
$a = modify($a);
print $a;
sub modify { my $b = shift; $b =~ s/l/L/; return $b; }

$a = "bla";
modify(\$a);
print $a;
sub modify { my $bRef = shift; $$bRef =~ s/l/L/; }


There is also a 3rd alternative to consider:

$a = "bla";
modify($a);
print $a;
sub modify { $_[0] =~ s/l/L/; }
 
M

Markus Dehmann

Markus Dehmann said:
Is it preferrable to pass variables by reference, or does the perl
interpreter optimize things so that it's not necessary?


Whether it is preferrable rarely has anything to do with how the
interpreter optimizes things. Preferred code is usually determined more by
things like correctness, intuitiveness, maintainibility, etc.

Micro-optimiztion of your code is extremely context and detail dependent,
so it is hard to make general statements.

In other words, is the 2nd variant of the following two much more
efficient?

$a = "bla";
$a = modify($a);
print $a;
sub modify { my $b = shift; $b =~ s/l/L/; return $b; }

$a = "bla";
modify(\$a);
print $a;
sub modify { my $bRef = shift; $$bRef =~ s/l/L/; }


time perl -le 'foreach(1..1e7) {$a = "bla";$a = modify($a)}; \
sub modify { my $b = shift; $b =~ s/l/L/; return $b; }'
22.640u 0.000s 0:23.24 97.4% 0+0k 0+0io 351pf+0w

time perl -le 'foreach(1..1e7) {$a = "bla";modify(\$a)}; \
sub modify { my $bRef = shift; $$bRef =~ s/l/L/; }'
16.430u 0.000s 0:17.26 95.1% 0+0k 0+0io 352pf+0w

I'd say it is slightly more efficient, not much more efficient. (Of
course, if $a was much larger, this difference could become greater. But
then again, if $a was much larger, just creating $a in the first place
would probably swamp your call involving $a.)

BTW, did you know that perl automatically passes scalars by alias (which
is kind of, but not exactly, like passing by reference) and that if you
wish to avoid copying the way to do it is by not copying elements of @_ in
the first place? (both you're "my $b = shift" and "my $bRef = shift" are
examples of such copying.)

time perl -le 'foreach(1..1e7) {$a = "bla";modify($a)}; \
sub modify { $_[0] =~ s/l/L/; }'
11.520u 0.010s 0:11.60 99.3% 0+0k 0+0io 349pf+0w

It's interesting that if you don't copy and just use $_[0], as you
suggest, then passing by reference is not an advantage anymore. It even
seems passing by reference is slower than passing by value now:

time perl -le 'foreach(1..1e7) {$a = "bla";modify($a)}; \
sub modify {$_[0] =~ s/l/L/; }'
10.494u 0.018s 0:10.54 99.6% 0+0k 0+0io 27pf+0w
time perl -le 'foreach(1..1e7) {$a = "bla";modify(\$a)}; \
sub modify { ${$_[0]} =~ s/l/L/; }'
12.976u 0.014s 0:13.05 99.4% 0+0k 0+0io 0pf+0w

But then, time is rather unreliable of course, and the Benchmark module
should be used here...

Markus
 
X

xhoster

Markus Dehmann said:
(e-mail address removed) wrote:

time perl -le 'foreach(1..1e7) {$a = "bla";modify($a)}; \
sub modify {$_[0] =~ s/l/L/; }'
10.494u 0.018s 0:10.54 99.6% 0+0k 0+0io 27pf+0w
time perl -le 'foreach(1..1e7) {$a = "bla";modify(\$a)}; \
sub modify { ${$_[0]} =~ s/l/L/; }'
12.976u 0.014s 0:13.05 99.4% 0+0k 0+0io 0pf+0w

But then, time is rather unreliable of course, and the Benchmark module
should be used here...


How so? I find "time" to be at least as reliable as Benchmark.

Xho
 
E

Eric J. Roode

Is it preferrable to pass variables by reference, or does the perl
interpreter optimize things so that it's not necessary?

In other words, is the 2nd variant of the following two much more
efficient?

$a = "bla";
$a = modify($a);
print $a;
sub modify { my $b = shift; $b =~ s/l/L/; return $b; }

$a = "bla";
modify(\$a);
print $a;
sub modify { my $bRef = shift; $$bRef =~ s/l/L/; }

In perl, *everything* is passed by reference.

$a = 'bla';
modify ($a);
print $a;
sub modify { $_[0] =~ s/l/L/ }

--
Eric
`$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,@%)=(
$!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++;
$_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);$,++
;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=`
 
B

brian d foy

Markus Dehmann said:
But then, time is rather unreliable of course, and the Benchmark module
should be used here...

Actually, time(1) tends to be more reliable. A lot of numbers that
come out of Benchmark don't add up (literally) because there is
about a 7% error from the null-loop handling. The precision of
Benchmark.pm tends to be pretty low.
 
I

Ingo Menger

Markus said:
(e-mail address removed) wrote:
It's interesting that if you don't copy and just use $_[0], as you
suggest, then passing by reference is not an advantage anymore. It even
seems passing by reference is slower than passing by value now:

At the contrary, it would be "interesting" if this were not so.

As xhoster explained, the value is passed by (kind a) reference anyway,
so taking an extra reference and dereferencing it in the subroutine
requires so much extra CPU cycles.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,176
Messages
2,570,947
Members
47,501
Latest member
Ledmyplace

Latest Threads

Top