Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: Can unpack add zero bytes before converting?

by mossi2000 (Initiate)
on Sep 13, 2021 at 13:19 UTC ( [id://11136717]=note: print w/replies, xml ) Need Help??


in reply to Can unpack add zero bytes before converting?

Hi to all who have answered!

Thanks for all your input.
Of course my question was driven by "need for speed".
I tried to minimize the number of loops to go over the buffer (2k, 4k, 8k, or 16k of values)
I extended the benchmark script and put the different solutions all in there.
Below you can see the results.

Three things:
-I was astonished that the unpack_pack_unpack way is still twice as fast as my solution using bitstrings.
-the solution with the borrowed pad to 8 bytes is really nifty! With one single buffer padding,
one can nearly achieve what I wanted first. One unpack only.
-Next surprise: the used
 $_ &= $mask for @values;
does the same as
map { $_ &= $mask) @values;
but is about 25% faster....Must be the useless generation of the resulting array...
(the test with @values = map { $_ &= $mask) @values; gets a rate of only 4000/s!!)


So of course I'll go with the fastest solution, which has the advantage that it includes the
easy case of 8 bytes per value at no cost when I pre-compute the unpack format.

Thanks again,
Axel

se strict; use warnings; no warnings 'portable'; use Benchmark 'cmpthese'; my $bytes_per_value = 5; my $count = 1_000; my $value = 0xf_dead_beef_4; my $bin_value = substr (pack ('Q', $value), 0, $bytes_per_value); my $buffer = $bin_value x $count; my $fmt = sprintf "(b%d)*", $bytes_per_value << 3; my $pad_len = 8 - $bytes_per_value; my $mask = ~ 0 >> $pad_len * 8; my $pad = "\0" x $pad_len; my @fmts = ('(Q<)', '(Q<X)', '(Q<X2)', '(Q<X3)'); my $fmt2 = $fmts[$pad_len] . sprintf ("%d", $count); cmpthese -1, { strings => sub { my @values = map { oct '0b'.reverse ($_)} unpack ($fmt, $buffe +r); return \@values; }, map_unpack => sub { my @values = map { unpack 'Q<', "$_$pad" } unpack "(a$bytes_p +er_value)*", $buffer; return \@values; }, unpack_pack_unpack => sub { my @values = unpack '(Q<)*', pack '(a8)*', unpack "(a$bytes_pe +r_value)*", $buffer; }, numbers_map => sub { my @values = unpack "(QX$pad_len)$count", $buffer.$pad; map { $_ &= $mask } @values; return \@values; }, numbers_for => sub { my @values = unpack $fmt2, $buffer.$pad; if ($pad_len) { $_ &= $mask for @values; } return \@values; }, }; __END__
Rate strings map_unpack unpack_pack_unpack number +s_map numbers_for strings 1707/s -- -28% -47% + -69% -77% map_unpack 2386/s 40% -- -26% + -56% -68% unpack_pack_unpack 3242/s 90% 36% -- + -41% -57% numbers_map 5462/s 220% 129% 68% + -- -28% numbers_for 7538/s 342% 216% 133% + 38% --

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11136717]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (1)
As of 2024-04-24 13:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found