summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2016-07-02 05:19:59 +0000
committerEric Fiselier <eric@efcs.ca>2016-07-02 05:19:59 +0000
commitf977598bb629afeb3f7cf591bd483f21adfab1a7 (patch)
tree99f39b6394216bc7c073ca62380246f31aa0bb84
parent4f905b8daaf9826b91abe30fe8b5c5cd1ee7caa9 (diff)
downloadbcm5719-llvm-f977598bb629afeb3f7cf591bd483f21adfab1a7.tar.gz
bcm5719-llvm-f977598bb629afeb3f7cf591bd483f21adfab1a7.zip
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. llvm-svn: 274423
-rw-r--r--libcxx/benchmarks/set_find.pass.cpp29
-rw-r--r--libcxx/include/__hash_table6
2 files changed, 33 insertions, 2 deletions
diff --git a/libcxx/benchmarks/set_find.pass.cpp b/libcxx/benchmarks/set_find.pass.cpp
new file mode 100644
index 00000000000..32f90266dcc
--- /dev/null
+++ b/libcxx/benchmarks/set_find.pass.cpp
@@ -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()
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 6b93e848d5c..414019aa1fa 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -2201,7 +2201,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
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>::find(const _Key& __k) const
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))
OpenPOWER on IntegriCloud