From f77bdb9b6760b692948369f74bd106e734a0a337 Mon Sep 17 00:00:00 2001 From: joaquintides Date: Wed, 29 May 2024 19:51:32 +0200 Subject: [PATCH 01/11] updated is_avalanching trait protocol --- benchmark/string.cpp | 5 +-- benchmark/string_stats.cpp | 7 +++-- benchmark/string_view.cpp | 5 +-- doc/unordered/changes.adoc | 1 + doc/unordered/hash_quality.adoc | 2 +- doc/unordered/hash_traits.adoc | 11 +++++-- include/boost/unordered/hash_traits.hpp | 34 ++++++++++++++++----- test/unordered/hash_is_avalanching_test.cpp | 27 ++++++++++++++++ 8 files changed, 74 insertions(+), 18 deletions(-) diff --git a/benchmark/string.cpp b/benchmark/string.cpp index 5f4cbc13..dd190f6e 100644 --- a/benchmark/string.cpp +++ b/benchmark/string.cpp @@ -1,5 +1,5 @@ // Copyright 2021 Peter Dimov. -// Copyright 2023 Joaquin M Lopez Munoz. +// Copyright 2023-2024 Joaquin M Lopez Munoz. // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -25,6 +25,7 @@ #include #include #include +#include using namespace std::chrono_literals; @@ -341,7 +342,7 @@ template<> struct fnv1a_hash_impl<64> struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits::digits > { - using is_avalanching = void; + using is_avalanching = std::true_type; }; template using std_unordered_map_fnv1a = diff --git a/benchmark/string_stats.cpp b/benchmark/string_stats.cpp index b3bd3ba6..513681d5 100644 --- a/benchmark/string_stats.cpp +++ b/benchmark/string_stats.cpp @@ -18,6 +18,7 @@ #include #include #include +#include using namespace std::chrono_literals; @@ -262,7 +263,7 @@ template<> struct fnv1a_hash_impl<64> struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits::digits > { - using is_avalanching = void; + using is_avalanching = std::true_type; }; template using boost_unordered_flat_map_fnv1a = @@ -272,7 +273,7 @@ template using boost_unordered_flat_map_fnv1a = struct slightly_bad_hash { - using is_avalanching = void; + using is_avalanching = std::true_type; std::size_t operator()( std::string const& s ) const { @@ -295,7 +296,7 @@ template using boost_unordered_flat_map_slightly_bad_hash = struct bad_hash { - using is_avalanching = void; + using is_avalanching = std::true_type; std::size_t operator()( std::string const& s ) const { diff --git a/benchmark/string_view.cpp b/benchmark/string_view.cpp index 2b1583be..df37cd12 100644 --- a/benchmark/string_view.cpp +++ b/benchmark/string_view.cpp @@ -1,5 +1,5 @@ // Copyright 2021 Peter Dimov. -// Copyright 2023 Joaquin M Lopez Munoz. +// Copyright 2023-2024 Joaquin M Lopez Munoz. // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -26,6 +26,7 @@ #include #include #include +#include using namespace std::chrono_literals; @@ -342,7 +343,7 @@ template<> struct fnv1a_hash_impl<64> struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits::digits > { - using is_avalanching = void; + using is_avalanching = std::true_type; }; template using std_unordered_map_fnv1a = diff --git a/doc/unordered/changes.adoc b/doc/unordered/changes.adoc index b59bb90b..56a2dd4c 100644 --- a/doc/unordered/changes.adoc +++ b/doc/unordered/changes.adoc @@ -10,6 +10,7 @@ * Added container `pmr` aliases when header `` is available. The alias `boost::unordered::pmr::[container]` refers to `boost::unordered::[container]` with a `std::pmr::polymorphic_allocator` allocator type. * Equipped open-addressing and concurrent containers to internally calculate and provide statistical metrics affected by the quality of the hash function. This functionality is enabled by the global macro `BOOST_UNORDERED_ENABLE_STATS`. +* Avalanching hash functions must now be marked via an `is_avalanching` typedef with an embedded `value` constant set to `true` (typically, defining `is_avalanching` as `std::true_type`). `using is_avalanching = void` is deprecated but allowed for backwards compatibility. == Release 1.85.0 diff --git a/doc/unordered/hash_quality.adoc b/doc/unordered/hash_quality.adoc index f8c94871..828e9421 100644 --- a/doc/unordered/hash_quality.adoc +++ b/doc/unordered/hash_quality.adoc @@ -33,7 +33,7 @@ follows: ---- struct my_string_hash_function { - using is_avalanching = void; // instruct Boost.Unordered to not use post-mixing + using is_avalanching = std::true_type; // instruct Boost.Unordered to not use post-mixing std::size_t operator()(const std::string& x) const { diff --git a/doc/unordered/hash_traits.adoc b/doc/unordered/hash_traits.adoc index ae2ca67e..0abd5dcf 100644 --- a/doc/unordered/hash_traits.adoc +++ b/doc/unordered/hash_traits.adoc @@ -32,9 +32,14 @@ large changes in the returned hash code —ideally, flipping one bit in the the input value results in each bit of the hash code flipping with probability 50%. Approaching this property is critical for the proper behavior of open-addressing hash containers. -`hash_is_avalanching::value` is `true` if `Hash::is_avalanching` is a valid type, -and `false` otherwise. -Users can then declare a hash function `Hash` as avalanching either by embedding an `is_avalanching` typedef +`hash_is_avalanching::value` is: + + * `false` if `Hash::is_avalanching` is not present, + * `Hash::is_avalanching::value` if this is present and convertible at compile time to a `bool`, + * `true` if `Hash::is_avalanching` is `void` (this usage is deprecated). + +The behavior is undefined if none of the three cases above is met. +Users can then declare a hash function `Hash` as avalanching either by embedding an appropriate `is_avalanching` typedef into the definition of `Hash`, or directly by specializing `hash_is_avalanching` to a class with an embedded compile-time constant `value` set to `true`. diff --git a/include/boost/unordered/hash_traits.hpp b/include/boost/unordered/hash_traits.hpp index d5f94a78..24fdf808 100644 --- a/include/boost/unordered/hash_traits.hpp +++ b/include/boost/unordered/hash_traits.hpp @@ -1,6 +1,6 @@ /* Hash function characterization. * - * Copyright 2022 Joaquin M Lopez Munoz. + * Copyright 2022-2024 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) @@ -19,12 +19,28 @@ namespace unordered{ namespace detail{ template -struct hash_is_avalanching_impl: std::false_type{}; +struct hash_is_avalanching_impl:std::false_type{}; + +template +struct avalanching_value +{ + static constexpr bool value=IsAvalanching::value; +}; + +/* may be explicitly marked as BOOST_DEPRECATED in the future */ +template<> struct avalanching_value +{ + static constexpr bool value=true; +}; template -struct hash_is_avalanching_impl >: - std::true_type{}; +struct hash_is_avalanching_impl< + Hash, + boost::unordered::detail::void_t +>:std::integral_constant< + bool, + avalanching_value::value +>{}; } /* namespace detail */ @@ -32,8 +48,12 @@ struct hash_is_avalanching_impl::value is true when the type Hash::is_avalanching - * is present, false otherwise. +/* hash_is_avalanching::value is: + * - false if Hash::is_avalanching is not present. + * - Hash::is_avalanching::value if this is present and constexpr-convertible + * to a bool. + * - true if Hash::is_avalanching is void (deprecated). + * UB otherwise. */ template struct hash_is_avalanching: detail::hash_is_avalanching_impl::type{}; diff --git a/test/unordered/hash_is_avalanching_test.cpp b/test/unordered/hash_is_avalanching_test.cpp index 1e25e033..7ba7e083 100644 --- a/test/unordered/hash_is_avalanching_test.cpp +++ b/test/unordered/hash_is_avalanching_test.cpp @@ -1,4 +1,5 @@ // Copyright 2022 Peter Dimov +// Copyright 2024 Joaquin M Lopez Munoz // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -26,6 +27,7 @@ namespace unordered #include #include +#include struct X1 { @@ -36,6 +38,27 @@ struct X2 typedef void is_avalanching; }; +struct X4 +{ + using is_avalanching = std::false_type; +}; + +struct X5 +{ + using is_avalanching = std::true_type; +}; + +struct X6 +{ + using is_avalanching = boost::false_type; +}; + +struct X7 +{ + using is_avalanching = boost::true_type; +}; + + int main() { using boost::unordered::hash_is_avalanching; @@ -43,6 +66,10 @@ int main() BOOST_TEST_TRAIT_FALSE((hash_is_avalanching)); BOOST_TEST_TRAIT_TRUE((hash_is_avalanching)); BOOST_TEST_TRAIT_TRUE((hash_is_avalanching)); + BOOST_TEST_TRAIT_FALSE((hash_is_avalanching)); + BOOST_TEST_TRAIT_TRUE((hash_is_avalanching)); + BOOST_TEST_TRAIT_FALSE((hash_is_avalanching)); + BOOST_TEST_TRAIT_TRUE((hash_is_avalanching)); return boost::report_errors(); } From 7e9032c703651e495d806fc3cbbb03a559471286 Mon Sep 17 00:00:00 2001 From: joaquintides Date: Thu, 30 May 2024 09:08:07 +0200 Subject: [PATCH 02/11] s/UB/ill-formed --- doc/unordered/hash_traits.adoc | 4 ++-- include/boost/unordered/hash_traits.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/unordered/hash_traits.adoc b/doc/unordered/hash_traits.adoc index 0abd5dcf..5a60fa82 100644 --- a/doc/unordered/hash_traits.adoc +++ b/doc/unordered/hash_traits.adoc @@ -36,9 +36,9 @@ this property is critical for the proper behavior of open-addressing hash contai * `false` if `Hash::is_avalanching` is not present, * `Hash::is_avalanching::value` if this is present and convertible at compile time to a `bool`, - * `true` if `Hash::is_avalanching` is `void` (this usage is deprecated). + * `true` if `Hash::is_avalanching` is `void` (this usage is deprecated), + * ill-formed otherwise. -The behavior is undefined if none of the three cases above is met. Users can then declare a hash function `Hash` as avalanching either by embedding an appropriate `is_avalanching` typedef into the definition of `Hash`, or directly by specializing `hash_is_avalanching` to a class with an embedded compile-time constant `value` set to `true`. diff --git a/include/boost/unordered/hash_traits.hpp b/include/boost/unordered/hash_traits.hpp index 24fdf808..f6b912b7 100644 --- a/include/boost/unordered/hash_traits.hpp +++ b/include/boost/unordered/hash_traits.hpp @@ -53,7 +53,7 @@ struct hash_is_avalanching_impl< * - Hash::is_avalanching::value if this is present and constexpr-convertible * to a bool. * - true if Hash::is_avalanching is void (deprecated). - * UB otherwise. + * - ill-formed otherwise. */ template struct hash_is_avalanching: detail::hash_is_avalanching_impl::type{}; From 401b06663f14a4c6f0488e72fbb5e3b062aecbeb Mon Sep 17 00:00:00 2001 From: joaquintides Date: Thu, 30 May 2024 09:11:06 +0200 Subject: [PATCH 03/11] forced a compile error when Hash::is_avalanching is not a type --- include/boost/unordered/hash_traits.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/unordered/hash_traits.hpp b/include/boost/unordered/hash_traits.hpp index f6b912b7..5e2b1af0 100644 --- a/include/boost/unordered/hash_traits.hpp +++ b/include/boost/unordered/hash_traits.hpp @@ -42,6 +42,12 @@ struct hash_is_avalanching_impl< avalanching_value::value >{}; +template +struct hash_is_avalanching_impl< + Hash, + typename std::enable_if<((void)Hash::is_avalanching,true)>::type +>{}; /* Hash::is_avalanching is not a type: compile error downstream */ + } /* namespace detail */ /* Each trait can be partially specialized by users for concrete hash functions From 29521c3a77e0c44318da8901594dd0f9e96e2299 Mon Sep 17 00:00:00 2001 From: Braden Ganetsky Date: Sat, 11 May 2024 11:28:06 -0500 Subject: [PATCH 04/11] Create natvis file and update CMakeLists.txt --- CMakeLists.txt | 9 +++++++++ extra/boost_unordered.natvis | 10 ++++++++++ 2 files changed, 19 insertions(+) create mode 100644 extra/boost_unordered.natvis diff --git a/CMakeLists.txt b/CMakeLists.txt index b8f2a176..9bcd6769 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,15 @@ target_link_libraries(boost_unordered Boost::throw_exception ) +if(CMAKE_VERSION VERSION_GREATER 3.18 AND CMAKE_GENERATOR MATCHES "Visual Studio") + + file(GLOB_RECURSE boost_unordered_IDEFILES CONFIGURE_DEPENDS include/*.hpp) + source_group(TREE ${PROJECT_SOURCE_DIR}/include FILES ${boost_unordered_IDEFILES} PREFIX "Header Files") + list(APPEND boost_unordered_IDEFILES extra/boost_unordered.natvis) + target_sources(boost_unordered PRIVATE ${boost_unordered_IDEFILES}) + +endif() + target_compile_features(boost_unordered INTERFACE cxx_std_11) if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") diff --git a/extra/boost_unordered.natvis b/extra/boost_unordered.natvis new file mode 100644 index 00000000..befb2355 --- /dev/null +++ b/extra/boost_unordered.natvis @@ -0,0 +1,10 @@ + + + + + + From 485101db9ba384430db49f44f11d639e088388f2 Mon Sep 17 00:00:00 2001 From: Braden Ganetsky Date: Fri, 31 May 2024 23:51:30 -0500 Subject: [PATCH 05/11] Write natvis for fca containers --- extra/boost_unordered.natvis | 88 ++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/extra/boost_unordered.natvis b/extra/boost_unordered.natvis index befb2355..344ab554 100644 --- a/extra/boost_unordered.natvis +++ b/extra/boost_unordered.natvis @@ -7,4 +7,92 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + + + + + + + + + + + + + + + hash(active_idx()) + key_eq(active_idx()) + hash(spare_idx()) + key_eq(spare_idx()) + + + + + + + + + + + + current_bucket = &buckets[bucket_index] + node = current_bucket->next + + node->buf.t_ + node = node->next + + ++bucket_index + + + + + + + + + + + + + + current_bucket = &buckets[bucket_index] + node = current_bucket->next + + node->buf.t_ + node = node->next + + ++bucket_index + + + + + + + + + + {{ size={table_.size_} }} + + table_.buckets_.size_ + table_.mlf_ + *reinterpret_cast<table::functions*>(&table_) + *reinterpret_cast<table::bucket_array_type::node_allocator_type*>(&table_.buckets_) + table_.buckets_ + + + + + + {{ size={table_.size_} }} + + table_.buckets_.size_ + table_.mlf_ + *reinterpret_cast<table::functions*>(&table_) + *reinterpret_cast<table::bucket_array_type::node_allocator_type*>(&table_.buckets_) + table_.buckets_,view(MapHelper) + + + From 27ead86b360068c6473d9ee520c9c80983a2a477 Mon Sep 17 00:00:00 2001 From: Braden Ganetsky Date: Fri, 31 May 2024 23:51:31 -0500 Subject: [PATCH 06/11] Write natvis for fca iterators --- extra/boost_unordered.natvis | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/extra/boost_unordered.natvis b/extra/boost_unordered.natvis index 344ab554..308e2565 100644 --- a/extra/boost_unordered.natvis +++ b/extra/boost_unordered.natvis @@ -95,4 +95,16 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + + + + + {p->buf.t_} + {{ end iterator }} + + p->buf.t_ + + + From 763a8629284bb4f3e9809640874ebac078cbe7ed Mon Sep 17 00:00:00 2001 From: Braden Ganetsky Date: Fri, 31 May 2024 23:51:31 -0500 Subject: [PATCH 07/11] Write natvis for foa and cfoa helpers --- extra/boost_unordered.natvis | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/extra/boost_unordered.natvis b/extra/boost_unordered.natvis index 308e2565..02b85421 100644 --- a/extra/boost_unordered.natvis +++ b/extra/boost_unordered.natvis @@ -107,4 +107,56 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + + + {*p} + + *p + + + + + + ({p->first}, {p->second}) + + p->first + p->second + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 0a66c687fdad0d214f29570672986c2fa6654cc7 Mon Sep 17 00:00:00 2001 From: Braden Ganetsky Date: Sat, 1 Jun 2024 09:26:37 -0500 Subject: [PATCH 08/11] Write natvis for foa and cfoa containers --- extra/boost_unordered.natvis | 142 ++++++++++++++++++++ include/boost/unordered/detail/foa/core.hpp | 6 + 2 files changed, 148 insertions(+) diff --git a/extra/boost_unordered.natvis b/extra/boost_unordered.natvis index 02b85421..b00f49bb 100644 --- a/extra/boost_unordered.natvis +++ b/extra/boost_unordered.natvis @@ -159,4 +159,146 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *p_ + + first_time = false + + n0 = reinterpret_cast<uintptr_t>(pc_) % sizeof(group_type) + pc_ -= (ptrdiff_t)n0 + + mask = (reinterpret_cast<group_type*>(pc_)->match_occupied() >> (n0+1)) << (n0+1) + + pc_ += sizeof(group_type) + p_ += group_type::N + mask = reinterpret_cast<group_type*>(pc_)->match_occupied() + + + n = countr_zero(mask) + + p_ = nullptr + + + pc_ += (ptrdiff_t)n + p_ -= (ptrdiff_t)n0 + p_ += (ptrdiff_t)n + + + + + + + + + + + + + + + + + + + + + + + *p_ + + first_time = false + + n0 = reinterpret_cast<uintptr_t>(pc_) % sizeof(group_type) + pc_ -= (ptrdiff_t)n0 + + mask = (reinterpret_cast<group_type*>(pc_)->match_occupied() >> (n0+1)) << (n0+1) + + pc_ += sizeof(group_type) + p_ += group_type::N + mask = reinterpret_cast<group_type*>(pc_)->match_occupied() + + + n = countr_zero(mask) + + p_ = nullptr + + + pc_ += (ptrdiff_t)n + p_ -= (ptrdiff_t)n0 + p_ += (ptrdiff_t)n + + + + + + + + + + + + + + {{ size={table_.size_ctrl.size} }} + + *reinterpret_cast<hasher*>(static_cast<table_type::super::base1*>(&table_)) + *reinterpret_cast<key_equal*>(static_cast<table_type::super::base2*>(&table_)) + *reinterpret_cast<allocator_type*>(static_cast<table_type::super::base3*>(&table_)) + table_ + + + + + + + {{ size={table_.size_ctrl.size} }} + + *reinterpret_cast<hasher*>(static_cast<table_type::super::base1*>(&table_)) + *reinterpret_cast<key_equal*>(static_cast<table_type::super::base2*>(&table_)) + *reinterpret_cast<allocator_type*>(static_cast<table_type::super::base3*>(&table_)) + table_,view(MapHelper) + + + diff --git a/include/boost/unordered/detail/foa/core.hpp b/include/boost/unordered/detail/foa/core.hpp index db73a866..513b433d 100644 --- a/include/boost/unordered/detail/foa/core.hpp +++ b/include/boost/unordered/detail/foa/core.hpp @@ -1413,6 +1413,12 @@ __declspec(empty_bases) /* activate EBO with multiple inheritance */ table_core:empty_value,empty_value,empty_value { +private: + // These `baseN` aliases are for debugger visualizations, like natvis + using base1=empty_value; + using base2=empty_value; + using base3=empty_value; + public: using type_policy=TypePolicy; using group_type=Group; From 901f0a29b8d55b713c9b55105018e64d9ce64df6 Mon Sep 17 00:00:00 2001 From: Braden Ganetsky Date: Fri, 31 May 2024 23:51:32 -0500 Subject: [PATCH 09/11] Write natvis for foa iterators --- extra/boost_unordered.natvis | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/extra/boost_unordered.natvis b/extra/boost_unordered.natvis index b00f49bb..e0f5bc46 100644 --- a/extra/boost_unordered.natvis +++ b/extra/boost_unordered.natvis @@ -301,4 +301,15 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + + + + {*p_} + {{ end iterator }} + + *p_ + + + From 317d4aa06023c4ecb4b8ba27c6601ab727bb73d5 Mon Sep 17 00:00:00 2001 From: Braden Ganetsky Date: Fri, 31 May 2024 23:51:33 -0500 Subject: [PATCH 10/11] Write release notes and documentation for natvis --- doc/unordered.adoc | 1 + doc/unordered/changes.adoc | 1 + doc/unordered/debuggability.adoc | 16 ++++++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 doc/unordered/debuggability.adoc diff --git a/doc/unordered.adoc b/doc/unordered.adoc index 1febb283..8f339623 100644 --- a/doc/unordered.adoc +++ b/doc/unordered.adoc @@ -18,6 +18,7 @@ include::unordered/concurrent.adoc[] include::unordered/hash_quality.adoc[] include::unordered/compliance.adoc[] include::unordered/structures.adoc[] +include::unordered/debuggability.adoc[] include::unordered/benchmarks.adoc[] include::unordered/rationale.adoc[] include::unordered/ref.adoc[] diff --git a/doc/unordered/changes.adoc b/doc/unordered/changes.adoc index 56a2dd4c..ffdaf242 100644 --- a/doc/unordered/changes.adoc +++ b/doc/unordered/changes.adoc @@ -11,6 +11,7 @@ * Added container `pmr` aliases when header `` is available. The alias `boost::unordered::pmr::[container]` refers to `boost::unordered::[container]` with a `std::pmr::polymorphic_allocator` allocator type. * Equipped open-addressing and concurrent containers to internally calculate and provide statistical metrics affected by the quality of the hash function. This functionality is enabled by the global macro `BOOST_UNORDERED_ENABLE_STATS`. * Avalanching hash functions must now be marked via an `is_avalanching` typedef with an embedded `value` constant set to `true` (typically, defining `is_avalanching` as `std::true_type`). `using is_avalanching = void` is deprecated but allowed for backwards compatibility. +* Added Visual Studio Natvis framework custom visualizations for containers and iterators. This works for all containers with an allocator using raw pointers. In this release, containers and iterators are not supported if their allocator uses fancy pointers. This may be addressed in later releases. == Release 1.85.0 diff --git a/doc/unordered/debuggability.adoc b/doc/unordered/debuggability.adoc new file mode 100644 index 00000000..cd40e498 --- /dev/null +++ b/doc/unordered/debuggability.adoc @@ -0,0 +1,16 @@ +[#debuggability] +:idprefix: debuggability_ + += Debuggability + +== Visual Studio Natvis + +All containers and iterators have custom visualizations in the Natvis framework, as long as their allocator uses regular raw pointers. Any container or iterator with an allocator using fancy pointers does not have a custom visualization right now. + +The visualizations mirror those for the standard unordered containers. A container has a maximum of 100 elements displayed at once. Each set element has its item name listed as `[i]`, where `i` is the index in the display, starting at `0`. Each map element has its item name listed as `[\{key-display}]` by default. For example, if the first element is the pair `("abc", 1)`, the item name will be `["abc"]`. This behaviour can be overridden by using the view "ShowElementsByIndex", which switches the map display behaviour to name the elements by index. This same view name is used in the standard unordered containers. + +By default, the closed-addressing containers will show the `[hash_function]` and `[key_eq]`, the `[spare_hash_function]` and `[spare_key_eq]` if applicable, the `[allocator]`, and the elements. Using the view "detailed" adds the `[bucket_count]` and `[max_load_factor]`. Conversely, using the view "simple" shows only the elements, with no other items present. + +By default, the open-addressing containers will show the `[hash_function]`, `[key_eq]`, `[allocator]`, and the elements. Using the view "simple" shows only the elements, with no other items present. Both the SIMD and the non-SIMD implementations are viewable through the Natvis framework. + +Iterators are displayed similarly to their standard counterparts. An iterator is displayed as though it were the element that it points to. An end iterator is simply displayed as `\{ end iterator }`. From 39d86cb896cb4bb5e6a9edfe2a2ac83ca829cd60 Mon Sep 17 00:00:00 2001 From: Braden Ganetsky Date: Sun, 2 Jun 2024 11:27:15 -0500 Subject: [PATCH 11/11] Display foa stats in natvis if applicable --- extra/boost_unordered.natvis | 69 ++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/extra/boost_unordered.natvis b/extra/boost_unordered.natvis index e0f5bc46..d4dbc186 100644 --- a/extra/boost_unordered.natvis +++ b/extra/boost_unordered.natvis @@ -8,7 +8,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - + @@ -20,7 +20,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - + hash(active_idx()) key_eq(active_idx()) @@ -159,6 +159,69 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + + + stats + + insertion + successful_lookup + unsuccessful_lookup + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ count = {n} }} + + n + + {{ average = {average(0)} }} + + average(0) + variance(0) + deviation(0) + + + + {{ average = {average(1)} }} + + average(1) + variance(1) + deviation(1) + + + + + @@ -189,6 +252,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + cstats @@ -233,6 +297,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + cstats