From 49c70046e40412ffcddbd98ab33a27ee2c9578cf Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 8 Mar 2022 01:06:04 +0200 Subject: [PATCH] Add memory measurements to uint32.cpp --- benchmark/uint32.cpp | 104 ++++++++++++++++++++++++++++++++++++++----- benchmark/uint64.cpp | 8 +++- 2 files changed, 99 insertions(+), 13 deletions(-) diff --git a/benchmark/uint32.cpp b/benchmark/uint32.cpp index 6aa51a7c..241b94d2 100644 --- a/benchmark/uint32.cpp +++ b/benchmark/uint32.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,18 +189,78 @@ template BOOST_NOINLINE void test_erase( Map& map, std::chrono::stead std::cout << std::endl; } -static std::vector< std::pair > times; +// counting allocator + +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 ) { std::cout << label << ":\n\n"; + s_alloc_bytes = 0; + s_alloc_count = 0; + Map map; 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 +269,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 +287,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 +330,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"; } } diff --git a/benchmark/uint64.cpp b/benchmark/uint64.cpp index cc4b8cb3..eb1906fd 100644 --- a/benchmark/uint64.cpp +++ b/benchmark/uint64.cpp @@ -189,6 +189,8 @@ template BOOST_NOINLINE void test_erase( Map& map, std::chrono::stead std::cout << std::endl; } +// counting allocator + static std::size_t s_alloc_bytes = 0; static std::size_t s_alloc_count = 0; @@ -229,6 +231,8 @@ template struct allocator } }; +// + struct record { std::string label_; @@ -243,11 +247,11 @@ template class Map> BOOST_NOINLINE void test( char const* lab { std::cout << label << ":\n\n"; - Map map; - s_alloc_bytes = 0; s_alloc_count = 0; + Map map; + auto t0 = std::chrono::steady_clock::now(); auto t1 = t0;