Algorithm-HyperLogLog

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN


0.14    Sat Apr 14 03:30:00 2013
    - Change required perl version
    - Add $VERSION to Algorithm/HyperLogLog/PP.pm

0.11    Fri Apr 05 01:40:00 2013
    - XSLoader is loaded when runtime

0.10    Wed Apr 03 22:15:00 2013
    - [enhancement] register dump/restore feature
    - [bugfix] hash calculation error in big endian environment

0.05    Wed Mar 27 23:30:00 2013
    - Fixed: integer overflow in 32bit environment

0.04    Sat Mar 23 01:50:00 2013
    - Fixed: unportable tests 

0.03    Thu Mar 21 03:15:00 2013
    - Remove unnecessary code in XS

lib/Algorithm/HyperLogLog.pm  view on Meta::CPAN

        $PERL_ONLY = !eval { XSLoader::load( __PACKAGE__, $VERSION ); };
    }
    if ($PERL_ONLY) {
        require 'Algorithm/HyperLogLog/PP.pm';
    }
}

sub new_from_file {
    my ( $class, $filename ) = @_;
    open my $fh, '<', $filename or die $!;
    my $on_error = sub { close $fh; croak "Invalid dump file($filename)"; };

    binmode $fh;
    my ( @dumpdata, $buf, $readed );

    # Read register size data
    $readed = read( $fh, $buf, 1 );
    $on_error->() if $readed != 1;
    my $k = unpack 'C', $buf;

    # Read register content data
    my $m = 2**$k;
    $readed = read $fh, $buf, $m;
    $on_error->() if $readed != $m;
    close $fh;
    @dumpdata = unpack 'C*', $buf;
    my $self = $class->_new_from_dump( $k, \@dumpdata );
    return $self;
}

sub dump_to_file {
    my ( $self, $filename ) = @_;
    my $k        = log( $self->register_size ) / log(2);    # Calculate log2(register_size)
    my $dumpdata = $self->_dump_register();

t/02_basic.t  view on Meta::CPAN

use strict;
use warnings;
use Test::More;
use Test::Fatal qw(exception lives_ok);
use Algorithm::HyperLogLog;
use Algorithm::HyperLogLog::PP;

plan skip_all => 'No XS' unless Algorithm::HyperLogLog->XS;

my $error_sum = 0;
my $repeat    = 100;

for ( 1 .. $repeat ) {

    my $hll   = Algorithm::HyperLogLog->new(16);
    my $hllpp = Algorithm::HyperLogLog::PP->new(16);

    my %unique = ( q{} => 1 );

    for ( 0 .. 999 ) {

t/02_basic.t  view on Meta::CPAN

        ok 1, 'XS and PP compatibility test';
    }
    else {
        diag $cardinality;
        diag $cardinalitypp;
        fail();
    }

    my $unique = scalar keys %unique;

    $error_sum += abs( $unique - $cardinality );

}

my $error_avg   = $error_sum / $repeat;
my $error_ratio = $error_avg / 10001 * 100;

ok $error_ratio < 1.0, 'Error ratio less than 1.0%';

done_testing();

sub random_string {
    my $n   = shift;
    my $str = q{};
    for ( 1 .. $n ) {
        my $rand = rand(26);
        $str .= chr( ord('A') + $rand );
    }

t/03_pp.t  view on Meta::CPAN

BEGIN {
    $Algorithm::HyperLogLog::PERL_ONLY = 1;
}
use Algorithm::HyperLogLog;
my $hll = Algorithm::HyperLogLog->new(16);

isa_ok $hll, 'Algorithm::HyperLogLog';

ok !$hll->XS, 'is Pure Perl?';

my $error_sum = 0;
my $repeat    = 100;

for ( 1 .. $repeat ) {

    my %unique;
    for ( 0 .. 999 ) {
        my $str = q{};
        while ( exists $unique{$str} ) {
            $str = random_string(10);
        }
        $unique{$str} = 1;
    }

    $hll->add( keys %unique );
    my $num = scalar keys %unique;
    my $error_sum += abs( $num - $hll->estimate() );
}
my $error_avg   = $error_sum / $repeat;
my $error_ratio = $error_avg / 1000 * 100;
ok $error_ratio < 1;

done_testing();

sub random_string {
    my $n   = shift;
    my $str = q{};
    for ( 1 .. $n ) {
        my $rand = rand(26);
        $str .= chr( ord('A') + $rand );
    }



( run in 0.722 second using v1.01-cache-2.11-cpan-65fba6d93b7 )