This is an automated email from the ASF dual-hosted git repository.

git-hulk pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new bae3ba7a3 perf(search): share a thread-local RNG for HNSW and drop 
seed (#2398) (#3562)
bae3ba7a3 is described below

commit bae3ba7a356779a0af1798903aa0a0377b861b7e
Author: advisedy <[email protected]>
AuthorDate: Thu Jul 30 14:00:48 2026 +0800

    perf(search): share a thread-local RNG for HNSW and drop seed (#2398) 
(#3562)
    
    Fixes #2398.
---
 src/search/hnsw_indexer.cc       | 11 +++++------
 src/search/hnsw_indexer.h        | 10 +++++-----
 tests/cppunit/hnsw_index_test.cc |  3 +--
 3 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/src/search/hnsw_indexer.cc b/src/search/hnsw_indexer.cc
index cb9aca770..7fbc193e7 100644
--- a/src/search/hnsw_indexer.cc
+++ b/src/search/hnsw_indexer.cc
@@ -24,7 +24,6 @@
 
 #include <algorithm>
 #include <cmath>
-#include <memory>
 #include <queue>
 #include <random>
 #include <unordered_set>
@@ -172,15 +171,15 @@ StatusOr<double> ComputeSimilarity(const VectorItem& 
left, const VectorItem& rig
   }
 }
 
-HnswIndex::HnswIndex(const SearchKey& search_key, HnswVectorFieldMetadata* 
vector, engine::Storage* storage,
-                     std::random_device::result_type seed)
+thread_local std::mt19937 HnswIndex::generator{std::random_device()()};
+
+HnswIndex::HnswIndex(const SearchKey& search_key, HnswVectorFieldMetadata* 
vector, engine::Storage* storage)
     : search_key(search_key),
       metadata(vector),
       storage(storage),
-      generator(std::mt19937(seed)),
       m_level_normalization_factor(1.0 / std::log(metadata->m)) {}
 
-uint16_t HnswIndex::RandomizeLayer() {
+uint16_t HnswIndex::RandomizeLayer() const {
   std::uniform_real_distribution<double> level_dist(0.0, 1.0);
   double r = level_dist(generator);
   double log_val = -std::log(r);
@@ -518,7 +517,7 @@ Status 
HnswIndex::InsertVectorEntryInternal(engine::Context& ctx, std::string_vi
 }
 
 Status HnswIndex::InsertVectorEntry(engine::Context& ctx, std::string_view 
key, const kqir::NumericArray& vector,
-                                    
ObserverOrUniquePtr<rocksdb::WriteBatchBase>& batch) {
+                                    
ObserverOrUniquePtr<rocksdb::WriteBatchBase>& batch) const {
   auto target_level = RandomizeLayer();
   return InsertVectorEntryInternal(ctx, key, vector, batch, target_level);
 }
diff --git a/src/search/hnsw_indexer.h b/src/search/hnsw_indexer.h
index 579352a8b..461fd8eb5 100644
--- a/src/search/hnsw_indexer.h
+++ b/src/search/hnsw_indexer.h
@@ -89,17 +89,17 @@ struct HnswIndex {
   HnswVectorFieldMetadata* metadata;
   engine::Storage* storage = nullptr;
 
-  std::mt19937 generator;
   double m_level_normalization_factor;
 
-  HnswIndex(const SearchKey& search_key, HnswVectorFieldMetadata* vector, 
engine::Storage* storage,
-            std::random_device::result_type seed = std::random_device()());
+  static thread_local std::mt19937 generator;
+
+  HnswIndex(const SearchKey& search_key, HnswVectorFieldMetadata* vector, 
engine::Storage* storage);
 
   static StatusOr<std::vector<VectorItem>> 
DecodeNodesToVectorItems(engine::Context& ctx,
                                                                     const 
std::vector<NodeKey>& node_key,
                                                                     uint16_t 
level, const SearchKey& search_key,
                                                                     const 
HnswVectorFieldMetadata* metadata);
-  uint16_t RandomizeLayer();
+  uint16_t RandomizeLayer() const;
   StatusOr<NodeKey> DefaultEntryPoint(engine::Context& ctx, uint16_t level) 
const;
   Status AddEdge(const NodeKey& node_key1, const NodeKey& node_key2, uint16_t 
layer,
                  ObserverOrUniquePtr<rocksdb::WriteBatchBase>& batch) const;
@@ -117,7 +117,7 @@ struct HnswIndex {
   Status InsertVectorEntryInternal(engine::Context& ctx, std::string_view key, 
const kqir::NumericArray& vector,
                                    
ObserverOrUniquePtr<rocksdb::WriteBatchBase>& batch, uint16_t layer) const;
   Status InsertVectorEntry(engine::Context& ctx, std::string_view key, const 
kqir::NumericArray& vector,
-                           ObserverOrUniquePtr<rocksdb::WriteBatchBase>& 
batch);
+                           ObserverOrUniquePtr<rocksdb::WriteBatchBase>& 
batch) const;
   Status DeleteVectorEntry(engine::Context& ctx, std::string_view key,
                            ObserverOrUniquePtr<rocksdb::WriteBatchBase>& 
batch) const;
   StatusOr<std::vector<KeyWithDistance>> KnnSearch(engine::Context& ctx, const 
kqir::NumericArray& query_vector,
diff --git a/tests/cppunit/hnsw_index_test.cc b/tests/cppunit/hnsw_index_test.cc
index 022f2a738..332c1582a 100644
--- a/tests/cppunit/hnsw_index_test.cc
+++ b/tests/cppunit/hnsw_index_test.cc
@@ -66,7 +66,6 @@ struct HnswIndexTest : TestBase {
   std::string idx_name = "hnsw_test_idx";
   std::string key = "vector";
   std::unique_ptr<redis::HnswIndex> hnsw_index;
-  const std::random_device::result_type seed = 14863;  // fixed seed for 
reproducibility
 
   HnswIndexTest() {
     metadata.vector_type = redis::VectorType::FLOAT64;
@@ -74,7 +73,7 @@ struct HnswIndexTest : TestBase {
     metadata.m = 3;
     metadata.distance_metric = redis::DistanceMetric::L2;
     auto search_key = redis::SearchKey(ns, idx_name, key);
-    hnsw_index = std::make_unique<redis::HnswIndex>(search_key, &metadata, 
storage_.get(), seed);
+    hnsw_index = std::make_unique<redis::HnswIndex>(search_key, &metadata, 
storage_.get());
   }
 
   void TearDown() override { hnsw_index.reset(); }

Reply via email to