Browse Source

Check for unconstrained hash equality before constrained hash equality.

This patch implements a simple optimization in __hash_table::find. When iterating
the found bucket we only constrain the bucket elements hash if it doesn't
already match the unconstrained hash of the specified key. This prevent
the performance of an expensive modulo operation.

Since the bucket element almost always matches the key, especially when the
load factor is low, this optimization has large performance impacts. For
a unordered_set<int> of random integers this patch improves the performance of
'find(...)' by 40%.


git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@275734 91177308-0d34-0410-b5e6-96231b3b80d8
Eric Fiselier 9 năm trước cách đây
mục cha
commit
41aafc25c6
1 tập tin đã thay đổi với 3 bổ sung2 xóa
  1. 3 2
      include/__hash_table

+ 3 - 2
include/__hash_table

@@ -2202,7 +2202,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
         if (__nd != nullptr)
         if (__nd != nullptr)
         {
         {
             for (__nd = __nd->__next_; __nd != nullptr &&
             for (__nd = __nd->__next_; __nd != nullptr &&
-                __constrain_hash(__nd->__hash_, __bc) == __chash;
+                (__nd->__hash_ == __hash
+                  || __constrain_hash(__nd->__hash_, __bc) == __chash);
                                                            __nd = __nd->__next_)
                                                            __nd = __nd->__next_)
             {
             {
                 if ((__nd->__hash_ == __hash) && key_eq()(__nd->__value_, __k))
                 if ((__nd->__hash_ == __hash) && key_eq()(__nd->__value_, __k))
@@ -2231,7 +2232,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
         if (__nd != nullptr)
         if (__nd != nullptr)
         {
         {
             for (__nd = __nd->__next_; __nd != nullptr &&
             for (__nd = __nd->__next_; __nd != nullptr &&
-                  __constrain_hash(__nd->__hash_, __bc) == __chash;
+                (__hash == __nd->__hash_ || __constrain_hash(__nd->__hash_, __bc) == __chash);
                                                            __nd = __nd->__next_)
                                                            __nd = __nd->__next_)
             {
             {
                 if ((__nd->__hash_ == __hash) && key_eq()(__nd->__value_, __k))
                 if ((__nd->__hash_ == __hash) && key_eq()(__nd->__value_, __k))