Reputation: 42139
Curious if anyone knows (or can easily test) the time it takes to reference and then dereference an array.
my @foo = (0..1500000); # (~1.5M nodes).
join('',@{\@foo}); # any noticeable time difference vs join('',@foo) ?
There's obviously no legitimate reason for this, but I've come across unreasonable code :)
Upvotes: 0
Views: 296
Reputation: 118148
A naive benchmark shows that there is no discernible difference among different methods of concatenating integers from 1 to 1,500,000 into a single string (except, there is a wrong way -- not shown below).
I do wonder why one would need to create such a string, but then I wonder a lot.
#!/usr/bin/env perl
use strict; use warnings;
use Benchmark qw( cmpthese );
my @nodes = (1 .. 1_500_000);
cmpthese -5, {
derefref_join => sub {
my $str = join('', @{ \@nodes });
},
plain_join => sub {
my $str = join('', @nodes);
},
interpolate => sub {
local $" = '';
my $str = "@nodes";
},
};
Output:
Rate interpolate derefref_join plain_join interpolate 4.76/s -- -3% -3% derefref_join 4.89/s 3% -- -1% plain_join 4.92/s 4% 1% --
C:\temp> perl -v This is perl 5, version 14, subversion 2 (v5.14.2) built for MSWin32-x86-multi-thread Binary build 1402 [295342] provided by ActiveState http://www.ActiveState.com Built Oct 7 2011 15:49:44 Intel Core2 Duo [email protected], 2GB ram.
Upvotes: 6
Reputation: 386331
Benchmarks of similar tests I've performed gave something on the order 10 nanoseconds per deref. There's only deref in the code you posted, so we're talking about a 0.000,000,010s difference.
Bah, the difference is so tiny, that I can't even reliably tell which one is faster!
Benchmark: running array, array_ref for at least 3 CPU seconds...
array: 3 wallclock secs ( 3.04 usr + 0.02 sys = 3.06 CPU) @ 11.12/s (n=34)
array_ref: 3 wallclock secs ( 3.13 usr + 0.00 sys = 3.13 CPU) @ 11.48/s (n=36)
Benchmark: running array, array_ref for at least 3 CPU seconds...
array: 3 wallclock secs ( 3.06 usr + 0.03 sys = 3.09 CPU) @ 11.33/s (n=35)
array_ref: 3 wallclock secs ( 3.12 usr + 0.05 sys = 3.17 CPU) @ 11.37/s (n=36)
Benchmark: running array, array_ref for at least 3 CPU seconds...
array: 3 wallclock secs ( 3.06 usr + 0.00 sys = 3.06 CPU) @ 11.45/s (n=35)
array_ref: 3 wallclock secs ( 3.18 usr + 0.00 sys = 3.18 CPU) @ 11.31/s (n=36)
Benchmark: running array, array_ref for at least 3 CPU seconds...
array: 3 wallclock secs ( 3.09 usr + 0.00 sys = 3.09 CPU) @ 11.66/s (n=36)
array_ref: 3 wallclock secs ( 3.17 usr + 0.00 sys = 3.17 CPU) @ 11.37/s (n=36)
array is faster 50% of the time, array ref is faster 50% of the time.
use strict;
use warnings;
use Benchmark qw( timethese );
my %tests = (
array_ref => 'my $x = join("", @$foo);',
array => 'my $x = join("", @foo);',
);
$_ = 'use strict; use warnings; our $foo; our @foo; ' . $_
for values(%tests);
our @foo = 1..1_500_000;
our $foo = \@foo;
timethese(-3, \%tests);
Here's a better test than the one you posted. The only you posted spent less than 1% of the time doing the thing you wanted to test.
But again, the different is so small, that it's not measurable. Sometimes array ref appears faster, sometimes the array appears faster.
Actual speed is actually 1000x larger than indicated.
Benchmark: running array, array_ref for at least 3 CPU seconds...
array: 3 wallclock secs ( 3.09 usr + 0.00 sys = 3.09 CPU) @ 1015.54/s (n=3136)
array_ref: 3 wallclock secs ( 3.24 usr + 0.00 sys = 3.24 CPU) @ 1040.99/s (n=3378)
Actual speed is actually 1000x larger than indicated.
Benchmark: running array, array_ref for at least 3 CPU seconds...
array: 3 wallclock secs ( 3.25 usr + 0.00 sys = 3.25 CPU) @ 1011.09/s (n=3281)
array_ref: 3 wallclock secs ( 3.07 usr + 0.00 sys = 3.07 CPU) @ 1022.13/s (n=3141)
Actual speed is actually 1000x larger than indicated.
Benchmark: running array, array_ref for at least 3 CPU seconds...
array: 3 wallclock secs ( 3.29 usr + 0.00 sys = 3.29 CPU) @ 1020.96/s (n=3361)
array_ref: 3 wallclock secs ( 3.20 usr + 0.00 sys = 3.20 CPU) @ 1016.26/s (n=3250)
Actual speed is actually 1000x larger than indicated.
Benchmark: running array, array_ref for at least 3 CPU seconds...
array: 3 wallclock secs ( 3.07 usr + 0.00 sys = 3.07 CPU) @ 1053.03/s (n=3237)
array_ref: 4 wallclock secs ( 3.23 usr + 0.00 sys = 3.23 CPU) @ 1006.50/s (n=3250)
Again, array is faster 50% of the time, array ref is faster 50% of the time.
use strict;
use warnings;
use Benchmark qw( timethese );
my %tests = (
array_ref => 'my $x = join("", @$foo);',
array => 'my $x = join("", @foo);',
);
$_ = 'use strict; use warnings; our $foo; our @foo; for (1..1000) { '.$_.' }'
for values(%tests);
our @foo = 1..15;
our $foo = \@foo;
print("Actual speed is actually 1000x larger than indicated.\n");
timethese(-3, \%tests);
Upvotes: 7
Reputation: 5865
It will differ per host machine due to processor speed, obviously.
A way to measure this would be to use the time
function to record the time. Then create and execute a loop of 10's of thousands of dereferencing operations (because measuring a single dereference will be so fast you won't be able to measure it.) Afterwards, record the time again. Subtract the times and divide by the number of times through the loop. Subtract from this the time it takes to go through the loop without the dereference. A little math, and you have it.
Upvotes: -1