Bit-Set
view release on metacpan or search on metacpan
lib/Bit/Set.pm view on Meta::CPAN
A slightly more complex example, in which we create a bitset, set a few bits,
extract them into a buffer (allocated via L<FFI::Platypus::Buffer|https://metacpan.org/pod/FFI::Platypus::Buffer>, though other
possibilities exist e.g. through L<Task::MemManager|https://metacpan.org/pod/Task::MemManager>) and then checking that their
values is correct. The load example logic is as follows: first, we allocate the
buffer, then we set its value using pack, and finaly we put the buffer into a bitset and test the individual bits.
use Test::More; # Convenient testing framework
use Bit::Set qw(:all);
use FFI::Platypus::Buffer;
use constant SIZE_OF_TEST_BIT => 65536;
my $bitset = Bit_new(SIZE_OF_TEST_BIT);
Bit_bset( $bitset, 2 );
Bit_bset( $bitset, 0 );
my $buffer_size = Bit_buffer_size(SIZE_OF_TEST_BIT);
my $scalar =
"\0" x $buffer_size;
my ( $buffer, $size ) =
scalar_to_buffer $scalar;
my $bytes =
Bit_extract( $bitset, $buffer );
my $first_byte = unpack( 'C', substr( $scalar, 0, 1 ) );
is( $first_byte, 0b00000101, 'Bit_extract produces correct buffer' );
Bit_free( \$bitset );
# test_bit_load
$scalar =
"\0" x $buffer_size;
( $buffer, $size ) =
scalar_to_buffer $scalar;
substr( $scalar, 0, 1 ) = pack( 'C', 0b00000101 );
$bitset = Bit_load( SIZE_OF_TEST_BIT, $buffer );
my $load_success =
( Bit_get( $bitset, 0 ) == 1 && Bit_get( $bitset, 2 ) == 1 );
ok( $load_success, 'Bit_load creates bitset from buffer correctly' );
Bit_free( \$bitset );
=item Example 6: Benchmarking of the Perl interface to the Bit library
This example re-implements part of the C benchmarking suite for the Bit library
(found in the source file "benchmark.c" in the L<github repository for Bit|https://github.com/chrisarg/Bit>). The goal is to compare the performance of various bitset operations in Perl with their C counterparts, while showing a larger application th...
In this example we profile the time it takes to execute the intersection and the
count of the two intersection of two bitsets with variable capacity, ranging from 128 to 1048576 bits. The intersection and the count of the intersection is executed 1000 times and the time it takes to finish this benchmark is used to infer the perfo...
There is negligible overhead introduced by the Perl interface, making it a viable option for performance-critical applications, without the "pain" of writing an application in C.
The github repo L<benchmarking-bits|https://github.com/chrisarg/benchmarking-bits> contains an extensive benchmarking suite that compares the performance of the FFI and XS implementations of both the procedural and the OO interfaces of the Bit::Set m...
use strict;
use warnings;
use Time::HiRes qw(gettimeofday tv_interval);
use Bit::Set qw(:all);
# Constants
use constant BPQW => 64; # bits per qword (8 bytes * 8 bits)
use constant BPB => 8; # bits per byte
# Test sizes and iterations
my @size_array = (
128, 256, 512, 1024, 2048, 4096, 8192, 16384,
32768, 65536, 131072, 262144, 524288, 1048576
);
my $iterations = 1000;
# Benchmark function registry
my %benchmark_funcs = (
'Count' => {
code => \&benchmark_bit_count,
descr => 'Count the number of bits set in the bitset'
},
'Inter Count' => {
code => \&benchmark_bit_inter_count,
descr => 'Count the number of bits set in an intersection'
},
);
print "Benchmarking the Perl Bit::Set library\n";
print "=" x 50, "\n";
for my $test ( sort keys %benchmark_funcs ) {
printf "%-15s => %s\n", $test, $benchmark_funcs{$test}{descr};
}
print "\n";
# Benchmark functions for each test type
sub benchmark_bit_count {
my ($size) = @_;
# Pre-create bitsets outside the benchmark
my $bit1 = Bit_new($size);
Bit_set( $bit1, int( $size / 2 ), $size - 1 );
Bit_bset( $bit1, 0 );
my $t0 = [gettimeofday];
my $result = Bit_count($bit1) for 1 .. $iterations;
my $t1 = [gettimeofday];
my $total_time = tv_interval $t0, $t1;
Bit_free( \$bit1 );
return $total_time;
}
sub benchmark_bit_inter_count {
my ($size) = @_;
# Pre-create bitsets outside the benchmark
my $bit1 = Bit_new($size);
my $bit2 = Bit_new($size);
Bit_set( $bit1, int( $size / 2 ), $size - 1 );
Bit_bset( $bit1, 0 );
my $t0 = [gettimeofday];
my $result = Bit_inter_count( $bit1, $bit2 ) for 1 .. $iterations;
my $t1 = [gettimeofday];
my $total_time = tv_interval $t0, $t1;
Bit_free( \$bit1 );
Bit_free( \$bit2 );
return $total_time;
}
sub run_benchmark {
my ( $test_name, $size, $benchmark_func ) = @_;
my $total_time = $benchmark_func->($size);
my $total_time_ns = $total_time * 1_000_000_000; # Convert to nanoseconds
# Calculate derived metrics
my $time_per_iteration = $total_time_ns / $iterations;
my $iterations_per_second = $iterations / $total_time;
# Format and print results
printf
"%-30s (size = %8d): %12.0f ns total\t%8.2f ns/iter\t%10.2e iter/s\n",
"Bit $test_name", $size, $total_time_ns, $time_per_iteration,
$iterations_per_second;
}
# Main benchmark execution
print "Running individual benchmarks...\n";
print "=" x 80, "\n";
for my $test_name ( sort keys %benchmark_funcs ) {
print "\nBenchmarking $test_name: $benchmark_funcs{$test_name}{descr}\n";
print "-" x 80, "\n";
for my $size (@size_array) {
run_benchmark( $test_name, $size, $benchmark_funcs{$test_name}{code} );
}
}
print "\n\nBenchmark completed!\n";
=back
=head1 SEE ALSO
=over 4
=item L<Alien::Bit|https://metacpan.org/pod/Alien::Bit>
This distribution provides the library Bit so that it can be used by other Perl
distributions that are on CPAN. It will download Bit from Github and will build
the (static and dynamic) versions of the library for use by other Perl modules.
=item L<benchmarking-bits|https://github.com/chrisarg/benchmarking-bits>
A collection of benchmarking scripts for various bitset libraries in C and Perl.
=item L<Bit|https://github.com/chrisarg/Bit>
Bit is a high-performance, uncompressed bitset implementation in C, optimized
for modern architectures. The library provides an efficient way to create,
manipulate, and query bitsets with a focus on performance and memory alignment.
The API and the interface is largely based on David Hanson's Bit_T library
discussed in Chapter 13 of "C Interfaces and Implementations",
Addison-Wesley ISBN 0-201-49841-3 extended to incorporate additional operations
(such as counts on unions/differences/intersections of sets),
fast population counts using the libpocnt library and GPU operations for packed
containers of (collections) of Bit(sets).
=item L<Bit::Set::OO|https://metacpan.org/pod/Bit::Set::OO>
Object Oriented interface to the Bit::Set module.
=item L<Bit::Set::DB|https://metacpan.org/pod/Bit::Set::DB>
Procedural interface to the containerized operations of the Bit library.
=item L<Bit::Set::DB::OO|https://metacpan.org/pod/Bit::Set::DB::OO>
Object Oriented interface to the Bit::Set::DB module.
=item L<Bit::Vector|https://metacpan.org/pod/Bit::Vector>
( run in 2.021 seconds using v1.01-cache-2.11-cpan-96521ef73a4 )