Skip to content

Commit 6442207

Browse files
committed
Pass 64 MiB blocked allocator
1 parent 90c16c3 commit 6442207

File tree

2 files changed

+101
-90
lines changed

2 files changed

+101
-90
lines changed

bindings/cpp/src/dynamic_vamana_index_impl.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,12 +448,19 @@ class DynamicVamanaIndexImpl {
448448
auto threadpool = default_threadpool();
449449

450450
svs::DistanceDispatcher distance_dispatcher(to_svs_distance(metric));
451+
452+
// Create allocator with custom block size for data loading
453+
auto parameters =
454+
svs::data::BlockingParameters{.blocksize_bytes = svs::lib::PowerOfTwo(26)};
455+
auto allocator = svs::data::Blocked<svs::lib::Allocator<std::byte>>{parameters};
456+
451457
return distance_dispatcher([&](auto&& distance) {
452458
return new svs::DynamicVamana(
453459
svs::DynamicVamana::assemble<float, storage::StorageType_t<Tag>>(
454460
stream,
455461
std::forward<decltype(distance)>(distance),
456-
std::move(threadpool)
462+
std::move(threadpool),
463+
allocator
457464
)
458465
);
459466
});

bindings/cpp/tests/runtime_test.cpp

Lines changed: 93 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,22 @@ inline const std::vector<float>& get_test_data() {
5757
return test_data;
5858
}
5959

60-
// Get current RSS (Resident Set Size) memory usage in bytes
6160
size_t get_current_rss() {
6261
std::ifstream statm("/proc/self/statm");
6362
if (!statm.is_open()) {
6463
return 0;
6564
}
6665
size_t vsize, rss;
6766
statm >> vsize >> rss;
68-
return rss * sysconf(_SC_PAGESIZE);
67+
size_t page_size = sysconf(_SC_PAGESIZE);
68+
return rss * page_size;
6969
}
7070

71+
struct UsageInfo {
72+
size_t file_size;
73+
size_t rss_increase;
74+
};
75+
7176
} // namespace
7277

7378
// Template function to write and read an index
@@ -130,6 +135,78 @@ void write_and_read_index(
130135
svs::runtime::v0::DynamicVamanaIndex::destroy(loaded);
131136
}
132137

