use strict; use warnings; use Benchmark qw/cmpthese/; use Data::Dump qw/pp/; use feature 'say'; use Test::More; say "Perlversion $^V"; my (@arr_1,@arr_2); sub init_data{ my $range_limit=shift; say "\n\n Setting values range: 1..$range_limit\n"; my %unique; $unique{int rand $range_limit}=undef while keys %unique <8000; @arr_1=keys %unique; %unique=(); $unique{int rand $range_limit}=undef while keys %unique <6000; @arr_2=keys %unique; } { package CMP; my @res= ("") x 8000; sub hash_values_diff { my %diff3; @diff3{@arr_1} = @arr_1; delete @diff3{@arr_2}; @res = values %diff3 ; } sub hash_key_diff { my %diff3; undef @diff3{@arr_1}; delete @diff3{@arr_2}; @res = keys %diff3 ; } sub using_vec_diff { my $vec = ''; vec( $vec, $_, 1 ) = 1 for @arr_2; @res = grep !vec( $vec, $_, 1 ), @arr_1; } sub hash_grep_diff { my %arr_2_hash; undef @arr_2_hash{@arr_2}; @res = grep !exists $arr_2_hash{$_}, @arr_1; } } #--- Test benchmarks for correctness init_data("1e4"); test_subs('_diff$',"CMP"); #--- Compare benchmarks foreach my $range (qw/1e4 1e6 1e8 1e9/) { init_data($range); cmpthese(-5, pckg_subs('_diff$',"CMP") ); } #====== Utility functions for smarter benchmarks sub pckg_subs { my $filter = shift // qr[.]; my $pckg_name = shift // "CMP"; my $stash = do { no strict 'refs'; \ %{ "${pckg_name}::" }; }; # filter all subs from package my $codehashref; while (my ($name,$glob)= each %$stash) { if ( my $cref = *{$glob}{CODE} and $name =~ s/$filter// ) { # print "$name:\t$glob\n"; $codehashref->{$name}=$cref; } } return $codehashref; } sub test_subs { my $h_subs=pckg_subs(@_); my ($last_name,@last_res,$name,$code,@res); # compair pairwise, loop twice to exclude sideeffects for (1..2) { while (($name,$code) =each %$h_subs ) { @res = sort $code->(); is_deeply(\@last_res,\@res,"$last_name ~~ $name (". scalar @res . " entries)") if $last_name; @last_res = @res; $last_name = $name; } } done_testing( ); }