printing lists versus concat strings? a little nibble of a benchmark
September 2, 2011 7 Comments
Please check out the comments to see more information about this topic.
Going to put this out there because I saw some code the other day that printed comma separated strings and scalars, and it got me curious about how expensive it was to print a list of items, rather than concatenating them into a string and passing that to print.
I’ll let the code speak for itself:
my $x = 'test';
my $r = timethese(
10000000,
{
'commaprint' => sub { print STDERR 'test', 'test', 'test', 'test', 'test', 'test'; },
'varcommaprint' => sub { print STDERR $x, $x, $x, $x, $x, $x; },
'interpprint' => sub { print STDERR "$x $x $x $x $x $x"; },
'concatprint' => sub { print STDERR 'test' . 'test' . 'test' . 'test' . 'test' . 'test'; },
'singleprint' => sub { print STDERR 'test'; },
} );
And the result on my laptop:
commaprint: 33 wallclock secs (12.46 usr + 19.77 sys = 32.23 CPU) @ 310269.93/s (n=10000000) varcommaprint: 32 wallclock secs (12.76 usr + 19.74 sys = 32.50 CPU) @ 307692.31/s (n=10000000) interpprint: 10 wallclock secs ( 7.44 usr + 3.68 sys = 11.12 CPU) @ 899280.58/s (n=10000000) concatprint: 6 wallclock secs ( 3.02 usr + 3.58 sys = 6.60 CPU) @ 1515151.52/s (n=10000000) singleprint: 6 wallclock secs ( 2.97 usr + 3.52 sys = 6.49 CPU) @ 1540832.05/s (n=10000000)
I’m not completely surprised by the result, but I would’t want to speculate about what’s going on under the covers without spending time studying the perl code. For now this will just have to leave this out there as something to consider in the future.
Your concatprint test is not fair. The concatenation occurs only once because Perl folds constants:
perl -MO=Deparse -e '$a = "a" . "b"; $b = 5 + 10;'
a better benchmark is
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark;
use File::Spec;
open my $fh, ">", File::Spec->devnull
or die "could not open bit bucket (", File::Spec->devnull, "): $!";
my $x = 'a';
my %subs = (
comma => sub { print $fh $x, $x, $x, $x, $x, $x; },
string => sub { print $fh "$x$x$x$x$x$x"; },
concat => sub { print $fh $x . $x . $x . $x . $x . $x; },
);
Benchmark::cmpthese -1, \%subs;
Which produces
Rate concat comma string
concat 2143658/s -- -4% -4%
comma 2226951/s 4% -- -0%
string 2234181/s 4% 0% --
From this we can see that there is practically no difference between the styles.
Hi Chas,
Thanks for taking the time to reply to my post, and to point out the lifting Perl does for constant creation.
When I run your benchmark I get similar results, and if I run it for longer I see results like:
Rate concat string comma
concat 3226888/s -- -2% -10%
string 3301053/s 2% -- -8%
comma 3572287/s 11% 8% --
I’m not sure if these results are some artifact of the way I’m running the tests. I’m curious if comma separated printing could take less time because it would skip the string creation.
I think it is just noise. I ran the benchmark with -20 and got
nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;Ratenbsp;concatnbsp;stringnbsp;nbsp;comma
concatnbsp;1867761/snbsp;nbsp;nbsp;nbsp;nbsp;--nbsp;nbsp;nbsp;nbsp;-8%nbsp;nbsp;nbsp;-17%
stringnbsp;2036189/snbsp;nbsp;nbsp;nbsp;nbsp;9%nbsp;nbsp;nbsp;nbsp;nbsp;--nbsp;nbsp;nbsp;nbsp;-9%
commanbsp;nbsp;2245308/snbsp;nbsp;nbsp;nbsp;20%nbsp;nbsp;nbsp;nbsp;10%nbsp;nbsp;nbsp;nbsp;nbsp;--
And then with -50 and got
nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;nbsp;Ratenbsp;stringnbsp;nbsp;commanbsp;concat
stringnbsp;1994398/snbsp;nbsp;nbsp;nbsp;nbsp;--nbsp;nbsp;nbsp;nbsp;-0%nbsp;nbsp;nbsp;nbsp;-8%
commanbsp;nbsp;2002747/snbsp;nbsp;nbsp;nbsp;nbsp;0%nbsp;nbsp;nbsp;nbsp;nbsp;--nbsp;nbsp;nbsp;nbsp;-7%
concatnbsp;2160460/snbsp;nbsp;nbsp;nbsp;nbsp;8%nbsp;nbsp;nbsp;nbsp;nbsp;8%nbsp;nbsp;nbsp;nbsp;nbsp;--
Whoops, that should have been
Rate concat string comma
concat 1867761/s – -8% -17%
string 2036189/s 9% – -9%
comma 2245308/s 20% 10% –
Rate string comma concat
string 1994398/s – -0% -8%
comma 2002747/s 0% – -7%
concat 2160460/s 8% 8% –
durn it, I had blogs that don’t use markdown, one last time:
Rate concat string comma
concat 1867761/s -- -8% -17%
string 2036189/s 9% -- -9%
comma 2245308/s 20% 10% --
Rate string comma concat
string 1994398/s -- -0% -8%
comma 2002747/s 0% -- -7%
concat 2160460/s 8% 8% --
Thanks Chas!
I thought passing a list should be faster because it doesn’t concat the strings which also requires more memory?!