in reply to Re: Unexpected: unpack slower than several substr's. Why?
in thread Unexpected: unpack slower than several substr's. Why?

Thanks to everyone who replied(++!).
Some very interesting comments.

The suggestion not to use a lexically scoped/my'ed array, but instead to just build up the return list and no more made some serious differences.

The code is generated on the fly, then eval'ed once to create the anonymous subroutines, then called multiple times. The eval was not included in any benchmarking.

Using a constant for the format, rather than a string in a scalar isn't needed, because of the eval.

I have a feeling some of this problem is due to the fact that the perl I use at home is 5.8.0 with threading.
The 5.6.1 I use at work shows more of an improvement between different implementations.

I've got benchmarks for 5.6.1 and 5.8.0 (in the readmore section below) for comparison.

A_unpack_line_no_array uses pack("A...", $line)
unpack_line_no_array uses pack("a...", $line).

Update: changed pre tags to code tags.

Benchmarks on 5.6.1, sun4-solaris:

Benchmark: timing 200000 iterations of A_unpack_line_no_array, substr_ +into_array, substr_no_array, unpack_line_into_array, unpack_line _no_array... A_unpack_line_no_array: 3 wallclock secs ( 1.56 usr + 0.00 sys = 1. +56 CPU) @ 128205.13/s (n=200000) substr_into_array: 21 wallclock secs (21.54 usr + 0.00 sys = 21.54 CP +U) @ 9285.05/s (n=200000) substr_no_array: 5 wallclock secs ( 4.82 usr + 0.00 sys = 4.82 CPU) + @ 41493.78/s (n=200000) unpack_line_into_array: 10 wallclock secs (10.62 usr + 0.00 sys = 10. +62 CPU) @ 18832.39/s (n=200000) unpack_line_no_array: 1 wallclock secs ( 1.48 usr + 0.00 sys = 1.48 + CPU) @ 135135.14/s (n=200000) Rate substr_into_array unpack_line_into_arr +ay substr_no_array A_unpack_line_no_array unpack_line_no_array substr_into_array 9285/s -- -5 +1% -78% -93% -93% unpack_line_into_array 18832/s 103% +-- -55% -85% -86% substr_no_array 41494/s 347% 12 +0% -- -68% -69% A_unpack_line_no_array 128205/s 1281% 58 +1% 209% -- -5% unpack_line_no_array 135135/s 1355% 61 +8% 226% 5% --

Benchmarks for 5.8.0 and code used for benchmark follows... Benchmarks on 5.8.0-thread, Linux:

Benchmark: timing 200000 iterations of A_unpack_line_no_array, substr_ +into_array, substr_no_array, unpack_line_into_array, unpack_line_no_a +rray... A_unpack_line_no_array: 2 wallclock secs ( 2.53 usr + 0.00 sys = 2. +53 CPU) @ 79051.38/s (n=200000) substr_into_array: 3 wallclock secs ( 4.02 usr + 0.00 sys = 4.02 CP +U) @ 49751.24/s (n=200000) substr_no_array: 1 wallclock secs ( 0.84 usr + 0.00 sys = 0.84 CPU) + @ 238095.24/s (n=200000) unpack_line_into_array: 4 wallclock secs ( 4.22 usr + 0.00 sys = 4. +22 CPU) @ 47393.36/s (n=200000) unpack_line_no_array: 2 wallclock secs ( 2.10 usr + 0.00 sys = 2.10 + CPU) @ 95238.10/s (n=200000) Rate unpack_line_into_array substr_into_arr +ay A_unpack_line_no_array unpack_line_no_array substr_no_array unpack_line_into_array 47393/s -- - +5% -40% -50% -80% substr_into_array 49751/s 5% +-- -37% -48% -79% A_unpack_line_no_array 79051/s 67% 5 +9% -- -17% -67% unpack_line_no_array 95238/s 101% 9 +1% 20% -- -60% substr_no_array 238095/s 402% 37 +9% 201% 150% --

Code used:

#substr_into_array: sub { my $line = shift; my @data; $data[0] = substr($line, 413, 30); $data[1] = substr($line, 373, 30); $data[2] = substr($line, 343, 30); $data[3] = substr($line, 243, 10); $data[4] = substr($line, 283, 15); $data[5] = substr($line, 253, 30); $data[6] = substr($line, 328, 15); $data[7] = substr($line, 298, 30); $data[8] = substr($line, 524, 30); $data[9] = substr($line, 559, 30); $data[10] = substr($line, 443, 6); $data[11] = substr($line, 489, 30); $data[12] = substr($line, 454, 30); $data[13] = substr($line, 240, 3); $data[14] = substr($line, 236, 4); return \@data; }; #-------------------------------------- #substr_no_array: sub { (substr($_[0], 413, 30), substr($_[0], 373, 30), substr($_[0], 343, 30), substr($_[0], 243, 10), substr($_[0], 283, 15), substr($_[0], 253, 30), substr($_[0], 328, 15), substr($_[0], 298, 30), substr($_[0], 524, 30), substr($_[0], 559, 30), substr($_[0], 443, 6), substr($_[0], 489, 30), substr($_[0], 454, 30), substr($_[0], 240, 3), substr($_[0], 236, 4), ); }; #-------------------------------------- #unpack_line_into_array: sub { my @data = unpack('@413a30 @373a30 @343a30 @243a10 @283a15 @253a30 @328a15 @298a30 @524a30 @559a30 @443a6 @489a30 @454a30 @240a3 @236a4 ', $_[0]); return \@data;}; #-------------------------------------- unpack_line_no_array: sub { unpack('@413a30 @373a30 @343a30 @243a10 @283a15 @253a30 @328a15 @298a30 @524a30 @559a30 @443a6 @489a30 @454a30 @240a3 @236a4 ', $_[0]); };