Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/VecSim/algorithms/brute_force/brute_force.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class BruteForceIndex : public VecSimIndexAbstract<DistType> {

return actual_stored_vec;
}

size_t indexMetaDataCapacity() const override { return idToLabelMapping.capacity(); }
#endif

protected:
Expand Down
2 changes: 2 additions & 0 deletions src/VecSim/algorithms/hnsw/hnsw.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ class HNSWIndex : public VecSimIndexAbstract<DistType>,

return actual_stored_vec;
}

size_t indexMetaDataCapacity() const override { return idToMetaData.capacity(); }
#endif

protected:
Expand Down
4 changes: 4 additions & 0 deletions src/VecSim/algorithms/hnsw/hnsw_tiered.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ class TieredHNSWIndex : public VecSimTieredIndex<DataType, DistType> {
}
#ifdef BUILD_TESTS
void getDataByLabel(labelType label, std::vector<std::vector<DataType>> &vectors_output) const;
size_t indexMetaDataCapacity() const override {
return this->backendIndex->indexMetaDataCapacity() +
this->frontendIndex->indexMetaDataCapacity();
}
#endif
};

Expand Down
12 changes: 12 additions & 0 deletions src/VecSim/vec_sim_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,16 @@ struct VecSimIndexInterface : public VecsimBaseObject {
inline static void setWriteMode(VecSimWriteMode mode) {
VecSimIndexInterface::asyncWriteMode = mode;
}
#ifdef BUILD_TESTS
/**
* @brief get the capacity of the meta data containers.
*
* @return The capacity of the meta data containers in number of elements.
* The value returned from this function may differ from the indexCapacity() function. For
* example, in HNSW, the capacity of the meta data containers is the capacity of the labels
* lookup table, while the capacity of the data containers is the capacity of the vectors
* container.
*/
virtual size_t indexMetaDataCapacity() const = 0;
#endif
};
18 changes: 13 additions & 5 deletions tests/benchmark/bm_vecsim_basics.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@ void BM_VecSimBasics<index_type_t>::UpdateAtBlockSize(benchmark::State &st) {
// Calculate vectors needed to reach next block boundary
size_t vecs_to_blocksize =
BM_VecSimGeneral::block_size - (initial_index_size % BM_VecSimGeneral::block_size);
size_t initial_index_cap = index->indexMetaDataCapacity();
assert(initial_index_cap == N_VECTORS + vecs_to_blocksize);

assert(vecs_to_blocksize < BM_VecSimGeneral::block_size);
labelType initial_label_count = index->indexLabelCount();
labelType curr_label = initial_label_count;
Expand All @@ -327,24 +330,29 @@ void BM_VecSimBasics<index_type_t>::UpdateAtBlockSize(benchmark::State &st) {

// Benchmark loop: repeatedly delete/add same vector to trigger grow-shrink cycles
labelType label_to_update = curr_label - 1;
size_t index_cap = index->indexCapacity();
size_t index_cap = index->indexMetaDataCapacity();
std::cout << "index_cap after adding vectors " << index_cap << std::endl;
assert(index_cap == initial_index_cap + BM_VecSimGeneral::block_size);

for (auto _ : st) {
// Remove the vector directly from hnsw
size_t ret = VecSimIndex_DeleteVector(
INDICES[st.range(0) == VecSimAlgo_TIERED ? VecSimAlgo_HNSWLIB : st.range(0)],
label_to_update);
assert(ret == 1);
assert(index->indexCapacity() == index_cap - BM_VecSimGeneral::block_size);
// Capacity should shrink by one block after deletion

// Capacity should not change
size_t curr_cap = index->indexMetaDataCapacity();
assert(curr_cap == index_cap);
ret = VecSimIndex_AddVector(index, QUERIES[(added_vec_count - 1) % N_QUERIES].data(),
label_to_update);
assert(ret == 1);
BM_VecSimGeneral::mock_thread_pool.thread_pool_wait();
assert(VecSimIndex_IndexSize(
INDICES[st.range(0) == VecSimAlgo_TIERED ? VecSimAlgo_HNSWLIB : st.range(0)]) ==
N_VECTORS + added_vec_count);
// Capacity should grow back to original size after addition
assert(index->indexCapacity() == index_cap);
// Capacity should not change
assert(index->indexMetaDataCapacity() == index_cap);
}
assert(VecSimIndex_IndexSize(index) == N_VECTORS + added_vec_count);

Expand Down
2 changes: 2 additions & 0 deletions tests/unit/test_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ TYPED_TEST(IndexAllocatorTest, test_bf_index_block_size_1) {

ASSERT_EQ(bfIndex->indexCapacity(), expected_map_containers_size);
ASSERT_EQ(bfIndex->idToLabelMapping.capacity(), expected_map_containers_size);
ASSERT_EQ(bfIndex->indexMetaDataCapacity(), expected_map_containers_size);
ASSERT_EQ(bfIndex->idToLabelMapping.size(), expected_map_containers_size);
ASSERT_GE(bfIndex->labelToIdLookup.bucket_count(), expected_map_containers_size);
};
Expand Down Expand Up @@ -530,6 +531,7 @@ TYPED_TEST(IndexAllocatorTest, test_hnsw_reclaim_memory) {
ASSERT_EQ(hnswIndex->getStoredVectorsCount(), expected_size);

ASSERT_EQ(hnswIndex->idToMetaData.capacity(), expected_map_containers_size);
ASSERT_EQ(hnswIndex->indexMetaDataCapacity(), expected_map_containers_size);
ASSERT_EQ(hnswIndex->idToMetaData.size(), expected_map_containers_size);
ASSERT_GE(hnswIndex->labelLookup.bucket_count(), expected_map_containers_size);
// Also validate that there are no unidirectional connections (these add memory to the
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/test_hnsw_tiered.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3795,6 +3795,11 @@ TYPED_TEST(HNSWTieredIndexTestBasic, HNSWResize) {
ASSERT_EQ(tiered_index->getMainIndexGuardWriteLockCount(), resize_operations);
ASSERT_EQ(hnsw_index->indexSize(), 1);
ASSERT_EQ(hnsw_index->indexCapacity(), blockSize);
ASSERT_EQ(hnsw_index->indexMetaDataCapacity(), blockSize);
ASSERT_EQ(tiered_index->frontendIndex->indexMetaDataCapacity(), 0);
ASSERT_EQ(tiered_index->indexMetaDataCapacity(),
hnsw_index->indexMetaDataCapacity() +
tiered_index->frontendIndex->indexMetaDataCapacity());

// add up to block size
for (size_t i = 1; i < blockSize; i++) {
Expand All @@ -3805,6 +3810,11 @@ TYPED_TEST(HNSWTieredIndexTestBasic, HNSWResize) {
ASSERT_EQ(tiered_index->getMainIndexGuardWriteLockCount(), resize_operations);
ASSERT_EQ(hnsw_index->indexSize(), blockSize);
ASSERT_EQ(hnsw_index->indexCapacity(), blockSize);
ASSERT_EQ(hnsw_index->indexMetaDataCapacity(), blockSize);
ASSERT_EQ(tiered_index->frontendIndex->indexMetaDataCapacity(), 0);
ASSERT_EQ(tiered_index->indexMetaDataCapacity(),
hnsw_index->indexMetaDataCapacity() +
tiered_index->frontendIndex->indexMetaDataCapacity());

// add one more vector to trigger another resize
GenerateAndAddVector<TEST_DATA_T>(tiered_index, dim, blockSize);
Expand All @@ -3814,6 +3824,11 @@ TYPED_TEST(HNSWTieredIndexTestBasic, HNSWResize) {
ASSERT_EQ(tiered_index->getMainIndexGuardWriteLockCount(), resize_operations);
ASSERT_EQ(hnsw_index->indexSize(), blockSize + 1);
ASSERT_EQ(hnsw_index->indexCapacity(), 2 * blockSize);
ASSERT_EQ(hnsw_index->indexMetaDataCapacity(), 2 * blockSize);
ASSERT_EQ(tiered_index->frontendIndex->indexMetaDataCapacity(), 0);
ASSERT_EQ(tiered_index->indexMetaDataCapacity(),
hnsw_index->indexMetaDataCapacity() +
tiered_index->frontendIndex->indexMetaDataCapacity());

// delete a vector to shrink data blocks
ASSERT_EQ(VecSimIndex_DeleteVector(tiered_index, 0), 1) << "Failed to delete vector 0";
Expand All @@ -3825,6 +3840,8 @@ TYPED_TEST(HNSWTieredIndexTestBasic, HNSWResize) {
ASSERT_EQ(tiered_index->getMainIndexGuardWriteLockCount(), resize_operations);
ASSERT_EQ(hnsw_index->indexSize(), blockSize);
ASSERT_EQ(hnsw_index->indexCapacity(), blockSize);
// meta data capacity should not shrink
ASSERT_EQ(hnsw_index->indexMetaDataCapacity(), 2 * blockSize);

// add this vector again and verify lock was acquired to resize
GenerateAndAddVector<TEST_DATA_T>(tiered_index, dim, 0);
Expand All @@ -3833,6 +3850,11 @@ TYPED_TEST(HNSWTieredIndexTestBasic, HNSWResize) {
ASSERT_EQ(tiered_index->getMainIndexGuardWriteLockCount(), resize_operations);
ASSERT_EQ(hnsw_index->indexSize(), blockSize + 1);
ASSERT_EQ(hnsw_index->indexCapacity(), 2 * blockSize);
ASSERT_EQ(hnsw_index->indexMetaDataCapacity(), 2 * blockSize);
ASSERT_EQ(tiered_index->frontendIndex->indexMetaDataCapacity(), 0);
ASSERT_EQ(tiered_index->indexMetaDataCapacity(),
hnsw_index->indexMetaDataCapacity() +
tiered_index->frontendIndex->indexMetaDataCapacity());

// add up to block size (count = 2 blockSize), the lock shouldn't be acquired because no resize
// is required
Expand All @@ -3843,4 +3865,9 @@ TYPED_TEST(HNSWTieredIndexTestBasic, HNSWResize) {
ASSERT_EQ(tiered_index->getMainIndexGuardWriteLockCount(), resize_operations);
ASSERT_EQ(hnsw_index->indexSize(), 2 * blockSize);
ASSERT_EQ(hnsw_index->indexCapacity(), 2 * blockSize);
ASSERT_EQ(hnsw_index->indexMetaDataCapacity(), 2 * blockSize);
ASSERT_EQ(tiered_index->frontendIndex->indexMetaDataCapacity(), 0);
ASSERT_EQ(tiered_index->indexMetaDataCapacity(),
hnsw_index->indexMetaDataCapacity() +
tiered_index->frontendIndex->indexMetaDataCapacity());
}
Loading