Skip to content

[diskann-garnet] Implement XVCREATE, XVIMPORT - #1455

Open
Jack Moffitt (metajack) wants to merge 1 commit into
mainfrom
push-ttwwvqlmswws
Open

Jack Moffitt (metajack) wants to merge 1 commit into
mainfrom
push-ttwwvqlmswws

Conversation

@metajack

Copy link
Copy Markdown
Contributor

This PR adds direct import of externally stored diskann graphs to Garnet. This can be useful for interoperating with indices created with other DiskANN systems.

It adds two new commands, XVCREATE to create a vector set without doing a VADD, and XVIMPORT to directly import index terms to a vector set. To make quantizer state compatible, XVCREATE allows directly specifying the quantizer state.

Finalization of import checks that all required terms are present and have sensical sizes, but does not verify quantize vectors match unquantized vectors or that the neighbor lists make sense. It is expected that the graph is correctly constructed in the external system.

This currently requires that the internal ID 0 not be used in the graph since it will get used by the start point once the graph is imported.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Arbitrary-ID imports, malformed neighbor counts, reserved-ID mappings, and quantizer-state replacement can currently corrupt or fail imported indexes.

Review effort: Balanced
Findings: 4 High severity · 2 Low severity

Open (6)
What changed in this PR

Adds bulk import support for externally generated DiskANN graphs through new Garnet FFI operations.

Changes:

  • Adds quantizer-state injection and term import/finalization APIs.
  • Persists import eligibility and validates imported graph terms.
  • Adds import tests, documentation, and a patch version bump.
File Description
Cargo.lock Updates the package version.
diskann-garnet/​Cargo.toml Bumps the crate version.
diskann-garnet/​diskann-garnet.nuspec Bumps the NuGet version.
diskann-garnet/​README.md Documents bulk import usage.
diskann-garnet/​docs/​ffi-design.rs Documents import FFI APIs.
diskann-garnet/​docs/​data-design.md Documents imported-term storage.
diskann-garnet/​src/​dyn_index.rs Exposes import operations through DynIndex.
diskann-garnet/​src/​ffi_tests.rs Adds import and FFI validation tests.
diskann-garnet/​src/​fsm.rs Adds explicit internal-ID claiming.
diskann-garnet/​src/​garnet.rs Adds term conversion and existence checks.
diskann-garnet/​src/​lib.rs Exposes import-related C APIs.
diskann-garnet/​src/​provider.rs Implements import gating, validation, and finalization.
diskann-garnet/​src/​quantization.rs Supports externally supplied quantizer state.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread diskann-garnet/src/fsm.rs
Comment on lines +374 to +381
let mut id_minter = self.id_minter.write().unwrap();
let max_id = id_minter.next_id.saturating_sub(1);

if id > max_id {
// NOTE: expand_to will modify max_block if needed.
self.expand_to(&mut id_minter, ctx, id)?;
id_minter.next_id = id + 1;
}
Comment on lines +833 to +837
pub(crate) fn set_quant_state(&self, context: &Context, state: &[u8]) -> bool {
// NOTE: We change the quantizer before persisting to Garnet because if anything
// fails, the vector set will be thrown away.
if let Some(quantizer) = &self.quantizer
&& quantizer.deserialize(state).is_ok()
Comment on lines +937 to +939
Term::Neighbors => {
value.len() == (self.max_degree + 1) * mem::size_of::<u32>()
}
Comment on lines +963 to +970
Term::IntMap => {
if value.len() != mem::size_of::<u32>() {
return false;
}

let eid = GarnetId::from(id);
self.callbacks.write_eid(&context.term(term), &eid, value)
}
Comment thread diskann-garnet/README.md

At the FFI layer, `can_import` checks eligibility.

Indices created with `XVCREATE` are eligible for import until import finalization is complete.
Comment thread diskann-garnet/docs/data-design.md Outdated
Comment thread diskann-garnet/src/ffi_tests.rs Dismissed
Comment thread diskann-garnet/src/ffi_tests.rs Dismissed
Comment thread diskann-garnet/src/ffi_tests.rs Dismissed
Comment thread diskann-garnet/src/lib.rs
state: *const u8,
state_len: usize,
) -> bool {
let index = unsafe { &*index_ptr.cast::<Index>() };
Comment thread diskann-garnet/src/lib.rs
/// `index_ptr` must be a live index returned by `create_index`, and `ctx` must identify its storage.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn can_import(ctx: u64, index_ptr: *const c_void) -> bool {
let index = unsafe { &*index_ptr.cast::<Index>() };
Comment thread diskann-garnet/src/lib.rs
value: *const u8,
value_len: usize,
) -> bool {
let index = unsafe { &*index_ptr.cast::<Index>() };
Comment thread diskann-garnet/src/lib.rs
task_idx: usize,
task_count: usize,
) -> u8 {
let index = unsafe { &*index_ptr.cast::<Index>() };
@codecov-commenter

Codecov Comments Bot (codecov-commenter) commented Sep 30, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.74576% with 72 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.93%. Comparing base (a3c1d74) to head (d99ff9a).

Files with missing lines Patch % Lines
diskann-garnet/src/provider.rs 85.49% 37 Missing ⚠️
diskann-garnet/src/dyn_index.rs 72.46% 19 Missing ⚠️
diskann-garnet/src/lib.rs 87.75% 12 Missing ⚠️
diskann-garnet/src/quantization.rs 90.00% 4 Missing ⚠️

❌ Your patch status has failed because the patch coverage (84.74%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1455      +/-   ##
==========================================
- Coverage   90.93%   90.93%   -0.01%     
==========================================
  Files         583      583              
  Lines      116854   117286     +432     
==========================================
+ Hits       106266   106652     +386     
- Misses      10588    10634      +46     
Flag Coverage Δ
miri 90.93% <84.74%> (-0.01%) ⬇️
unittests 90.62% <84.74%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
diskann-garnet/src/fsm.rs 94.86% <100.00%> (+0.34%) ⬆️
diskann-garnet/src/quantization.rs 96.85% <90.00%> (-0.06%) ⬇️
diskann-garnet/src/lib.rs 93.89% <87.75%> (-0.51%) ⬇️
diskann-garnet/src/dyn_index.rs 79.60% <72.46%> (-3.99%) ⬇️
diskann-garnet/src/provider.rs 87.00% <85.49%> (-0.02%) ⬇️

... and 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@metajack
Jack Moffitt (metajack) added this pull request to stack #1466 October 6, 2026 19:44

This branch has not been deployed

No deployments
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.

4 participants