From 2e152707c1266df3c39c60cde5f9db6a40221c9b Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Fri, 4 Jun 2021 07:57:04 +0000 Subject: - Add benchmark for hashtable reconstruction. - Optimize by not initializing hash_node._node char array. - Also skip reconstruction, if it is in initial state. --- vespalib/src/tests/stllike/hashtable_test.cpp | 21 +++++++++++++++++++++ vespalib/src/vespa/vespalib/stllike/hashtable.h | 4 +++- vespalib/src/vespa/vespalib/stllike/hashtable.hpp | 2 ++ 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'vespalib') diff --git a/vespalib/src/tests/stllike/hashtable_test.cpp b/vespalib/src/tests/stllike/hashtable_test.cpp index cbd8b28d9a8..5f6f1601c84 100644 --- a/vespalib/src/tests/stllike/hashtable_test.cpp +++ b/vespalib/src/tests/stllike/hashtable_test.cpp @@ -134,6 +134,27 @@ TEST("require that hashtable> can be copied") { EXPECT_EQUAL(6, (*table.find(2))[2]); } +/** + * Test to profile destruction and recreation of hash map. + * It revealed some unexpected behaviour. Results with 10k iterations on 2018 macbook pro 2.6 Ghz i7 + * 1 - previous - 14.7s hash_node() : _node(), _next(invalid) {} + * 2 - test - 6.6s hash_node() : _next(invalid) { memset(_node, 0, sizeof(node)); } + * 3 - current - 2.3s hash_node() : _next(invalid) {} + */ +TEST("benchmark clear") { + vespalib::hash_map m(1000000); + constexpr size_t NUM_ITER = 10; // Set to 1k-10k to get measurable numbers 10k ~= 2.3s + for (size_t i(0); i < NUM_ITER; i++) { + m[46] = 17; + EXPECT_FALSE(m.empty()); + EXPECT_EQUAL(1u, m.size()); + EXPECT_EQUAL(1048576u, m.capacity()); + m.clear(); + EXPECT_TRUE(m.empty()); + EXPECT_EQUAL(1048576u, m.capacity()); + } +} + } // namespace TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/vespalib/src/vespa/vespalib/stllike/hashtable.h b/vespalib/src/vespa/vespalib/stllike/hashtable.h index b94672aaa06..ede18f89dc2 100644 --- a/vespalib/src/vespa/vespalib/stllike/hashtable.h +++ b/vespalib/src/vespa/vespalib/stllike/hashtable.h @@ -102,7 +102,9 @@ class hash_node { public: using next_t=hashtable_base::next_t; enum {npos=-1u, invalid=-2u}; - hash_node() : _node(), _next(invalid) {} + hash_node() + : _next(invalid) + {} hash_node(const V & node, next_t next=npos) : _next(next) { diff --git a/vespalib/src/vespa/vespalib/stllike/hashtable.hpp b/vespalib/src/vespa/vespalib/stllike/hashtable.hpp index d80113a8f55..494dc223f5b 100644 --- a/vespalib/src/vespa/vespalib/stllike/hashtable.hpp +++ b/vespalib/src/vespa/vespalib/stllike/hashtable.hpp @@ -146,6 +146,8 @@ hashtable::erase(const Key & key template< typename Key, typename Value, typename Hash, typename Equal, typename KeyExtract, typename Modulator > void hashtable::clear() { + if (_count == 0) return; // Already empty and properly initialized + _nodes.clear(); _count = 0; _nodes.resize(getTableSize()); -- cgit v1.2.3