From ff1b01bd10cd07dcd91283bdc0d7ccef496f1719 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 7 Mar 2022 22:14:58 +0200 Subject: [PATCH] Add memory measurements to uint64.cpp --- benchmark/uint64.cpp | 100 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 89 insertions(+), 11 deletions(-) diff --git a/benchmark/uint64.cpp b/benchmark/uint64.cpp index 1ec69fbc..cc4b8cb3 100644 --- a/benchmark/uint64.cpp +++ b/benchmark/uint64.cpp @@ -15,9 +15,11 @@ # include "absl/container/flat_hash_map.h" #endif #include -#include +#include +#include #include #include +#include #include using namespace std::chrono_literals; @@ -187,7 +189,55 @@ template BOOST_NOINLINE void test_erase( Map& map, std::chrono::stead std::cout << std::endl; } -static std::vector< std::pair > times; +static std::size_t s_alloc_bytes = 0; +static std::size_t s_alloc_count = 0; + +template struct allocator +{ + using value_type = T; + + allocator() = default; + + template allocator( allocator const & ) noexcept + { + } + + template bool operator==( allocator const & ) const noexcept + { + return true; + } + + template bool operator!=( allocator const& ) const noexcept + { + return false; + } + + T* allocate( std::size_t n ) const + { + s_alloc_bytes += n; + s_alloc_count++; + + return std::allocator().allocate( n ); + } + + void deallocate( T* p, std::size_t n ) const noexcept + { + s_alloc_bytes -= n; + s_alloc_count--; + + std::allocator().deallocate( p, n ); + } +}; + +struct record +{ + std::string label_; + long long time_; + std::size_t bytes_; + std::size_t count_; +}; + +static std::vector times; template class Map> BOOST_NOINLINE void test( char const* label ) { @@ -195,10 +245,18 @@ template class Map> BOOST_NOINLINE void test( char const* lab Map map; + s_alloc_bytes = 0; + s_alloc_count = 0; + auto t0 = std::chrono::steady_clock::now(); auto t1 = t0; test_insert( map, t1 ); + + std::cout << "Memory: " << s_alloc_bytes << " bytes in " << s_alloc_count << " allocations\n\n"; + + record rec = { label, 0, s_alloc_bytes, s_alloc_count }; + test_lookup( map, t1 ); test_iteration( map, t1 ); test_lookup( map, t1 ); @@ -207,7 +265,8 @@ template class Map> BOOST_NOINLINE void test( char const* lab auto tN = std::chrono::steady_clock::now(); std::cout << "Total: " << ( tN - t0 ) / 1ms << " ms\n\n"; - times.push_back( { label, ( tN - t0 ) / 1ms } ); + rec.time_ = ( tN - t0 ) / 1ms; + times.push_back( rec ); } // multi_index emulation of unordered_map @@ -224,23 +283,42 @@ template using multi_index_map = multi_index_container< pair, indexed_by< hashed_unique< member, K, &pair::first> > - > + >, + ::allocator< pair > >; +// aliases using the counting allocator + +template using allocator_for = ::allocator< std::pair >; + +template using std_unordered_map = + std::unordered_map, std::equal_to, allocator_for>; + +template using boost_unordered_map = + boost::unordered_map, std::equal_to, allocator_for>; + +#ifdef HAVE_ABSEIL + +template using absl_node_hash_map = + absl::node_hash_map, absl::container_internal::hash_default_eq, allocator_for>; + +template using absl_flat_hash_map = + absl::flat_hash_map, absl::container_internal::hash_default_eq, allocator_for>; + +#endif + int main() { init_indices(); - test( "std::unordered_map" ); - test( "boost::unordered_map" ); + test( "std::unordered_map" ); + test( "boost::unordered_map" ); test( "multi_index_map" ); - // test( "std::map" ); - #ifdef HAVE_ABSEIL - test( "absl::node_hash_map" ); - test( "absl::flat_hash_map" ); + test( "absl::node_hash_map" ); + test( "absl::flat_hash_map" ); #endif @@ -248,7 +326,7 @@ int main() for( auto const& x: times ) { - std::cout << x.first << ": " << x.second << " ms\n"; + std::cout << std::setw( 25 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 8 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n"; } }