Sihal has asked for the wisdom of the Perl Monks concerning the following question:
I tried the following thing: swap 2 vars this way:
($b,$a) = ($a,$b) ;
Other way:
my $tmp = $b ;
$b= $a ;
$b = $tmp ;
If doing this with 2 big vars ( my $a = "10"x10000 ; in a long loop ( 10000 iterations) I can see different results.
Case 2, while taking more memory, is kinda faster. In particular it uses up way less cpu time, while case 1 takes a lot of user time. Can somebody explain this ?
also, if I do my ($b,$a) = ($a,$b)
It is way faster... ????
Re: swapping vars, two ways, 2 results...
by pg (Canon) on Dec 18, 2002 at 22:47 UTC
|
my ($b, $a) = ($a, $b)
you are not swaping, you simply defined another set of variables. Try this, it will clearly show you what happend, and why it is way fast:
$a = 100;
$b = 200;
my ($a, $b) = ($b, $a);
print $a, "\n"; #200
print $b, "\n"; #100
print $main::a, "\n";#100
print $main::b, "\n";#200
Update:
When you do:
($b, $a) = ($a, $b)
You are not working against two scalars, in stead you are working against two arrays, and two scalars. Not that it is slow, I don't even think it take less memory as you thought. Although you are not using any temps, Perl is using. | [reply] [d/l] [select] |
|
well it does use less memory, but that may be due to the length of the vars...
Anyway, this was a kinda stupid post but I wanted to write it cause I saw in one of my team mates code that he would never swap perls way, but rather Cs way, using a temp var. I first thought why wrinting it Cs way when you can use a more compact form. But then I saw that in some case it was actually totally different both in terms of cpu usage and mem, hence the post.
| [reply] |
|
but why is it that much faster ?
| [reply] |
|
{
local @list;
$list[0]=$b;
$list[1]=$a;
$a=$list[0];
$b=$list[1];
undef @list;
}
Instead of allocating one temprary scalar and doing 3 assignments, it is allocating a temporary list, performing 4 assignments and deallocating the list.
Examine what is said, not who speaks. | [reply] [d/l] [select] |
Re: swapping vars, two ways, 2 results...
by jdporter (Paladin) on Dec 19, 2002 at 01:55 UTC
|
| [reply] [d/l] |
|
"perl's way" is better(?), faster, cheaper, shorter(just), and preferable in every way(opinion?).
c:\test>perl -MBenchmark=cmpthese
my ($a,$b)=('a'x1000,'b'x1000);
cmpthese( -10, {
PERL=> sub{ ($a, $b) = ($b, $a); },
C => sub{ my $t=$a, $a=$b, $b=$t; },
XOR => sub{ $a^=$b^=$a^=$b; },
} );
^Z
Benchmark: running C, PERL, XOR, each for at least 10 CPU seconds...
C: 10 wallclock secs (10.01 usr + 0.00 sys = 10.01 CPU) @ 19
+7752.07/s (n=1980487)
PERL: 10 wallclock secs (10.30 usr + 0.00 sys = 10.30 CPU) @ 12
+1439.73/s (n=1250222)
XOR: 10 wallclock secs (10.03 usr + -0.01 sys = 10.02 CPU) @ 33
+5113.02/s (n=3356492)
Rate PERL C XOR
PERL 121440/s -- -39% -64%
C 197752/s 63% -- -41%
XOR 335113/s 176% 69% --
c:\test>
If performance isn't a concern I use list assignment, if it is, I'd use the XOR method.
Examine what is said, not who speaks. | [reply] [d/l] |
|
| [reply] |
|
|
my ($a,$b)=("a","bb");
printf("/%s/ (%d bytes) /%s/ (%d bytes)\n",$a,length($a),$b,length($b)
+);
$a^=$b^=$a^=$b;
printf("/%s/ (%d bytes) /%s/ (%d bytes)\n",$a,length($a),$b,length($b)
+);'
This results in:
/a/ (1 bytes) /bb/ (2 bytes)
/bb/ (2 bytes) /a/ (2 bytes)
The unexpected "2 bytes" for /a/ occurs because the string is still 2 characters long, but the 2nd character is now null.
This can (and will) trip you up later, because $b ne "a", even though they print the same.
--
Mike | [reply] [d/l] [select] |
|
|
By the way, if the two vars are very differents sizes, Perl's way gets slower.
| [reply] |
|
|