Merge pull request #247 from boostorg/feature/stats

Feature/stats
This commit is contained in:
joaquintides
2024-05-08 17:19:12 +02:00
committed by GitHub
26 changed files with 1653 additions and 16 deletions
+1
View File
@@ -9,6 +9,7 @@
== Release 1.86.0
* Added container `pmr` aliases when header `<memory_resource>` 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`.
== Release 1.85.0
+49
View File
@@ -50,6 +50,8 @@ namespace boost {
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using stats = xref:stats_stats_type[__stats-type__]; // if statistics are xref:concurrent_flat_map_boost_unordered_enable_stats[enabled]
// constants
static constexpr size_type xref:#concurrent_flat_map_constants[bulk_visit_size] = _implementation-defined_;
@@ -228,6 +230,10 @@ namespace boost {
size_type xref:#concurrent_flat_map_max_load[max_load]() const noexcept;
void xref:#concurrent_flat_map_rehash[rehash](size_type n);
void xref:#concurrent_flat_map_reserve[reserve](size_type n);
// statistics (if xref:concurrent_flat_map_boost_unordered_enable_stats[enabled])
stats xref:#concurrent_flat_map_get_stats[get_stats]() const;
void xref:#concurrent_flat_map_reset_stats[reset_stats]() noexcept;
};
// Deduction Guides
@@ -407,6 +413,15 @@ a function visiting elements of `m`) are detected and signalled through `BOOST_A
When run-time speed is a concern, the feature can be disabled by globally defining
this macro.
---
==== `BOOST_UNORDERED_ENABLE_STATS`
Globally define this macro to enable xref:#stats[statistics calculation] for the table. Note
that this option decreases the overall performance of many operations.
---
=== Constants
```cpp
@@ -488,6 +503,8 @@ concurrent_flat_map(concurrent_flat_map&& other);
The move constructor. The internal bucket array of `other` is transferred directly to the new table.
The hash function, predicate and allocator are moved-constructed from `other`.
If statistics are xref:concurrent_flat_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` and calls `other.reset_stats()`.
[horizontal]
Concurrency:;; Blocking on `other`.
@@ -536,6 +553,9 @@ concurrent_flat_map(concurrent_flat_map&& other, Allocator const& a);
If `a == other.get_allocator()`, the elements of `other` are transferred directly to the new table;
otherwise, elements are moved-constructed from those of `other`. The hash function and predicate are moved-constructed
from `other`, and the allocator is copy-constructed from `a`.
If statistics are xref:concurrent_flat_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff `a == other.get_allocator()`,
and always calls `other.reset_stats()`.
[horizontal]
Concurrency:;; Blocking on `other`.
@@ -551,6 +571,8 @@ concurrent_flat_map(unordered_flat_map<Key, T, Hash, Pred, Allocator>&& other);
Move construction from a xref:#unordered_flat_map[`unordered_flat_map`].
The internal bucket array of `other` is transferred directly to the new container.
The hash function, predicate and allocator are moved-constructed from `other`.
If statistics are xref:concurrent_flat_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` and calls `other.reset_stats()`.
[horizontal]
Complexity:;; O(`bucket_count()`)
@@ -709,6 +731,9 @@ The move assignment operator. Destroys previously existing elements, swaps the h
and move-assigns the allocator from `other` if `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`.
If at this point the allocator is equal to `other.get_allocator()`, the internal bucket array of `other` is transferred directly to `*this`;
otherwise, inserts move-constructed copies of the elements of `other`.
If statistics are xref:concurrent_flat_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff the final allocator is equal to `other.get_allocator()`,
and always calls `other.reset_stats()`.
[horizontal]
Concurrency:;; Blocking on `*this` and `other`.
@@ -1480,6 +1505,30 @@ Concurrency:;; Blocking on `*this`.
---
=== Statistics
==== get_stats
```c++
stats get_stats() const;
```
[horizontal]
Returns:;; A statistical description of the insertion and lookup operations performed by the table so far.
Notes:;; Only available if xref:stats[statistics calculation] is xref:concurrent_flat_map_boost_unordered_enable_stats[enabled].
---
==== reset_stats
```c++
void reset_stats() noexcept;
```
[horizontal]
Effects:;; Sets to zero the internal statistics kept by the table.
Notes:;; Only available if xref:stats[statistics calculation] is xref:concurrent_flat_map_boost_unordered_enable_stats[enabled].
---
=== Deduction Guides
A deduction guide will not participate in overload resolution if any of the following are true:
+49
View File
@@ -45,6 +45,8 @@ namespace boost {
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using stats = xref:stats_stats_type[__stats-type__]; // if statistics are xref:concurrent_flat_set_boost_unordered_enable_stats[enabled]
// constants
static constexpr size_type xref:#concurrent_flat_set_constants[bulk_visit_size] = _implementation-defined_;
@@ -188,6 +190,10 @@ namespace boost {
size_type xref:#concurrent_flat_set_max_load[max_load]() const noexcept;
void xref:#concurrent_flat_set_rehash[rehash](size_type n);
void xref:#concurrent_flat_set_reserve[reserve](size_type n);
// statistics (if xref:concurrent_flat_set_boost_unordered_enable_stats[enabled])
stats xref:#concurrent_flat_set_get_stats[get_stats]() const;
void xref:#concurrent_flat_set_reset_stats[reset_stats]() noexcept;
};
// Deduction Guides
@@ -358,6 +364,15 @@ a function visiting elements of `m`) are detected and signalled through `BOOST_A
When run-time speed is a concern, the feature can be disabled by globally defining
this macro.
---
==== `BOOST_UNORDERED_ENABLE_STATS`
Globally define this macro to enable xref:#stats[statistics calculation] for the table. Note
that this option decreases the overall performance of many operations.
---
=== Constants
```cpp
@@ -439,6 +454,8 @@ concurrent_flat_set(concurrent_flat_set&& other);
The move constructor. The internal bucket array of `other` is transferred directly to the new table.
The hash function, predicate and allocator are moved-constructed from `other`.
If statistics are xref:concurrent_flat_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` and calls `other.reset_stats()`.
[horizontal]
Concurrency:;; Blocking on `other`.
@@ -487,6 +504,9 @@ concurrent_flat_set(concurrent_flat_set&& other, Allocator const& a);
If `a == other.get_allocator()`, the elements of `other` are transferred directly to the new table;
otherwise, elements are moved-constructed from those of `other`. The hash function and predicate are moved-constructed
from `other`, and the allocator is copy-constructed from `a`.
If statistics are xref:concurrent_flat_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff `a == other.get_allocator()`,
and always calls `other.reset_stats()`.
[horizontal]
Concurrency:;; Blocking on `other`.
@@ -502,6 +522,8 @@ concurrent_flat_set(unordered_flat_set<Key, Hash, Pred, Allocator>&& other);
Move construction from a xref:#unordered_flat_set[`unordered_flat_set`].
The internal bucket array of `other` is transferred directly to the new container.
The hash function, predicate and allocator are moved-constructed from `other`.
If statistics are xref:concurrent_flat_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` and calls `other.reset_stats()`.
[horizontal]
Complexity:;; O(`bucket_count()`)
@@ -659,6 +681,9 @@ The move assignment operator. Destroys previously existing elements, swaps the h
and move-assigns the allocator from `other` if `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`.
If at this point the allocator is equal to `other.get_allocator()`, the internal bucket array of `other` is transferred directly to `*this`;
otherwise, inserts move-constructed copies of the elements of `other`.
If statistics are xref:concurrent_flat_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff the final allocator is equal to `other.get_allocator()`,
and always calls `other.reset_stats()`.
[horizontal]
Concurrency:;; Blocking on `*this` and `other`.
@@ -1316,6 +1341,30 @@ Concurrency:;; Blocking on `*this`.
---
=== Statistics
==== get_stats
```c++
stats get_stats() const;
```
[horizontal]
Returns:;; A statistical description of the insertion and lookup operations performed by the table so far.
Notes:;; Only available if xref:stats[statistics calculation] is xref:concurrent_flat_set_boost_unordered_enable_stats[enabled].
---
==== reset_stats
```c++
void reset_stats() noexcept;
```
[horizontal]
Effects:;; Sets to zero the internal statistics kept by the table.
Notes:;; Only available if xref:stats[statistics calculation] is xref:concurrent_flat_set_boost_unordered_enable_stats[enabled].
---
=== Deduction Guides
A deduction guide will not participate in overload resolution if any of the following are true:
+145
View File
@@ -0,0 +1,145 @@
[#hash_quality]
= Hash Quality
:idprefix: hash_quality_
In order to work properly, hash tables require that the supplied hash function
be of __good quality__, roughly meaning that it uses its `std::size_t` output
space as uniformly as possible, much like a random number generator would do
—except, of course, that the value of a hash function is not random but strictly determined
by its input argument.
Closed-addressing containers in Boost.Unordered are fairly robust against
hash functions with less-than-ideal quality, but open-addressing and concurrent
containers are much more sensitive to this factor, and their performance can
degrade dramatically if the hash function is not appropriate. In general, if
you're using functions provided by or generated with link:../../../container_hash/index.html[Boost.Hash^],
the quality will be adequate, but you have to be careful when using alternative
hash algorithms.
The rest of this section applies only to open-addressing and concurrent containers.
== Hash Post-mixing and the Avalanching Property
Even if your supplied hash function does not conform to the uniform behavior
required by open addressing, chances are that
the performance of Boost.Unordered containers will be acceptable, because the library
executes an internal __post-mixing__ step that improves the statistical
properties of the calculated hash values. This comes with an extra computational
cost; if you'd like to opt out of post-mixing, annotate your hash function as
follows:
[source,c++]
----
struct my_string_hash_function
{
using is_avalanching = void; // instruct Boost.Unordered to not use post-mixing
std::size_t operator()(const std::string& x) const
{
...
}
};
----
By setting the
xref:#hash_traits_hash_is_avalanching[hash_is_avalanching] trait, we inform Boost.Unordered
that `my_string_hash_function` is of sufficient quality to be used directly without
any post-mixing safety net. This comes at the risk of degraded performance in the
cases where the hash function is not as well-behaved as we've declared.
== Container Statistics
If we globally define the macro `BOOST_UNORDERED_ENABLE_STATS`, open-addressing and
concurrent containers will calculate some internal statistics directly correlated to the
quality of the hash function:
[source,c++]
----
#define BOOST_UNORDERED_ENABLE_STATS
#include <boost/unordered/unordered_map.hpp>
...
int main()
{
boost::unordered_flat_map<std::string, int, my_string_hash> m;
... // use m
auto stats = m.get_stats();
... // inspect stats
}
----
The `stats` object provides the following information:
[source,subs=+quotes]
----
stats
.insertion // *Insertion operations*
.count // Number of operations
.probe_length // Probe length per operation
.average
.variance
.deviation
.successful_lookup // *Lookup operations (element found)*
.count // Number of operations
.probe_length // Probe length per operation
.average
.variance
.deviation
.num_comparisons // Elements compared per operation
.average
.variance
.deviation
.unsuccessful_lookup // *Lookup operations (element not found)*
.count // Number of operations
.probe_length // Probe length per operation
.average
.variance
.deviation
.num_comparisons // Elements compared per operation
.average
.variance
.deviation
----
Statistics for three internal operations are maintained: insertions (without considering
the previous lookup to determine that the key is not present yet), successful lookups,
and unsuccessful lookups (including those issued internally when inserting elements).
_Probe length_ is the number of
xref:#structures_open_addressing_containers[bucket groups] accessed per operation.
If the hash function behaves properly:
* Average probe lengths should be close to 1.0.
* The average number of comparisons per successful lookup should be close to 1.0 (that is,
just the element found is checked).
* The average number of comparisons per unsuccessful lookup should be close to 0.0.
A link:../../benchmark/string_stats.cpp[example^] is provided that displays container
statistics for `boost::hash<std::string>`, an implementation of the
https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash[FNV-1a hash^]
and two ill-behaved custom hash functions that have been incorrectly marked as avalanching:
[listing]
----
boost::unordered_flat_map: 319 ms
insertion: probe length 1.08771
successful lookup: probe length 1.06206, num comparisons 1.02121
unsuccessful lookup: probe length 1.12301, num comparisons 0.0388251
boost::unordered_flat_map, FNV-1a: 301 ms
insertion: probe length 1.09567
successful lookup: probe length 1.06202, num comparisons 1.0227
unsuccessful lookup: probe length 1.12195, num comparisons 0.040527
boost::unordered_flat_map, slightly_bad_hash: 654 ms
insertion: probe length 1.03443
successful lookup: probe length 1.04137, num comparisons 6.22152
unsuccessful lookup: probe length 1.29334, num comparisons 11.0335
boost::unordered_flat_map, bad_hash: 12216 ms
insertion: probe length 699.218
successful lookup: probe length 590.183, num comparisons 43.4886
unsuccessful lookup: probe length 1361.65, num comparisons 75.238
----
+1 -1
View File
@@ -102,7 +102,7 @@ and *high* and *low* are the upper and lower halves of an extended word, respect
In 64-bit architectures, _C_ is the integer part of 2^64^&#8725;https://en.wikipedia.org/wiki/Golden_ratio[_&phi;_],
whereas in 32 bits _C_ = 0xE817FB2Du has been obtained from https://arxiv.org/abs/2001.05304[Steele and Vigna (2021)^].
When using a hash function directly suitable for open addressing, post-mixing can be opted out by via a dedicated <<hash_traits_hash_is_avalanching,`hash_is_avalanching`>>trait.
When using a hash function directly suitable for open addressing, post-mixing can be opted out of via a dedicated <<hash_traits_hash_is_avalanching,`hash_is_avalanching`>>trait.
`boost::hash` specializations for string types are marked as avalanching.
=== Platform Interoperability
+1
View File
@@ -6,6 +6,7 @@ include::unordered_multimap.adoc[]
include::unordered_set.adoc[]
include::unordered_multiset.adoc[]
include::hash_traits.adoc[]
include::stats.adoc[]
include::unordered_flat_map.adoc[]
include::unordered_flat_set.adoc[]
include::unordered_node_map.adoc[]
+71
View File
@@ -0,0 +1,71 @@
[#stats]
== Statistics
:idprefix: stats_
Open-addressing and concurrent containers can be configured to keep running statistics
of some internal operations affected by the quality of the supplied hash function.
=== Synopsis
[listing,subs="+macros,+quotes"]
-----
struct xref:#stats_stats_summary_type[__stats-summary-type__]
{
double average;
double variance;
double deviation;
};
struct xref:#stats_insertion_stats_type[__insertion-stats-type__]
{
std::size_t count;
xref:#stats_stats_summary_type[__stats-summary-type__] probe_length;
};
struct xref:stats_lookup_stats_type[__lookup-stats-type__]
{
std::size_t count;
xref:#stats_stats_summary_type[__stats-summary-type__] probe_length;
xref:#stats_stats_summary_type[__stats-summary-type__] num_comparisons;
};
struct xref:stats_stats_type[__stats-type__]
{
xref:#stats_insertion_stats_type[__insertion-stats-type__] insertion;
xref:stats_lookup_stats_type[__lookup-stats-type__] successful_lookup,
unsuccessful_lookup;
};
-----
==== __stats-summary-type__
Provides the average value, variance and standard deviation of a sequence of numerical values.
==== __insertion-stats-type__
Provides the number of insertion operations performed by a container and
statistics on the associated __probe length__ (number of
xref:#structures_open_addressing_containers[bucket groups] accessed per operation).
==== __lookup-stats-type__
For successful (element found) or unsuccessful (not found) lookup,
provides the number of operations performed by a container and
statistics on the associated __probe length__ (number of
xref:#structures_open_addressing_containers[bucket groups] accessed)
and number of element comparisons per operation.
==== __stats-type__
Provides statistics on insertion, successful and unsuccessful lookups performed by a container.
If the supplied hash function has good quality, then:
* Average probe lenghts should be close to 1.0.
* For successful lookups, the average number of element comparisons should be close to 1.0.
* For unsuccessful lookups, the average number of element comparisons should be close to 0.0.
These statistics can be used to determine if a given hash function
can be marked as xref:hash_traits_hash_is_avalanching[__avalanching__].
---
+51
View File
@@ -58,6 +58,8 @@ namespace boost {
using iterator = _implementation-defined_;
using const_iterator = _implementation-defined_;
using stats = xref:stats_stats_type[__stats-type__]; // if statistics are xref:unordered_flat_map_boost_unordered_enable_stats[enabled]
// construct/copy/destroy
xref:#unordered_flat_map_default_constructor[unordered_flat_map]();
explicit xref:#unordered_flat_map_bucket_count_constructor[unordered_flat_map](size_type n,
@@ -214,6 +216,10 @@ namespace boost {
size_type xref:#unordered_flat_map_max_load[max_load]() const noexcept;
void xref:#unordered_flat_map_rehash[rehash](size_type n);
void xref:#unordered_flat_map_reserve[reserve](size_type n);
// statistics (if xref:unordered_flat_map_boost_unordered_enable_stats[enabled])
stats xref:#unordered_flat_map_get_stats[get_stats]() const;
void xref:#unordered_flat_map_reset_stats[reset_stats]() noexcept;
};
// Deduction Guides
@@ -343,6 +349,15 @@ at the expense of extra computational cost.
---
=== Configuration Macros
==== `BOOST_UNORDERED_ENABLE_STATS`
Globally define this macro to enable xref:#stats[statistics calculation] for the container. Note
that this option decreases the overall performance of many operations.
---
=== Typedefs
[source,c++,subs=+quotes]
@@ -439,6 +454,8 @@ unordered_flat_map(unordered_flat_map&& other);
The move constructor. The internal bucket array of `other` is transferred directly to the new container.
The hash function, predicate and allocator are moved-constructed from `other`.
If statistics are xref:unordered_flat_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` and calls `other.reset_stats()`.
---
@@ -481,6 +498,9 @@ unordered_flat_map(unordered_flat_map&& other, Allocator const& a);
If `a == other.get_allocator()`, the elements of `other` are transferred directly to the new container;
otherwise, elements are moved-constructed from those of `other`. The hash function and predicate are moved-constructed
from `other`, and the allocator is copy-constructed from `a`.
If statistics are xref:unordered_flat_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff `a == other.get_allocator()`,
and always calls `other.reset_stats()`.
---
@@ -493,6 +513,8 @@ unordered_flat_map(concurrent_flat_map<Key, T, Hash, Pred, Allocator>&& other);
Move construction from a xref:#concurrent_flat_map[`concurrent_flat_map`].
The internal bucket array of `other` is transferred directly to the new container.
The hash function, predicate and allocator are moved-constructed from `other`.
If statistics are xref:unordered_flat_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` and calls `other.reset_stats()`.
[horizontal]
Complexity:;; Constant time.
@@ -651,6 +673,9 @@ The move assignment operator. Destroys previously existing elements, swaps the h
and move-assigns the allocator from `other` if `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`.
If at this point the allocator is equal to `other.get_allocator()`, the internal bucket array of `other` is transferred directly to the new container;
otherwise, inserts move-constructed copies of the elements of `other`.
If statistics are xref:unordered_flat_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff the final allocator is equal to `other.get_allocator()`,
and always calls `other.reset_stats()`.
---
@@ -1364,6 +1389,32 @@ Invalidates iterators, pointers and references, and changes the order of element
[horizontal]
Throws:;; The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
---
=== Statistics
==== get_stats
```c++
stats get_stats() const;
```
[horizontal]
Returns:;; A statistical description of the insertion and lookup operations performed by the container so far.
Notes:;; Only available if xref:stats[statistics calculation] is xref:unordered_flat_map_boost_unordered_enable_stats[enabled].
---
==== reset_stats
```c++
void reset_stats() noexcept;
```
[horizontal]
Effects:;; Sets to zero the internal statistics kept by the container.
Notes:;; Only available if xref:stats[statistics calculation] is xref:unordered_flat_map_boost_unordered_enable_stats[enabled].
---
=== Deduction Guides
A deduction guide will not participate in overload resolution if any of the following are true:
+51
View File
@@ -53,6 +53,8 @@ namespace boost {
using iterator = _implementation-defined_;
using const_iterator = _implementation-defined_;
using stats = xref:stats_stats_type[__stats-type__]; // if statistics are xref:unordered_flat_set_boost_unordered_enable_stats[enabled]
// construct/copy/destroy
xref:#unordered_flat_set_default_constructor[unordered_flat_set]();
explicit xref:#unordered_flat_set_bucket_count_constructor[unordered_flat_set](size_type n,
@@ -172,6 +174,10 @@ namespace boost {
size_type xref:#unordered_flat_set_max_load[max_load]() const noexcept;
void xref:#unordered_flat_set_rehash[rehash](size_type n);
void xref:#unordered_flat_set_reserve[reserve](size_type n);
// statistics (if xref:unordered_flat_set_boost_unordered_enable_stats[enabled])
stats xref:#unordered_flat_set_get_stats[get_stats]() const;
void xref:#unordered_flat_set_reset_stats[reset_stats]() noexcept;
};
// Deduction Guides
@@ -291,6 +297,15 @@ at the expense of extra computational cost.
---
=== Configuration Macros
==== `BOOST_UNORDERED_ENABLE_STATS`
Globally define this macro to enable xref:#stats[statistics calculation] for the container. Note
that this option decreases the overall performance of many operations.
---
=== Typedefs
[source,c++,subs=+quotes]
@@ -387,6 +402,8 @@ unordered_flat_set(unordered_flat_set&& other);
The move constructor. The internal bucket array of `other` is transferred directly to the new container.
The hash function, predicate and allocator are moved-constructed from `other`.
If statistics are xref:unordered_flat_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` and calls `other.reset_stats()`.
---
@@ -429,6 +446,9 @@ unordered_flat_set(unordered_flat_set&& other, Allocator const& a);
If `a == other.get_allocator()`, the elements of `other` are transferred directly to the new container;
otherwise, elements are moved-constructed from those of `other`. The hash function and predicate are moved-constructed
from `other`, and the allocator is copy-constructed from `a`.
If statistics are xref:unordered_flat_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff `a == other.get_allocator()`,
and always calls `other.reset_stats()`.
---
@@ -441,6 +461,8 @@ unordered_flat_set(concurrent_flat_set<Key, Hash, Pred, Allocator>&& other);
Move construction from a xref:#concurrent_flat_set[`concurrent_flat_set`].
The internal bucket array of `other` is transferred directly to the new container.
The hash function, predicate and allocator are moved-constructed from `other`.
If statistics are xref:unordered_flat_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` and calls `other.reset_stats()`.
[horizontal]
Complexity:;; Constant time.
@@ -599,6 +621,9 @@ The move assignment operator. Destroys previously existing elements, swaps the h
and move-assigns the allocator from `other` if `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`.
If at this point the allocator is equal to `other.get_allocator()`, the internal bucket array of `other` is transferred directly to the new container;
otherwise, inserts move-constructed copies of the elements of `other`.
If statistics are xref:unordered_flat_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff the final allocator is equal to `other.get_allocator()`,
and always calls `other.reset_stats()`.
---
@@ -1137,6 +1162,32 @@ Invalidates iterators, pointers and references, and changes the order of element
[horizontal]
Throws:;; The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
---
=== Statistics
==== get_stats
```c++
stats get_stats() const;
```
[horizontal]
Returns:;; A statistical description of the insertion and lookup operations performed by the container so far.
Notes:;; Only available if xref:stats[statistics calculation] is xref:unordered_flat_set_boost_unordered_enable_stats[enabled].
---
==== reset_stats
```c++
void reset_stats() noexcept;
```
[horizontal]
Effects:;; Sets to zero the internal statistics kept by the container.
Notes:;; Only available if xref:stats[statistics calculation] is xref:unordered_flat_set_boost_unordered_enable_stats[enabled].
---
=== Deduction Guides
A deduction guide will not participate in overload resolution if any of the following are true:
+49
View File
@@ -57,6 +57,8 @@ namespace boost {
using node_type = _implementation-defined_;
using insert_return_type = _implementation-defined_;
using stats = xref:stats_stats_type[__stats-type__]; // if statistics are xref:unordered_node_map_boost_unordered_enable_stats[enabled]
// construct/copy/destroy
xref:#unordered_node_map_default_constructor[unordered_node_map]();
explicit xref:#unordered_node_map_bucket_count_constructor[unordered_node_map](size_type n,
@@ -217,6 +219,10 @@ namespace boost {
size_type xref:#unordered_node_map_max_load[max_load]() const noexcept;
void xref:#unordered_node_map_rehash[rehash](size_type n);
void xref:#unordered_node_map_reserve[reserve](size_type n);
// statistics (if xref:unordered_node_map_boost_unordered_enable_stats[enabled])
stats xref:#unordered_node_map_get_stats[get_stats]() const;
void xref:#unordered_node_map_reset_stats[reset_stats]() noexcept;
};
// Deduction Guides
@@ -345,6 +351,15 @@ at the expense of extra computational cost.
---
=== Configuration Macros
==== `BOOST_UNORDERED_ENABLE_STATS`
Globally define this macro to enable xref:#stats[statistics calculation] for the container. Note
that this option decreases the overall performance of many operations.
---
=== Typedefs
[source,c++,subs=+quotes]
@@ -472,6 +487,8 @@ unordered_node_map(unordered_node_map&& other);
The move constructor. The internal bucket array of `other` is transferred directly to the new container.
The hash function, predicate and allocator are moved-constructed from `other`.
If statistics are xref:unordered_node_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` and calls `other.reset_stats()`.
---
@@ -514,6 +531,9 @@ unordered_node_map(unordered_node_map&& other, Allocator const& a);
If `a == other.get_allocator()`, the element nodes of `other` are transferred directly to the new container;
otherwise, elements are moved-constructed from those of `other`. The hash function and predicate are moved-constructed
from `other`, and the allocator is copy-constructed from `a`.
If statistics are xref:unordered_node_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff `a == other.get_allocator()`,
and always calls `other.reset_stats()`.
---
@@ -668,6 +688,9 @@ The move assignment operator. Destroys previously existing elements, swaps the h
and move-assigns the allocator from `other` if `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`.
If at this point the allocator is equal to `other.get_allocator()`, the internal bucket array of `other` is transferred directly to the new container;
otherwise, inserts move-constructed copies of the elements of `other`.
If statistics are xref:unordered_node_map_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff the final allocator is equal to `other.get_allocator()`,
and always calls `other.reset_stats()`.
---
@@ -1451,6 +1474,32 @@ Invalidates iterators and changes the order of elements.
[horizontal]
Throws:;; The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
---
=== Statistics
==== get_stats
```c++
stats get_stats() const;
```
[horizontal]
Returns:;; A statistical description of the insertion and lookup operations performed by the container so far.
Notes:;; Only available if xref:stats[statistics calculation] is xref:unordered_node_map_boost_unordered_enable_stats[enabled].
---
==== reset_stats
```c++
void reset_stats() noexcept;
```
[horizontal]
Effects:;; Sets to zero the internal statistics kept by the container.
Notes:;; Only available if xref:stats[statistics calculation] is xref:unordered_node_map_boost_unordered_enable_stats[enabled].
---
=== Deduction Guides
A deduction guide will not participate in overload resolution if any of the following are true:
+49
View File
@@ -52,6 +52,8 @@ namespace boost {
using node_type = _implementation-defined_;
using insert_return_type = _implementation-defined_;
using stats = xref:stats_stats_type[__stats-type__]; // if statistics are xref:unordered_node_set_boost_unordered_enable_stats[enabled]
// construct/copy/destroy
xref:#unordered_node_set_default_constructor[unordered_node_set]();
explicit xref:#unordered_node_set_bucket_count_constructor[unordered_node_set](size_type n,
@@ -176,6 +178,10 @@ namespace boost {
size_type xref:#unordered_node_set_max_load[max_load]() const noexcept;
void xref:#unordered_node_set_rehash[rehash](size_type n);
void xref:#unordered_node_set_reserve[reserve](size_type n);
// statistics (if xref:unordered_node_set_boost_unordered_enable_stats[enabled])
stats xref:#unordered_node_set_get_stats[get_stats]() const;
void xref:#unordered_node_set_reset_stats[reset_stats]() noexcept;
};
// Deduction Guides
@@ -294,6 +300,15 @@ at the expense of extra computational cost.
---
=== Configuration Macros
==== `BOOST_UNORDERED_ENABLE_STATS`
Globally define this macro to enable xref:#stats[statistics calculation] for the container. Note
that this option decreases the overall performance of many operations.
---
=== Typedefs
[source,c++,subs=+quotes]
@@ -424,6 +439,8 @@ unordered_node_set(unordered_node_set&& other);
The move constructor. The internal bucket array of `other` is transferred directly to the new container.
The hash function, predicate and allocator are moved-constructed from `other`.
If statistics are xref:unordered_node_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` and calls `other.reset_stats()`.
---
@@ -466,6 +483,9 @@ unordered_node_set(unordered_node_set&& other, Allocator const& a);
If `a == other.get_allocator()`, the element nodes of `other` are transferred directly to the new container;
otherwise, elements are moved-constructed from those of `other`. The hash function and predicate are moved-constructed
from `other`, and the allocator is copy-constructed from `a`.
If statistics are xref:unordered_node_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff `a == other.get_allocator()`,
and always calls `other.reset_stats()`.
---
@@ -620,6 +640,9 @@ The move assignment operator. Destroys previously existing elements, swaps the h
and move-assigns the allocator from `other` if `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`.
If at this point the allocator is equal to `other.get_allocator()`, the internal bucket array of `other` is transferred directly to the new container;
otherwise, inserts move-constructed copies of the elements of `other`.
If statistics are xref:unordered_node_set_boost_unordered_enable_stats[enabled],
transfers the internal statistical information from `other` iff the final allocator is equal to `other.get_allocator()`,
and always calls `other.reset_stats()`.
---
@@ -1228,6 +1251,32 @@ Invalidates iterators and changes the order of elements.
[horizontal]
Throws:;; The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
---
=== Statistics
==== get_stats
```c++
stats get_stats() const;
```
[horizontal]
Returns:;; A statistical description of the insertion and lookup operations performed by the container so far.
Notes:;; Only available if xref:stats[statistics calculation] is xref:unordered_node_set_boost_unordered_enable_stats[enabled].
---
==== reset_stats
```c++
void reset_stats() noexcept;
```
[horizontal]
Effects:;; Sets to zero the internal statistics kept by the container.
Notes:;; Only available if xref:stats[statistics calculation] is xref:unordered_node_set_boost_unordered_enable_stats[enabled].
---
=== Deduction Guides
A deduction guide will not participate in overload resolution if any of the following are true: