Skip to content

Conversation

@Giulio2002
Copy link

@Giulio2002 Giulio2002 commented Dec 11, 2025

Lazy loading support

First of all, most of the LOC are just to integrate it with the examples so that we can easily test regressions and if there is any memory improvement at all. the actual library diff is very tiny in comparison. I apologise in advance and we can split it into multiple PRs. We can also just revert the examples and make the feature small

Summary

Adds FeatureStore<T> trait who abstracts feature vector storage, enabling lazy loading from disk, mmap, or custom backends/whatever you want. The default implementation uses Vec<T> for backward compatibility. This PR also adds new_with_storage and new_with_storage_and_params constructors, updates the recall examples with mmap-based storage demonstrations, and fixes a bug in copy_from_slice where the destination slice wasn't properly sized.

Motivation

Previously, all feature vectors were stored in a Vec<T> in memory. For large datasets, this can exceed available RAM. The FeatureStore trait allows users to provide custom storage backends that could:

  • Memory-map files for larger-than-RAM datasets
  • Use disk-backed storage with custom access patterns
  • actually build a fully fledged Vector database quite easily just by exposing this new change without worrying about the underlying data structure.

note: that all api changes are backward compatible (i think)

There was also a small bug which I also uncovered while testing the recall examples:

In src/hnsw/hnsw_const.rs, the nearest method had incorrect copy_from_slice calls that would panic when the destination buffer was larger than the number of results found:

This bug would trigger when Searching with an amount of neighbors requested but with fewer results available (not sure if this was a bug before but I checked and seems everything work separately).

Benchmarks - Recall

This stayed identical, I am going to post the gnuplots for completeness. below are the Vec based plots

Screenshot 2025-12-11 at 19 24 39

Discrete:

Screenshot 2025-12-11 at 19 22 38

Mmap plots:

Screenshot 2025-12-11 at 19 31 36 Screenshot 2025-12-11 at 19 39 41

Benchmarks - Memory

Tested with 1 million 128-dimensional f32 vectors (512 bytes per feature):

Storage Backend Memory Used
Vec (default) 1.30 GB
DiskFeatureStore 215.77 MB

To prove the usefulness of the lazy loading, I benchmarked the results on the RAM consumption. The disk-based storage reduces memory usage by ~83%. As a matter of fact, the disk-based backend, only the graph structure remains in memory, bringing total usage down to ~216 MB.

These results are expected to scale linearly. a 100MN vector index cannot be stored on a laptop if you keep it in memory as it would be 130 GB, however, with lazy loading, you can store on 32 GB machine >100MN and if you had access to 130 GB, you could store around 0.5 Billion vectors.

@Giulio2002 Giulio2002 marked this pull request as draft December 11, 2025 15:24
@Giulio2002 Giulio2002 marked this pull request as ready for review December 11, 2025 19:21
@Giulio2002 Giulio2002 changed the title feat: added lazy loading. WIP feat: added lazy loading. Dec 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant