diff --git a/include/boost/unordered/detail/foa/concurrent_table.hpp b/include/boost/unordered/detail/foa/concurrent_table.hpp index 8531fac9..66c25791 100644 --- a/include/boost/unordered/detail/foa/concurrent_table.hpp +++ b/include/boost/unordered/detail/foa/concurrent_table.hpp @@ -1265,6 +1265,7 @@ private: it=first; for(auto i=m;i--;++it){ + BOOST_UNORDERED_STATS_COUNTER(num_cmps); auto pos=positions[i]; prober pb(pos); auto pg=this->arrays.groups()+pos; @@ -1277,12 +1278,15 @@ private: auto lck=access(access_mode,pos); do{ auto n=unchecked_countr_zero(mask); - if(BOOST_LIKELY( - pg->is_occupied(n)&& - bool(this->pred()(*it,this->key_from(p[n]))))){ - f(cast_for(access_mode,type_policy::value_from(p[n]))); - ++res; - goto next_key; + if(BOOST_LIKELY(pg->is_occupied(n))){ + BOOST_UNORDERED_INCREMENT_STATS_COUNTER(num_cmps); + if(bool(this->pred()(*it,this->key_from(p[n])))){ + f(cast_for(access_mode,type_policy::value_from(p[n]))); + ++res; + BOOST_UNORDERED_ADD_STATS( + this->cstats.successful_lookup,(pb.length(),num_cmps)); + goto next_key; + } } mask&=mask-1; }while(mask); @@ -1291,6 +1295,8 @@ private: do{ if(BOOST_LIKELY(pg->is_not_overflowed(hashes[i]))|| BOOST_UNLIKELY(!pb.next(this->arrays.groups_size_mask))){ + BOOST_UNORDERED_ADD_STATS( + this->cstats.unsuccessful_lookup,(pb.length(),num_cmps)); goto next_key; } pos=pb.get(); diff --git a/test/unordered/stats_tests.cpp b/test/unordered/stats_tests.cpp index 64492edf..a9315cd4 100644 --- a/test/unordered/stats_tests.cpp +++ b/test/unordered/stats_tests.cpp @@ -18,6 +18,7 @@ #include "../helpers/random_values.hpp" #include "../helpers/test.hpp" #include +#include #include template struct unequal_allocator @@ -215,16 +216,29 @@ template void test_stats() #if defined(BOOST_UNORDERED_CFOA_TESTS) + using key_type = typename Container::key_type; using value_type = typename Container::value_type; test::random_values l2(15000, test::sequential); std::vector v2(l2.begin(), l2.end()); std::atomic found{0}, not_found{0}; thread_runner(v2, [&cc, &found, ¬_found](boost::span sp) { - for (auto const& x : sp) { + // Half the span looked up elementwise + auto sp1 = boost::make_span(sp.begin(), sp.size()/2); + for (auto const& x : sp1) { if(cc.contains(test::get_key(x))) ++found; else ++not_found; } + + // Second half looked up in bulk + std::vector ksp2; + for (auto const& x : boost::make_span(sp1.end(), sp.end())) { + ksp2.push_back(test::get_key(x)); + } + auto visited = cc.visit( + ksp2.begin(), ksp2.end(), [](const value_type&) {}); + found += visited; + not_found += ksp2.size() - visited; }); #else