Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
};
16 changes: 11 additions & 5 deletions tests/benchmark/bm_vecsim_basics.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ 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);

assert(vecs_to_blocksize < BM_VecSimGeneral::block_size);
labelType initial_label_count = index->indexLabelCount();
labelType curr_label = initial_label_count;
Expand All @@ -327,24 +328,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_size + vecs_to_blocksize + 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