summaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2021-08-15 13:58:32 +0000
committerHenning Baldersheim <balder@yahoo-inc.com>2021-08-15 13:58:32 +0000
commit21337f626696182b68a8da2c1773784f5594027c (patch)
tree67e9bb97112a3d2bf3a59e60da68e0dc6f1ae292 /searchlib
parent6317934c7f314b7debf7df0a59d0e0228211b809 (diff)
Add a time budget of 100ms. If counting not complete by then, abort, and let the count be incomplete.
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp22
-rw-r--r--searchlib/src/vespa/searchlib/tensor/hnsw_index.h2
2 files changed, 17 insertions, 7 deletions
diff --git a/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp b/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp
index a1515534cbc..f11381070e1 100644
--- a/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp
+++ b/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp
@@ -12,6 +12,7 @@
#include <vespa/vespalib/util/memory_allocator.h>
#include <vespa/vespalib/util/rcuvector.hpp>
#include <vespa/vespalib/util/size_literals.h>
+#include <vespa/vespalib/util/time.h>
#include <vespa/log/log.h>
LOG_SETUP(".searchlib.tensor.hnsw_index");
@@ -30,6 +31,7 @@ constexpr float alloc_grow_factor = 0.3;
// TODO: Adjust these numbers to what we accept as max in config.
constexpr size_t max_level_array_size = 16;
constexpr size_t max_link_array_size = 64;
+constexpr vespalib::duration MAX_COUNT_DURATION(100ms);
bool has_link_to(vespalib::ConstArrayRef<uint32_t> links, uint32_t id) {
for (uint32_t link : links) {
@@ -500,9 +502,13 @@ HnswIndex::get_state(const vespalib::slime::Inserter& inserter) const
for (uint32_t hist_val : histograms.links_histogram) {
links_hst_array.addLong(hist_val);
}
- uint32_t reachable = count_reachable_nodes();
- uint32_t unreachable = valid_nodes - reachable;
- object.setLong("unreachable_nodes", unreachable);
+ auto count_result = count_reachable_nodes();
+ uint32_t unreachable = valid_nodes - count_result.first;
+ if (count_result.second) {
+ object.setLong("unreachable_nodes", unreachable);
+ } else {
+ object.setLong("unreachable_nodes_incomplete_count", unreachable);
+ }
auto entry_node = _graph.get_entry_node();
object.setLong("entry_docid", entry_node.docid);
object.setLong("entry_level", entry_node.level);
@@ -650,20 +656,24 @@ HnswIndex::check_link_symmetry() const
return all_sym;
}
-uint32_t
+std::pair<uint32_t, bool>
HnswIndex::count_reachable_nodes() const
{
auto entry = _graph.get_entry_node();
int search_level = entry.level;
if (search_level < 0) {
- return 0;
+ return {0, true};
}
std::vector<bool> visited(_graph.size());
LinkArray found_links;
found_links.push_back(entry.docid);
visited[entry.docid] = true;
+ vespalib::steady_time doom = vespalib::steady_clock::now() + MAX_COUNT_DURATION;
while (search_level >= 0) {
for (uint32_t idx = 0; idx < found_links.size(); ++idx) {
+ if (vespalib::steady_clock::now() > doom) {
+ return {found_links.size(), false};
+ }
uint32_t docid = found_links[idx];
auto neighbors = _graph.get_link_array(docid, search_level);
for (uint32_t neighbor : neighbors) {
@@ -674,7 +684,7 @@ HnswIndex::count_reachable_nodes() const
}
--search_level;
}
- return found_links.size();
+ return {found_links.size(), true};
}
} // namespace
diff --git a/searchlib/src/vespa/searchlib/tensor/hnsw_index.h b/searchlib/src/vespa/searchlib/tensor/hnsw_index.h
index 5bd9d17adc3..ef0f38c2263 100644
--- a/searchlib/src/vespa/searchlib/tensor/hnsw_index.h
+++ b/searchlib/src/vespa/searchlib/tensor/hnsw_index.h
@@ -183,7 +183,7 @@ public:
HnswNode get_node(uint32_t docid) const;
void set_node(uint32_t docid, const HnswNode &node);
bool check_link_symmetry() const;
- uint32_t count_reachable_nodes() const;
+ std::pair<uint32_t, bool> count_reachable_nodes() const;
static vespalib::datastore::ArrayStoreConfig make_default_node_store_config();
static vespalib::datastore::ArrayStoreConfig make_default_link_store_config();