/* Comparison table for several configurations of boost::bloom::filter. * * Copyright 2025 Joaquin M Lopez Munoz. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * See https://www.boost.org/libs/bloom for library home page. */ #include #include #include #include std::chrono::high_resolution_clock::time_point measure_start,measure_pause; template double measure(F f) { using namespace std::chrono; static const int num_trials=10; static const milliseconds min_time_per_trial(10); std::array trials; for(int i=0;i>(t2-measure_start).count()/runs; } std::sort(trials.begin(),trials.end()); return std::accumulate( trials.begin()+2,trials.end()-2,0.0)/(trials.size()-4); } void pause_timing() { measure_pause=std::chrono::high_resolution_clock::now(); } void resume_timing() { measure_start+=std::chrono::high_resolution_clock::now()-measure_pause; } #include #include #include #include #include #include #include #include #include #include #include #include template struct unordered_flat_set_filter { using value_type=T; unordered_flat_set_filter(std::size_t){} void insert(const T& x){s.insert(x);} bool may_contain(const T& x){return s.contains(x);} boost::unordered_flat_set s; }; static std::size_t num_elements; struct test_results { double fpr; /* % */ double insertion_time; /* ns per element */ double successful_lookup_time; /* ns per element */ double unsuccessful_lookup_time; /* ns per element */ double mixed_lookup_time; /* ns per element */ }; template test_results test(std::size_t c) { using value_type=typename Filter::value_type; static constexpr double lookup_mix=0.1; /* successful pr. */ static constexpr std::uint64_t mixed_lookup_cut= (std::uint64_t)( lookup_mix*(double)(std::numeric_limits::max)()); std::vector data_in,data_out,data_mixed; { boost::detail::splitmix64 rng; boost::unordered_flat_set unique; for(std::size_t i=0;i void row(std::size_t c) { std::cout<< " \n" " "<\n"; boost::mp11::mp_for_each< boost::mp11::mp_transform >([&](auto i){ using filter=typename decltype(i)::type; auto res=test(c); std::cout<< " "<\n" " "<\n" " "<\n" " "<\n" " "<\n" " "<\n"; }); std::cout<< " \n"; } using namespace boost::bloom; template using filters1=boost::mp11::mp_list< filter, filter>, filter,1> >; template using filters2=boost::mp11::mp_list< filter>, filter,1>, filter> >; template using filters3=boost::mp11::mp_list< filter,1>, filter>, filter,1> >; template using filters4=boost::mp11::mp_list< filter>, filter,1>, filter> >; int main(int argc,char* argv[]) { if(argc<2){ std::cerr<<"provide the number of elements\n"; return EXIT_FAILURE; } try{ num_elements=std::stoul(argv[1]); } catch(...){ std::cerr<<"wrong arg\n"; return EXIT_FAILURE; } /* reference table: boost::unordered_flat_set */ auto res=test>(0); std::cout<< "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
boost::unordered_flat_set
insertionsuccessful
lookup
unsuccessful
lookup
mixed
lookup
"<\n" " "<\n" " "<\n" " "<\n" "
\n"; /* filter table */ auto subheader= " K\n" " FPR
[%]\n" " ins.\n" " succ.
lkp.\n" " uns.
lkp.\n" " mixed
lkp.\n"; std::cout<< "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n"<< subheader<< subheader<< subheader<< " \n"; row>( 8); row>(12); row>(16); row>(20); std::cout<< " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n"<< subheader<< subheader<< subheader<< " \n"; row>( 8); row>(12); row>(16); row>(20); std::cout<< " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n"<< subheader<< subheader<< subheader<< " \n"; row>( 8); row>(12); row>(16); row>(20); std::cout<< " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n"<< subheader<< subheader<< subheader<< " \n"; row>( 8); row>(12); row>(16); row>(20); std::cout<<"
filter<int,K>filter<int,1,block<uint64_t,K>>filter<int,1,block<uint64_t,K>,1>
c
filter<int,1,multiblock<uint64_t,K>>filter<int,1,multiblock<uint64_t,K>,1>filter<int,1,fast_multiblock32<K>>
c
filter<int,1,fast_multiblock32<K>,1>filter<int,1,fast_multiblock64<K>>filter<int,1,fast_multiblock64<K>,1>
c
filter<int,1,block<uint64_t[8],K>>filter<int,1,block<uint64_t[8],K>,1>filter<int,1,multiblock<uint64_t[8],K>>
c
\n"; }