138+
// Helper that writes and reads and index of requested size
139+
// Reports memory usage
140+
UsageInfo run_save_and_load_test(const size_t target_mibytes) {
141+
// Generate requested MiB of test data
142+
constexpr size_t mem_test_d = 128;
143+
const size_t target_bytes = target_mibytes * 1024 * 1024;
144+
const size_t mem_test_n = target_bytes / (mem_test_d * sizeof(float));
145+
146+
svs_test::prepare_temp_directory();
147+
auto temp_dir = svs_test::temp_directory();
148+
auto filename = temp_dir / "memory_test_index.bin";
149+
150+
{
151+
// Build Vamana FP32 index, scoped for memory cleanup
152+
auto large_test_data = create_test_data(mem_test_n, mem_test_d, 456);
153+
154+
// Add data to index
155+
std::vector<size_t> labels(mem_test_n);
156+
std::iota(labels.begin(), labels.end(), 0);
157+
158+
size_t mem_before = get_current_rss();
159+
svs::runtime::v0::DynamicVamanaIndex* index = nullptr;
160+
svs::runtime::v0::VamanaIndex::BuildParams build_params{64};
161+
svs::runtime::v0::Status status = svs::runtime::v0::DynamicVamanaIndex::build(
162+
&index,
163+
mem_test_d,
164+
svs::runtime::v0::MetricType::L2,
165+
svs::runtime::v0::StorageKind::FP32,
166+
build_params
167+
);
168+
CATCH_REQUIRE(status.ok());
169+
CATCH_REQUIRE(index != nullptr);
170+
status = index->add(mem_test_n, labels.data(), large_test_data.data());
171+
CATCH_REQUIRE(status.ok());
172+
173+
std::ofstream out(filename, std::ios::binary);
174+
CATCH_REQUIRE(out.is_open());
175+
status = index->save(out);
176+
CATCH_REQUIRE(status.ok());
177+
out.close();
178+
179+
svs::runtime::v0::DynamicVamanaIndex::destroy(index);
180+
index = nullptr;
181+
}
182+
183+
// Investigate the file size on disk
184+
size_t file_size = std::filesystem::file_size(filename);
185+
186+
// Load the index from disk
187+
std::ifstream in(filename, std::ios::binary);
188+
CATCH_REQUIRE(in.is_open());
189+
190+
// Monitor RSS increase
191+
size_t rss_before = get_current_rss();
192+
193+
svs::runtime::v0::DynamicVamanaIndex* loaded = nullptr;
194+
auto status = svs::runtime::v0::DynamicVamanaIndex::load(
195+
&loaded, in, svs::runtime::v0::MetricType::L2, svs::runtime::v0::StorageKind::FP32
196+
);
197+
CATCH_REQUIRE(status.ok());
198+
CATCH_REQUIRE(loaded != nullptr);
199+
in.close();
200+
201+
size_t rss_delta = get_current_rss() - rss_before;
202+
203+
// Clean up
204+
svs::runtime::v0::DynamicVamanaIndex::destroy(loaded);
205+
loaded = nullptr;
206+
207+
return {file_size, rss_delta};
208+
}
209+
133210
CATCH_TEST_CASE("WriteAndReadIndexSVS", "[runtime]") {
134211
const auto& test_data = get_test_data();
135212
auto build_func = [](svs::runtime::v0::DynamicVamanaIndex** index) {
@@ -377,94 +454,21 @@ CATCH_TEST_CASE("RangeSearchFunctional", "[runtime]") {
377454
}
378455

379456
CATCH_TEST_CASE("MemoryUsageOnLoad", "[runtime][memory]") {
380-
// Generate some MiB of test data
381-
constexpr size_t mem_test_d = 128;
382-
constexpr size_t target_mibytes = 2;
383-
constexpr size_t target_bytes = target_mibytes * 1024 * 1024;
384-
constexpr size_t mem_test_n = target_bytes / (mem_test_d * sizeof(float));
385-
386-
std::cout << "Generating " << mem_test_n << " vectors of dimension " << mem_test_d
387-
<< " (approx " << (mem_test_n * mem_test_d * sizeof(float)) / (1024 * 1024)
388-
<< " MiB)" << std::endl;
389-
390-
// Save the index to a file
391-
svs_test::prepare_temp_directory();
392-
auto temp_dir = svs_test::temp_directory();
393-
auto filename = temp_dir / "memory_test_index.bin";
394-
395-
{
396-
// Build Vamana FP32 index, scoped for memory cleanup
397-
auto large_test_data = create_test_data(mem_test_n, mem_test_d, 456);
398-
399-
svs::runtime::v0::DynamicVamanaIndex* index = nullptr;
400-
svs::runtime::v0::VamanaIndex::BuildParams build_params{64};
401-
svs::runtime::v0::Status status = svs::runtime::v0::DynamicVamanaIndex::build(
402-
&index,
403-
mem_test_d,
404-
svs::runtime::v0::MetricType::L2,
405-
svs::runtime::v0::StorageKind::FP32,
406-
build_params
407-
);
408-
CATCH_REQUIRE(status.ok());
409-
CATCH_REQUIRE(index != nullptr);
410-
411-
// Add data to index
412-
std::vector<size_t> labels(mem_test_n);
413-
std::iota(labels.begin(), labels.end(), 0);
414-
status = index->add(mem_test_n, labels.data(), large_test_data.data());
415-
CATCH_REQUIRE(status.ok());
416-
417-
std::ofstream out(filename, std::ios::binary);
418-
CATCH_REQUIRE(out.is_open());
419-
status = index->save(out);
420-
CATCH_REQUIRE(status.ok());
421-
out.close();
422-
423-
// Clean up the first index
424-
svs::runtime::v0::DynamicVamanaIndex::destroy(index);
425-
index = nullptr;
457+
CATCH_SECTION("SmallIndex") {
458+
auto stats = run_save_and_load_test(10);
459+
CATCH_REQUIRE(stats.file_size < 20 * 1024 * 1024);
460+
CATCH_REQUIRE(stats.rss_increase < 1.2 * stats.file_size);
426461
}
427462

428-
// Investigate the file size on disk
429-
size_t file_size = std::filesystem::file_size(filename);
430-
std::cout << "Index file size on disk: " << file_size / (1024 * 1024) << " MiB ("
431-
<< file_size << " bytes)" << std::endl;
432-
433-
// Load the index from disk
434-
std::ifstream in(filename, std::ios::binary);
435-
CATCH_REQUIRE(in.is_open());
436-
437-
// Snapshot current memory usage before loading
438-
size_t memory_before = get_current_rss();
439-
std::cout << "Memory before load: " << memory_before / (1024 * 1024) << " MiB"
440-
<< std::endl;
441-
442-
svs::runtime::v0::DynamicVamanaIndex* loaded = nullptr;
443-
auto status = svs::runtime::v0::DynamicVamanaIndex::load(
444-
&loaded, in, svs::runtime::v0::MetricType::L2, svs::runtime::v0::StorageKind::FP32
445-
);
446-
CATCH_REQUIRE(status.ok());
447-
CATCH_REQUIRE(loaded != nullptr);
448-
in.close();
449-
450-
// Snapshot memory usage after loading
451-
size_t memory_after = get_current_rss();
452-
std::cout << "Memory after load: " << memory_after / (1024 * 1024) << " MiB"
453-
<< std::endl;
454-
455-
// Calculate memory increase
456-
size_t memory_increase = memory_after - memory_before;
457-
std::cout << "Memory increase: " << memory_increase / (1024 * 1024) << " MiB ("
458-
<< memory_increase << " bytes)" << std::endl;
459-
460-
// Assert that no more than 140% of file size on disk were allocated
461-
size_t max_allowed_memory = static_cast<size_t>(file_size * 1.4);
462-
std::cout << "Max allowed memory (140% of file size): "
463-
<< max_allowed_memory / (1024 * 1024) << " MiB (" << max_allowed_memory
464-
<< " bytes)" << std::endl;
465-
466-
CATCH_REQUIRE(memory_increase <= max_allowed_memory);
463+
CATCH_SECTION("MediumIndex") {
464+
auto stats = run_save_and_load_test(50);
465+
CATCH_REQUIRE(stats.file_size < 100 * 1024 * 1024);
466+
CATCH_REQUIRE(stats.rss_increase < 1.2 * stats.file_size);
467+
}
467468

468-
// Clean up
469-
svs::runtime::v0::DynamicVamanaIndex::destroy(loaded);
469+
CATCH_SECTION("LargeIndex") {
470+
auto stats = run_save_and_load_test(200);
471+
CATCH_REQUIRE(stats.file_size < 400 * 1024 * 1024);
472+
CATCH_REQUIRE(stats.rss_increase < 1.2 * stats.file_size);
473+
}
470474
}

0 commit comments

Comments
 (0)