aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Egge <Tor.Egge@broadpark.no>2021-03-26 10:59:16 +0100
committerTor Egge <Tor.Egge@broadpark.no>2021-03-26 10:59:16 +0100
commit4705dcb8fd738546882adfb39ebce0bf2421ffe1 (patch)
treef02668da987112b071332cc1384d50e9b742464c
parent326d62a79c51ff7332bf8dca205f66862330f453 (diff)
Rename SimpleHashMap to ShardedHashMap.
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enum_store_dictionary.cpp4
-rw-r--r--searchlib/src/vespa/searchlib/attribute/enumstore.cpp4
-rw-r--r--vespalib/CMakeLists.txt2
-rw-r--r--vespalib/src/tests/datastore/sharded_hash_map/CMakeLists.txt9
-rw-r--r--vespalib/src/tests/datastore/sharded_hash_map/sharded_hash_map_test.cpp (renamed from vespalib/src/tests/datastore/simple_hash_map/simple_hash_map_test.cpp)36
-rw-r--r--vespalib/src/tests/datastore/simple_hash_map/CMakeLists.txt9
-rw-r--r--vespalib/src/tests/datastore/unique_store/unique_store_test.cpp4
-rw-r--r--vespalib/src/tests/datastore/unique_store_dictionary/unique_store_dictionary_test.cpp4
-rw-r--r--vespalib/src/vespa/vespalib/datastore/CMakeLists.txt2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/fixed_size_hash_map.cpp16
-rw-r--r--vespalib/src/vespa/vespalib/datastore/fixed_size_hash_map.h6
-rw-r--r--vespalib/src/vespa/vespalib/datastore/sharded_hash_map.cpp168
-rw-r--r--vespalib/src/vespa/vespalib/datastore/sharded_hash_map.h (renamed from vespalib/src/vespa/vespalib/datastore/simple_hash_map.h)16
-rw-r--r--vespalib/src/vespa/vespalib/datastore/simple_hash_map.cpp168
14 files changed, 224 insertions, 224 deletions
diff --git a/searchlib/src/vespa/searchlib/attribute/enum_store_dictionary.cpp b/searchlib/src/vespa/searchlib/attribute/enum_store_dictionary.cpp
index 1d0430cfb63..5a65d4937e4 100644
--- a/searchlib/src/vespa/searchlib/attribute/enum_store_dictionary.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/enum_store_dictionary.cpp
@@ -8,7 +8,7 @@
#include <vespa/vespalib/btree/btreenodeallocator.hpp>
#include <vespa/vespalib/btree/btreeroot.hpp>
#include <vespa/vespalib/datastore/datastore.hpp>
-#include <vespa/vespalib/datastore/simple_hash_map.h>
+#include <vespa/vespalib/datastore/sharded_hash_map.h>
#include <vespa/vespalib/datastore/unique_store_dictionary.hpp>
#include <vespa/searchlib/util/bufferwriter.h>
@@ -355,7 +355,7 @@ template class EnumStoreDictionary<EnumTree>;
template class EnumStoreDictionary<EnumPostingTree>;
-template class EnumStoreDictionary<EnumPostingTree, vespalib::datastore::SimpleHashMap>;
+template class EnumStoreDictionary<EnumPostingTree, vespalib::datastore::ShardedHashMap>;
}
diff --git a/searchlib/src/vespa/searchlib/attribute/enumstore.cpp b/searchlib/src/vespa/searchlib/attribute/enumstore.cpp
index 5beafea0046..5065a4a6cdc 100644
--- a/searchlib/src/vespa/searchlib/attribute/enumstore.cpp
+++ b/searchlib/src/vespa/searchlib/attribute/enumstore.cpp
@@ -1,7 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "enumstore.hpp"
-#include <vespa/vespalib/datastore/simple_hash_map.h>
+#include <vespa/vespalib/datastore/sharded_hash_map.h>
#include <vespa/vespalib/util/rcuvector.hpp>
#include <iomanip>
@@ -51,7 +51,7 @@ make_enum_store_dictionary(IEnumStore &store, bool has_postings, search::Diction
switch (type) {
case search::DictionaryConfig::Type::HASH:
case search::DictionaryConfig::Type::BTREE_AND_HASH:
- return std::make_unique<EnumStoreDictionary<EnumPostingTree, vespalib::datastore::SimpleHashMap>>(store, std::move(compare));
+ return std::make_unique<EnumStoreDictionary<EnumPostingTree, vespalib::datastore::ShardedHashMap>>(store, std::move(compare));
default:
return std::make_unique<EnumStoreDictionary<EnumPostingTree>>(store, std::move(compare));
}
diff --git a/vespalib/CMakeLists.txt b/vespalib/CMakeLists.txt
index 9e06bb152fd..3bdd477fcb6 100644
--- a/vespalib/CMakeLists.txt
+++ b/vespalib/CMakeLists.txt
@@ -43,7 +43,7 @@ vespa_define_module(
src/tests/datastore/buffer_type
src/tests/datastore/datastore
src/tests/datastore/fixed_size_hash_map
- src/tests/datastore/simple_hash_map
+ src/tests/datastore/sharded_hash_map
src/tests/datastore/unique_store
src/tests/datastore/unique_store_dictionary
src/tests/datastore/unique_store_string_allocator
diff --git a/vespalib/src/tests/datastore/sharded_hash_map/CMakeLists.txt b/vespalib/src/tests/datastore/sharded_hash_map/CMakeLists.txt
new file mode 100644
index 00000000000..f94b952f4a3
--- /dev/null
+++ b/vespalib/src/tests/datastore/sharded_hash_map/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(vespalib_sharded_hash_map_test_app
+ SOURCES
+ sharded_hash_map_test.cpp
+ DEPENDS
+ vespalib
+ GTest::GTest
+)
+vespa_add_test(NAME vespalib_sharded_hash_map_test_app COMMAND vespalib_sharded_hash_map_test_app)
diff --git a/vespalib/src/tests/datastore/simple_hash_map/simple_hash_map_test.cpp b/vespalib/src/tests/datastore/sharded_hash_map/sharded_hash_map_test.cpp
index 866c2a30818..9f11b96e672 100644
--- a/vespalib/src/tests/datastore/simple_hash_map/simple_hash_map_test.cpp
+++ b/vespalib/src/tests/datastore/sharded_hash_map/sharded_hash_map_test.cpp
@@ -1,6 +1,6 @@
// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include <vespa/vespalib/datastore/simple_hash_map.h>
+#include <vespa/vespalib/datastore/sharded_hash_map.h>
#include <vespa/vespalib/datastore/unique_store_allocator.h>
#include <vespa/vespalib/datastore/unique_store_comparator.h>
@@ -13,18 +13,18 @@
#include <vespa/vespalib/datastore/unique_store_allocator.hpp>
#include <vespa/log/log.h>
-LOG_SETUP("vespalib_datastore_simple_hash_test");
+LOG_SETUP("vespalib_datastore_shared_hash_test");
using vespalib::datastore::EntryRef;
using RefT = vespalib::datastore::EntryRefT<22>;
using MyAllocator = vespalib::datastore::UniqueStoreAllocator<uint32_t, RefT>;
using MyDataStore = vespalib::datastore::DataStoreT<RefT>;
using MyCompare = vespalib::datastore::UniqueStoreComparator<uint32_t, RefT>;
-using MyHashMap = vespalib::datastore::SimpleHashMap;
+using MyHashMap = vespalib::datastore::ShardedHashMap;
using GenerationHandler = vespalib::GenerationHandler;
using vespalib::makeLambdaTask;
-struct DataStoreSimpleHashTest : public ::testing::Test
+struct DataStoreShardedHashTest : public ::testing::Test
{
GenerationHandler _generationHandler;
MyAllocator _allocator;
@@ -41,8 +41,8 @@ struct DataStoreSimpleHashTest : public ::testing::Test
std::atomic<int> _stop_read;
bool _report_work;
- DataStoreSimpleHashTest();
- ~DataStoreSimpleHashTest();
+ DataStoreShardedHashTest();
+ ~DataStoreShardedHashTest();
void commit();
void insert(uint32_t key);
void remove(uint32_t key);
@@ -53,7 +53,7 @@ struct DataStoreSimpleHashTest : public ::testing::Test
};
-DataStoreSimpleHashTest::DataStoreSimpleHashTest()
+DataStoreShardedHashTest::DataStoreShardedHashTest()
: _generationHandler(),
_allocator(),
_store(_allocator.get_data_store()),
@@ -73,7 +73,7 @@ DataStoreSimpleHashTest::DataStoreSimpleHashTest()
}
-DataStoreSimpleHashTest::~DataStoreSimpleHashTest()
+DataStoreShardedHashTest::~DataStoreShardedHashTest()
{
_readers.sync();
_readers.shutdown();
@@ -89,7 +89,7 @@ DataStoreSimpleHashTest::~DataStoreSimpleHashTest()
void
-DataStoreSimpleHashTest::commit()
+DataStoreShardedHashTest::commit()
{
_store.transferHoldLists(_generationHandler.getCurrentGeneration());
_hash_map.transfer_hold_lists(_generationHandler.getCurrentGeneration());
@@ -99,7 +99,7 @@ DataStoreSimpleHashTest::commit()
}
void
-DataStoreSimpleHashTest::insert(uint32_t key)
+DataStoreShardedHashTest::insert(uint32_t key)
{
MyCompare comp(_store, key);
std::function<EntryRef(void)> insert_entry([this, key]() -> EntryRef { return _allocator.allocate(key); });
@@ -110,7 +110,7 @@ DataStoreSimpleHashTest::insert(uint32_t key)
}
void
-DataStoreSimpleHashTest::remove(uint32_t key)
+DataStoreShardedHashTest::remove(uint32_t key)
{
MyCompare comp(_store, key);
auto result = _hash_map.remove(comp, EntryRef());
@@ -124,7 +124,7 @@ DataStoreSimpleHashTest::remove(uint32_t key)
void
-DataStoreSimpleHashTest::read_work(uint32_t cnt)
+DataStoreShardedHashTest::read_work(uint32_t cnt)
{
vespalib::Rand48 rnd;
long found = 0;
@@ -149,14 +149,14 @@ DataStoreSimpleHashTest::read_work(uint32_t cnt)
void
-DataStoreSimpleHashTest::read_work()
+DataStoreShardedHashTest::read_work()
{
read_work(std::numeric_limits<uint32_t>::max());
}
void
-DataStoreSimpleHashTest::write_work(uint32_t cnt)
+DataStoreShardedHashTest::write_work(uint32_t cnt)
{
vespalib::Rand48 &rnd(_rnd);
for (uint32_t i = 0; i < cnt; ++i) {
@@ -174,7 +174,7 @@ DataStoreSimpleHashTest::write_work(uint32_t cnt)
}
-TEST_F(DataStoreSimpleHashTest, single_threaded_reader_without_updates)
+TEST_F(DataStoreShardedHashTest, single_threaded_reader_without_updates)
{
_report_work = true;
write_work(10);
@@ -182,7 +182,7 @@ TEST_F(DataStoreSimpleHashTest, single_threaded_reader_without_updates)
read_work(10);
}
-TEST_F(DataStoreSimpleHashTest, single_threaded_reader_during_updates)
+TEST_F(DataStoreShardedHashTest, single_threaded_reader_during_updates)
{
uint32_t cnt = 1000000;
_report_work = true;
@@ -190,7 +190,7 @@ TEST_F(DataStoreSimpleHashTest, single_threaded_reader_during_updates)
_readers.execute(makeLambdaTask([this]() { read_work(); }));
}
-TEST_F(DataStoreSimpleHashTest, multi_threaded_reader_during_updates)
+TEST_F(DataStoreShardedHashTest, multi_threaded_reader_during_updates)
{
uint32_t cnt = 1000000;
_report_work = true;
@@ -200,7 +200,7 @@ TEST_F(DataStoreSimpleHashTest, multi_threaded_reader_during_updates)
}
}
-TEST_F(DataStoreSimpleHashTest, memory_usage_is_reported)
+TEST_F(DataStoreShardedHashTest, memory_usage_is_reported)
{
auto initial_usage = _hash_map.get_memory_usage();
EXPECT_LT(0, initial_usage.allocatedBytes());
diff --git a/vespalib/src/tests/datastore/simple_hash_map/CMakeLists.txt b/vespalib/src/tests/datastore/simple_hash_map/CMakeLists.txt
deleted file mode 100644
index c790481ebbc..00000000000
--- a/vespalib/src/tests/datastore/simple_hash_map/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-vespa_add_executable(vespalib_simple_hash_map_test_app
- SOURCES
- simple_hash_map_test.cpp
- DEPENDS
- vespalib
- GTest::GTest
-)
-vespa_add_test(NAME vespalib_simple_hash_map_test_app COMMAND vespalib_simple_hash_map_test_app)
diff --git a/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp b/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp
index 25ed566f57a..3e8b144cf32 100644
--- a/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp
+++ b/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp
@@ -3,7 +3,7 @@
#include <vespa/vespalib/datastore/unique_store_remapper.h>
#include <vespa/vespalib/datastore/unique_store_string_allocator.hpp>
#include <vespa/vespalib/datastore/unique_store_string_comparator.h>
-#include <vespa/vespalib/datastore/simple_hash_map.h>
+#include <vespa/vespalib/datastore/sharded_hash_map.h>
#include <vespa/vespalib/gtest/gtest.h>
#include <vespa/vespalib/test/datastore/buffer_stats.h>
#include <vespa/vespalib/test/insertion_operators.h>
@@ -152,7 +152,7 @@ TestBase<UniqueStoreTypeAndDictionaryType>::TestBase()
case DictionaryType::BTREE:
break;
default:
- store.set_dictionary(std::make_unique<UniqueStoreDictionary<uniquestore::DefaultDictionary, IUniqueStoreDictionary, SimpleHashMap>>(std::make_unique<CompareType>(store.get_data_store())));
+ store.set_dictionary(std::make_unique<UniqueStoreDictionary<uniquestore::DefaultDictionary, IUniqueStoreDictionary, ShardedHashMap>>(std::make_unique<CompareType>(store.get_data_store())));
}
}
diff --git a/vespalib/src/tests/datastore/unique_store_dictionary/unique_store_dictionary_test.cpp b/vespalib/src/tests/datastore/unique_store_dictionary/unique_store_dictionary_test.cpp
index 2085292cdf4..2c1b4ad3cf1 100644
--- a/vespalib/src/tests/datastore/unique_store_dictionary/unique_store_dictionary_test.cpp
+++ b/vespalib/src/tests/datastore/unique_store_dictionary/unique_store_dictionary_test.cpp
@@ -2,7 +2,7 @@
#include <vespa/vespalib/datastore/unique_store.hpp>
#include <vespa/vespalib/datastore/unique_store_dictionary.hpp>
-#include <vespa/vespalib/datastore/simple_hash_map.h>
+#include <vespa/vespalib/datastore/sharded_hash_map.h>
#include <vespa/vespalib/util/memoryusage.h>
#include <vespa/vespalib/gtest/gtest.h>
@@ -59,7 +59,7 @@ struct DictionaryReadTest : public ::testing::Test {
}
};
-using DictionaryReadTestTypes = ::testing::Types<DefaultUniqueStoreDictionary, UniqueStoreDictionary<DefaultDictionary, IUniqueStoreDictionary, SimpleHashMap>>;
+using DictionaryReadTestTypes = ::testing::Types<DefaultUniqueStoreDictionary, UniqueStoreDictionary<DefaultDictionary, IUniqueStoreDictionary, ShardedHashMap>>;
VESPA_GTEST_TYPED_TEST_SUITE(DictionaryReadTest, DictionaryReadTestTypes);
// Disable warnings emitted by gtest generated files when using typed tests
diff --git a/vespalib/src/vespa/vespalib/datastore/CMakeLists.txt b/vespalib/src/vespa/vespalib/datastore/CMakeLists.txt
index 1ee945f1b8f..b028a040f8d 100644
--- a/vespalib/src/vespa/vespalib/datastore/CMakeLists.txt
+++ b/vespalib/src/vespa/vespalib/datastore/CMakeLists.txt
@@ -9,7 +9,7 @@ vespa_add_library(vespalib_vespalib_datastore OBJECT
datastorebase.cpp
entryref.cpp
fixed_size_hash_map.cpp
- simple_hash_map.cpp
+ sharded_hash_map.cpp
unique_store.cpp
unique_store_string_allocator.cpp
DEPENDS
diff --git a/vespalib/src/vespa/vespalib/datastore/fixed_size_hash_map.cpp b/vespalib/src/vespa/vespalib/datastore/fixed_size_hash_map.cpp
index 4822313e39e..cca61e3c852 100644
--- a/vespalib/src/vespa/vespalib/datastore/fixed_size_hash_map.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/fixed_size_hash_map.cpp
@@ -20,7 +20,7 @@ FixedSizeHashMap::Node::on_free()
_kv = std::make_pair(AtomicEntryRef(), AtomicEntryRef());
}
-FixedSizeHashMap::FixedSizeHashMap(uint32_t modulo, uint32_t capacity, uint32_t num_stripes)
+FixedSizeHashMap::FixedSizeHashMap(uint32_t modulo, uint32_t capacity, uint32_t num_shards)
: _chain_heads(modulo),
_nodes(),
_modulo(modulo),
@@ -30,13 +30,13 @@ FixedSizeHashMap::FixedSizeHashMap(uint32_t modulo, uint32_t capacity, uint32_t
_hold_count(0u),
_hold_1_list(),
_hold_2_list(),
- _num_stripes(num_stripes)
+ _num_shards(num_shards)
{
_nodes.reserve(capacity);
}
-FixedSizeHashMap::FixedSizeHashMap(uint32_t modulo, uint32_t capacity, uint32_t num_stripes, const FixedSizeHashMap &orig, const EntryComparator& comp)
- : FixedSizeHashMap(modulo, capacity, num_stripes)
+FixedSizeHashMap::FixedSizeHashMap(uint32_t modulo, uint32_t capacity, uint32_t num_shards, const FixedSizeHashMap &orig, const EntryComparator& comp)
+ : FixedSizeHashMap(modulo, capacity, num_shards)
{
for (const auto &chain_head : orig._chain_heads) {
for (uint32_t node_idx = chain_head.load_relaxed(); node_idx != no_node_idx;) {
@@ -52,7 +52,7 @@ FixedSizeHashMap::~FixedSizeHashMap() = default;
void
FixedSizeHashMap::force_add(const EntryComparator& comp, const KvType& kv)
{
- size_t hash_idx = comp.hash(kv.first.load_relaxed()) / _num_stripes;
+ size_t hash_idx = comp.hash(kv.first.load_relaxed()) / _num_shards;
hash_idx %= _modulo;
auto& chain_head = _chain_heads[hash_idx];
assert(_nodes.size() < _nodes.capacity());
@@ -65,7 +65,7 @@ FixedSizeHashMap::force_add(const EntryComparator& comp, const KvType& kv)
FixedSizeHashMap::KvType&
FixedSizeHashMap::add(const EntryComparator& comp, EntryRef key_ref, std::function<EntryRef(void)>& insert_entry)
{
- size_t hash_idx = comp.hash(key_ref) / _num_stripes;
+ size_t hash_idx = comp.hash(key_ref) / _num_shards;
hash_idx %= _modulo;
auto& chain_head = _chain_heads[hash_idx];
uint32_t node_idx = chain_head.load_relaxed();
@@ -129,7 +129,7 @@ FixedSizeHashMap::trim_hold_lists_slow(generation_t first_used)
FixedSizeHashMap::KvType*
FixedSizeHashMap::remove(const EntryComparator& comp, EntryRef key_ref)
{
- size_t hash_idx = comp.hash(key_ref) / _num_stripes;
+ size_t hash_idx = comp.hash(key_ref) / _num_shards;
hash_idx %= _modulo;
auto& chain_head = _chain_heads[hash_idx];
uint32_t node_idx = chain_head.load_relaxed();
@@ -157,7 +157,7 @@ FixedSizeHashMap::remove(const EntryComparator& comp, EntryRef key_ref)
FixedSizeHashMap::KvType*
FixedSizeHashMap::find(const EntryComparator& comp, EntryRef key_ref)
{
- size_t hash_idx = comp.hash(key_ref) / _num_stripes;
+ size_t hash_idx = comp.hash(key_ref) / _num_shards;
hash_idx %= _modulo;
auto& chain_head = _chain_heads[hash_idx];
uint32_t node_idx = chain_head.load_acquire();
diff --git a/vespalib/src/vespa/vespalib/datastore/fixed_size_hash_map.h b/vespalib/src/vespa/vespalib/datastore/fixed_size_hash_map.h
index 8153bc82e06..a0ca1bf0568 100644
--- a/vespalib/src/vespa/vespalib/datastore/fixed_size_hash_map.h
+++ b/vespalib/src/vespa/vespalib/datastore/fixed_size_hash_map.h
@@ -89,14 +89,14 @@ private:
uint32_t _hold_count;
Array<uint32_t> _hold_1_list;
std::deque<std::pair<generation_t, uint32_t>> _hold_2_list;
- uint32_t _num_stripes;
+ uint32_t _num_shards;
void transfer_hold_lists_slow(generation_t generation);
void trim_hold_lists_slow(generation_t first_used);
void force_add(const EntryComparator& comp, const KvType& kv);
public:
- FixedSizeHashMap(uint32_t module, uint32_t capacity, uint32_t num_stripes);
- FixedSizeHashMap(uint32_t module, uint32_t capacity, uint32_t num_stripes, const FixedSizeHashMap &orig, const EntryComparator& comp);
+ FixedSizeHashMap(uint32_t module, uint32_t capacity, uint32_t num_shards);
+ FixedSizeHashMap(uint32_t module, uint32_t capacity, uint32_t num_shards, const FixedSizeHashMap &orig, const EntryComparator& comp);
~FixedSizeHashMap();
KvType& add(const EntryComparator& comp, EntryRef key_ref, std::function<EntryRef(void)>& insert_entry);
diff --git a/vespalib/src/vespa/vespalib/datastore/sharded_hash_map.cpp b/vespalib/src/vespa/vespalib/datastore/sharded_hash_map.cpp
new file mode 100644
index 00000000000..7c609f89972
--- /dev/null
+++ b/vespalib/src/vespa/vespalib/datastore/sharded_hash_map.cpp
@@ -0,0 +1,168 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "sharded_hash_map.h"
+#include "fixed_size_hash_map.h"
+#include "entry_comparator.h"
+#include <vespa/vespalib/util/memoryusage.h>
+
+namespace vespalib::datastore {
+
+class ShardedHashMapShardHeld : public GenerationHeldBase
+{
+ std::unique_ptr<const FixedSizeHashMap> _data;
+public:
+ ShardedHashMapShardHeld(size_t size, std::unique_ptr<const FixedSizeHashMap> data);
+ ~ShardedHashMapShardHeld();
+};
+
+ShardedHashMapShardHeld::ShardedHashMapShardHeld(size_t size, std::unique_ptr<const FixedSizeHashMap> data)
+ : GenerationHeldBase(size),
+ _data(std::move(data))
+{
+}
+
+ShardedHashMapShardHeld::~ShardedHashMapShardHeld() = default;
+
+ShardedHashMap::ShardedHashMap(std::unique_ptr<const EntryComparator> comp)
+ : _gen_holder(),
+ _maps(),
+ _comp(std::move(comp))
+{
+}
+
+ShardedHashMap::~ShardedHashMap()
+{
+ _gen_holder.clearHoldLists();
+ for (size_t i = 0; i < num_shards; ++i) {
+ auto map = _maps[i].load(std::memory_order_relaxed);
+ delete map;
+ }
+}
+
+size_t
+ShardedHashMap::get_shard_idx(const EntryComparator& comp, EntryRef key_ref) const
+{
+ return comp.hash(key_ref) % num_shards;
+}
+
+void
+ShardedHashMap::alloc_shard(size_t shard_idx)
+{
+ auto map = _maps[shard_idx].load(std::memory_order_relaxed);
+ if (map == nullptr) {
+ auto umap = std::make_unique<FixedSizeHashMap>(2u, 3u, num_shards);
+ _maps[shard_idx].store(umap.release(), std::memory_order_release);
+ } else {
+ auto umap = std::make_unique<FixedSizeHashMap>(map->size() * 2 + 2, map->size() * 3 + 3, num_shards, *map, *_comp);
+ _maps[shard_idx].store(umap.release(), std::memory_order_release);
+ hold_shard(std::unique_ptr<const FixedSizeHashMap>(map));
+ }
+}
+
+void
+ShardedHashMap::hold_shard(std::unique_ptr<const FixedSizeHashMap> map)
+{
+ auto usage = map->get_memory_usage();
+ auto hold = std::make_unique<ShardedHashMapShardHeld>(usage.allocatedBytes(), std::move(map));
+ _gen_holder.hold(std::move(hold));
+}
+
+ShardedHashMap::KvType&
+ShardedHashMap::add(const EntryComparator& comp, EntryRef key_ref, std::function<EntryRef(void)>& insert_entry)
+{
+ size_t shard_idx = get_shard_idx(comp, key_ref);
+ auto map = _maps[shard_idx].load(std::memory_order_relaxed);
+ if (map == nullptr || map->full()) {
+ alloc_shard(shard_idx);
+ map = _maps[shard_idx].load(std::memory_order_relaxed);
+ }
+ return map->add(comp, key_ref, insert_entry);
+}
+
+ShardedHashMap::KvType*
+ShardedHashMap::remove(const EntryComparator& comp, EntryRef key_ref)
+{
+ size_t shard_idx = get_shard_idx(comp, key_ref);
+ auto map = _maps[shard_idx].load(std::memory_order_relaxed);
+ if (map == nullptr) {
+ return nullptr;
+ }
+ return map->remove(comp, key_ref);
+}
+
+ShardedHashMap::KvType*
+ShardedHashMap::find(const EntryComparator& comp, EntryRef key_ref)
+{
+ size_t shard_idx = get_shard_idx(comp, key_ref);
+ auto map = _maps[shard_idx].load(std::memory_order_relaxed);
+ if (map == nullptr) {
+ return nullptr;
+ }
+ return map->find(comp, key_ref);
+}
+
+const ShardedHashMap::KvType*
+ShardedHashMap::find(const EntryComparator& comp, EntryRef key_ref) const
+{
+ size_t shard_idx = get_shard_idx(comp, key_ref);
+ auto map = _maps[shard_idx].load(std::memory_order_relaxed);
+ if (map == nullptr) {
+ return nullptr;
+ }
+ return map->find(comp, key_ref);
+}
+
+void
+ShardedHashMap::transfer_hold_lists(generation_t generation)
+{
+ for (size_t i = 0; i < num_shards; ++i) {
+ auto map = _maps[i].load(std::memory_order_relaxed);
+ if (map != nullptr) {
+ map->transfer_hold_lists(generation);
+ }
+ }
+ _gen_holder.transferHoldLists(generation);
+}
+
+void
+ShardedHashMap::trim_hold_lists(generation_t first_used)
+{
+ for (size_t i = 0; i < num_shards; ++i) {
+ auto map = _maps[i].load(std::memory_order_relaxed);
+ if (map != nullptr) {
+ map->trim_hold_lists(first_used);
+ }
+ }
+ _gen_holder.trimHoldLists(first_used);
+}
+
+size_t
+ShardedHashMap::size() const noexcept
+{
+ size_t result = 0;
+ for (size_t i = 0; i < num_shards; ++i) {
+ auto map = _maps[i].load(std::memory_order_relaxed);
+ if (map != nullptr) {
+ result += map->size();
+ }
+ }
+ return result;
+}
+
+MemoryUsage
+ShardedHashMap::get_memory_usage() const
+{
+ MemoryUsage memory_usage(sizeof(ShardedHashMap), sizeof(ShardedHashMap), 0, 0);
+ for (size_t i = 0; i < num_shards; ++i) {
+ auto map = _maps[i].load(std::memory_order_relaxed);
+ if (map != nullptr) {
+ memory_usage.merge(map->get_memory_usage());
+ }
+ }
+ size_t gen_holder_held_bytes = _gen_holder.getHeldBytes();
+ memory_usage.incAllocatedBytes(gen_holder_held_bytes);
+ memory_usage.incAllocatedBytesOnHold(gen_holder_held_bytes);
+ return memory_usage;
+}
+
+}
diff --git a/vespalib/src/vespa/vespalib/datastore/simple_hash_map.h b/vespalib/src/vespa/vespalib/datastore/sharded_hash_map.h
index bc052295511..7ea60646b06 100644
--- a/vespalib/src/vespa/vespalib/datastore/simple_hash_map.h
+++ b/vespalib/src/vespa/vespalib/datastore/sharded_hash_map.h
@@ -30,23 +30,23 @@ class EntryComparator;
* trim_hold_lists as needed to free up memory no longer needed by any
* readers.
*/
-class SimpleHashMap {
+class ShardedHashMap {
public:
using KvType = std::pair<AtomicEntryRef, AtomicEntryRef>;
using generation_t = GenerationHandler::generation_t;
using sgeneration_t = GenerationHandler::sgeneration_t;
private:
GenerationHolder _gen_holder;
- static constexpr size_t num_stripes = 3;
- std::atomic<FixedSizeHashMap *> _maps[num_stripes];
+ static constexpr size_t num_shards = 3;
+ std::atomic<FixedSizeHashMap *> _maps[num_shards];
std::unique_ptr<const EntryComparator> _comp;
- size_t get_stripe(const EntryComparator& comp, EntryRef key_ref) const;
- void alloc_stripe(size_t stripe);
- void hold_stripe(std::unique_ptr<const FixedSizeHashMap> map);
+ size_t get_shard_idx(const EntryComparator& comp, EntryRef key_ref) const;
+ void alloc_shard(size_t shard_idx);
+ void hold_shard(std::unique_ptr<const FixedSizeHashMap> map);
public:
- SimpleHashMap(std::unique_ptr<const EntryComparator> comp);
- ~SimpleHashMap();
+ ShardedHashMap(std::unique_ptr<const EntryComparator> comp);
+ ~ShardedHashMap();
KvType& add(const EntryComparator& comp, EntryRef key_ref, std::function<EntryRef(void)> &insert_entry);
KvType* remove(const EntryComparator& comp, EntryRef key_ref);
KvType* find(const EntryComparator& comp, EntryRef key_ref);
diff --git a/vespalib/src/vespa/vespalib/datastore/simple_hash_map.cpp b/vespalib/src/vespa/vespalib/datastore/simple_hash_map.cpp
deleted file mode 100644
index 2295cecd613..00000000000
--- a/vespalib/src/vespa/vespalib/datastore/simple_hash_map.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "simple_hash_map.h"
-#include "fixed_size_hash_map.h"
-#include "entry_comparator.h"
-#include <vespa/vespalib/util/memoryusage.h>
-
-namespace vespalib::datastore {
-
-class SimpleHashMapStripeHeld : public GenerationHeldBase
-{
- std::unique_ptr<const FixedSizeHashMap> _data;
-public:
- SimpleHashMapStripeHeld(size_t size, std::unique_ptr<const FixedSizeHashMap> data);
- ~SimpleHashMapStripeHeld();
-};
-
-SimpleHashMapStripeHeld::SimpleHashMapStripeHeld(size_t size, std::unique_ptr<const FixedSizeHashMap> data)
- : GenerationHeldBase(size),
- _data(std::move(data))
-{
-}
-
-SimpleHashMapStripeHeld::~SimpleHashMapStripeHeld() = default;
-
-SimpleHashMap::SimpleHashMap(std::unique_ptr<const EntryComparator> comp)
- : _gen_holder(),
- _maps(),
- _comp(std::move(comp))
-{
-}
-
-SimpleHashMap::~SimpleHashMap()
-{
- _gen_holder.clearHoldLists();
- for (size_t i = 0; i < num_stripes; ++i) {
- auto map = _maps[i].load(std::memory_order_relaxed);
- delete map;
- }
-}
-
-size_t
-SimpleHashMap::get_stripe(const EntryComparator& comp, EntryRef key_ref) const
-{
- return comp.hash(key_ref) % num_stripes;
-}
-
-void
-SimpleHashMap::alloc_stripe(size_t stripe)
-{
- auto map = _maps[stripe].load(std::memory_order_relaxed);
- if (map == nullptr) {
- auto umap = std::make_unique<FixedSizeHashMap>(2u, 3u, num_stripes);
- _maps[stripe].store(umap.release(), std::memory_order_release);
- } else {
- auto umap = std::make_unique<FixedSizeHashMap>(map->size() * 2 + 2, map->size() * 3 + 3, num_stripes, *map, *_comp);
- _maps[stripe].store(umap.release(), std::memory_order_release);
- hold_stripe(std::unique_ptr<const FixedSizeHashMap>(map));
- }
-}
-
-void
-SimpleHashMap::hold_stripe(std::unique_ptr<const FixedSizeHashMap> map)
-{
- auto usage = map->get_memory_usage();
- auto hold = std::make_unique<SimpleHashMapStripeHeld>(usage.allocatedBytes(), std::move(map));
- _gen_holder.hold(std::move(hold));
-}
-
-SimpleHashMap::KvType&
-SimpleHashMap::add(const EntryComparator& comp, EntryRef key_ref, std::function<EntryRef(void)>& insert_entry)
-{
- size_t stripe = get_stripe(comp, key_ref);
- auto map = _maps[stripe].load(std::memory_order_relaxed);
- if (map == nullptr || map->full()) {
- alloc_stripe(stripe);
- map = _maps[stripe].load(std::memory_order_relaxed);
- }
- return map->add(comp, key_ref, insert_entry);
-}
-
-SimpleHashMap::KvType*
-SimpleHashMap::remove(const EntryComparator& comp, EntryRef key_ref)
-{
- size_t stripe = get_stripe(comp, key_ref);
- auto map = _maps[stripe].load(std::memory_order_relaxed);
- if (map == nullptr) {
- return nullptr;
- }
- return map->remove(comp, key_ref);
-}
-
-SimpleHashMap::KvType*
-SimpleHashMap::find(const EntryComparator& comp, EntryRef key_ref)
-{
- size_t stripe = get_stripe(comp, key_ref);
- auto map = _maps[stripe].load(std::memory_order_relaxed);
- if (map == nullptr) {
- return nullptr;
- }
- return map->find(comp, key_ref);
-}
-
-const SimpleHashMap::KvType*
-SimpleHashMap::find(const EntryComparator& comp, EntryRef key_ref) const
-{
- size_t stripe = get_stripe(comp, key_ref);
- auto map = _maps[stripe].load(std::memory_order_relaxed);
- if (map == nullptr) {
- return nullptr;
- }
- return map->find(comp, key_ref);
-}
-
-void
-SimpleHashMap::transfer_hold_lists(generation_t generation)
-{
- for (size_t i = 0; i < num_stripes; ++i) {
- auto map = _maps[i].load(std::memory_order_relaxed);
- if (map != nullptr) {
- map->transfer_hold_lists(generation);
- }
- }
- _gen_holder.transferHoldLists(generation);
-}
-
-void
-SimpleHashMap::trim_hold_lists(generation_t first_used)
-{
- for (size_t i = 0; i < num_stripes; ++i) {
- auto map = _maps[i].load(std::memory_order_relaxed);
- if (map != nullptr) {
- map->trim_hold_lists(first_used);
- }
- }
- _gen_holder.trimHoldLists(first_used);
-}
-
-size_t
-SimpleHashMap::size() const noexcept
-{
- size_t result = 0;
- for (size_t i = 0; i < num_stripes; ++i) {
- auto map = _maps[i].load(std::memory_order_relaxed);
- if (map != nullptr) {
- result += map->size();
- }
- }
- return result;
-}
-
-MemoryUsage
-SimpleHashMap::get_memory_usage() const
-{
- MemoryUsage memory_usage(sizeof(SimpleHashMap), sizeof(SimpleHashMap), 0, 0);
- for (size_t i = 0; i < num_stripes; ++i) {
- auto map = _maps[i].load(std::memory_order_relaxed);
- if (map != nullptr) {
- memory_usage.merge(map->get_memory_usage());
- }
- }
- size_t gen_holder_held_bytes = _gen_holder.getHeldBytes();
- memory_usage.incAllocatedBytes(gen_holder_held_bytes);
- memory_usage.incAllocatedBytesOnHold(gen_holder_held_bytes);
- return memory_usage;
-}
-
-}