[libcxx] r274423 - Improve performance of unordered_set<uint32_t>::find by 45%. Add benchmarks.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 1 22:19:59 PDT 2016


Author: ericwf
Date: Sat Jul  2 00:19:59 2016
New Revision: 274423

URL: http://llvm.org/viewvc/llvm-project?rev=274423&view=rev
Log:
Improve performance of unordered_set<uint32_t>::find by 45%. Add benchmarks.

This patch improves the performance of unordered_set's find by 45% when
the value exists within the set. __hash_tables find method
needs to check if it's reached the end of the bucket by constraining the
hash of the current node and checking it against the bucket index. However
constraining the hash is an expensive operations and it can be avoided if the
two unconstrained hashes are equal. This patch applies that optimization.

This patch also adds a top level directory called benchmarks. 'benchmarks/'
is intended to store any/all benchmarks written for the standard library.
Currently nothing is done with files under 'benchmarks/' but I would like
to move towards introducing a formal format and test runner.

Added:
    libcxx/trunk/benchmarks/
    libcxx/trunk/benchmarks/set_find.pass.cpp
Modified:
    libcxx/trunk/include/__hash_table

Added: libcxx/trunk/benchmarks/set_find.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/benchmarks/set_find.pass.cpp?rev=274423&view=auto
==============================================================================
--- libcxx/trunk/benchmarks/set_find.pass.cpp (added)
+++ libcxx/trunk/benchmarks/set_find.pass.cpp Sat Jul  2 00:19:59 2016
@@ -0,0 +1,29 @@
+#include <unordered_set>
+#include <vector>
+#include <cstdint>
+
+#include "benchmark/benchmark_api.h"
+
+template <class IntT>
+std::vector<IntT> getInputs(size_t N) {
+    std::vector<IntT> inputs;
+    for (size_t i=0; i < N; ++i) {
+        inputs.push_back(i);
+    }
+    return inputs;
+}
+
+template <class Container, class Inputs>
+void BM_SetLookup(benchmark::State& st, Container c, Inputs const& in) {
+    c.insert(in.begin(), in.end());
+    const auto end = in.end();
+    while (st.KeepRunning()) {
+        for (auto it = in.begin(); it != end; ++it) {
+            benchmark::DoNotOptimize(c.find(*it++));
+        }
+    }
+}
+BENCHMARK_CAPTURE(BM_SetLookup, uint32_lookup,
+    std::unordered_set<uint32_t>{}, getInputs<uint32_t>(1024));
+
+BENCHMARK_MAIN()

Modified: libcxx/trunk/include/__hash_table
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__hash_table?rev=274423&r1=274422&r2=274423&view=diff
==============================================================================
--- libcxx/trunk/include/__hash_table (original)
+++ libcxx/trunk/include/__hash_table Sat Jul  2 00:19:59 2016
@@ -2201,7 +2201,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>
         if (__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_)
             {
                 if (key_eq()(__nd->__value_, __k))
@@ -2230,7 +2231,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>
         if (__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_)
             {
                 if (key_eq()(__nd->__value_, __k))




More information about the cfe-commits mailing list