Cool benchmark. I did a couple of variants of your routine to see if removing the map and simplifying the code helped. Interestingly it didn't really. The one called "unpack" is the furthest departure from your code but is neglibly faster when averaged over a few benchmarks. Also interesting was that the "clean" version without the map was consistently slower than yours, as well as any of the modifier versions.

It would be interesting to put the other offered solutions into the benchmark, but sleep calls.

BTW, you get a more accurate average if you use a negative timing. Benchmark.pm will run the benchmark until the clock ticks over, whereas unless your count is really high you stand a good chance of being on the misleading side of the tick.

Cheers,

#!/usr/bin/perl -w use strict; use warnings; use Math::BigInt; use Benchmark 'cmpthese'; our $bigint; our @bytes; sub bigint_to_bytearray { my $bigint = shift; my @bytes; while(1) { my ($q,$r) = $bigint->brsft(8); push(@bytes,$r+0); last if $q == 0; $bigint = Math::BigInt->new($q); } return @bytes; } ## This is the one I would like to speed up ## The array looks something like (127,6,64,27,166,33 .... ) sub bytearray_to_bigint { my @array = @_; my $count = Math::BigInt->new('0'); my $result = Math::BigInt->new('0'); foreach my $a (@array) { $result += $a * (256**$count++); } return $result; } sub bytearray_to_bigint2 { my $result = Math::BigInt->new('0'); for my $byte (reverse @_) { my $tmp = Math::BigInt->new($byte); $result = $result->blsft(8); $result += $tmp; } return $result; } sub ba2bi2 { my @ba = reverse (@_, (0) x (4 - ( @_%4 || 4 ) ) ); my $result = Math::BigInt->new(0); $result *= 4294967296 , $result += $_ for map{ unpack 'N' , pack 'C4' , @ba[4*$_ .. 4*$_+3] } 0 .. ($#ba/4); return $result; } sub ba2bi2_clean { my @ba = reverse (@_, (0) x (4 - ( @_%4 || 4 ) ) ); my $result = Math::BigInt->new(0); for (0 .. ($#ba/4)) { $result *= 4294967296; $result += unpack 'N', pack 'C4', @ba[4*$_ .. 4*$_+3] } return $result; } sub ba2bi2_nomap { my @ba = reverse (@_, (0) x (4 - ( @_%4 || 4 ) ) ); my $result = Math::BigInt->new(0); $result *= 4294967296, $result += unpack 'N', pack 'C4', @ba[4*$_ .. 4*$_+3] for (0 .. ($#ba/4)); return $result; } sub ba2bi2_unpack { my $result = Math::BigInt->new(0); $result *= 4294967296, $result += $_ for unpack 'N*', reverse pack 'C'.(4*int(@_/4+1)), @_; return $result; } $|++; $bigint = Math::BigInt->new('12345678' x 10); @bytes = bigint_to_bytearray($bigint); my $comphash={ 'mult' => 'bytearray_to_bigint(@bytes)', 'shift' => 'bytearray_to_bigint2(@bytes)', 'ba2bi2' => 'ba2bi2(@bytes)', 'nomap' => 'ba2bi2_nomap(@bytes)', 'clean' => 'ba2bi2_clean(@bytes)', 'unpack' => 'ba2bi2_unpack(@bytes)', }; foreach my $comp (values %$comphash) { eval <<EVAL or die $@; print '$comp',"\n",$comp,"\n"; 1 EVAL } cmpthese(-10, $comphash); __END__
ba2bi2(@bytes) +123456781234567812345678123456781234567812345678123456781234567812345 +67812345678 bytearray_to_bigint2(@bytes) +123456781234567812345678123456781234567812345678123456781234567812345 +67812345678 ba2bi2_nomap(@bytes) +123456781234567812345678123456781234567812345678123456781234567812345 +67812345678 ba2bi2_unpack(@bytes) +123456781234567812345678123456781234567812345678123456781234567812345 +67812345678 bytearray_to_bigint(@bytes) +123456781234567812345678123456781234567812345678123456781234567812345 +67812345678 ba2bi2_clean(@bytes) +123456781234567812345678123456781234567812345678123456781234567812345 +67812345678 Benchmark: running ba2bi2, clean, mult, nomap, shift, unpack, each for at least 10 CPU s +econds... ba2bi2: 13 wallclock secs (10.76 usr + 0.01 sys = 10.77 CPU) @ 69 +.21/s (n=745) clean: 12 wallclock secs (10.29 usr + 0.00 sys = 10.29 CPU) @ 68 +.55/s (n=705) mult: 12 wallclock secs (10.12 usr + 0.00 sys = 10.12 CPU) @ 5 +.24/s (n=53) nomap: 12 wallclock secs (10.08 usr + 0.00 sys = 10.08 CPU) @ 69 +.48/s (n=700) shift: 12 wallclock secs (10.28 usr + 0.02 sys = 10.30 CPU) @ 6 +.99/s (n=72) unpack: 12 wallclock secs (10.13 usr + 0.00 sys = 10.13 CPU) @ 71 +.05/s (n=720) Rate mult shift clean ba2bi2 nomap unpack mult 5.24/s -- -25% -92% -92% -92% -93% shift 6.99/s 33% -- -90% -90% -90% -90% clean 68.5/s 1208% 881% -- -1% -1% -4% ba2bi2 69.2/s 1221% 890% 1% -- -0% -3% nomap 69.5/s 1226% 894% 1% 0% -- -2% unpack 71.0/s 1256% 917% 4% 3% 2% --

--- demerphq
my friends call me, usually because I'm late....


In reply to Re: Re: Converting an array of bytes into a BigInt - 1500% quicker. by demerphq
in thread Converting an array of bytes into a BigInt - speed considerations by dempa

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.