microsoft/DiskANN v0.50.0
microsoft/DiskANN
Captured source
source ↗DiskANN v0.50.0
Repository: microsoft/DiskANN
Tag: v0.50.0
Published: 2026-03-31T16:14:11Z
Prerelease: no
Release notes: Release notes generated with the help of Copilot.
API Breaking Changes
This release contains several large API changes that should be mechanical to apply to existing code but that will enable forward evolution of our integrations.
WorkingSet/Fillset/Strategy API Changes (#859)
Removals
The following items have been removed:
| Removed | Replacement | |--------|--------------| | Fill | diskann::graph::workingset::Fill and diskann::graph::workingset::Map | | AsElement | diskann::graph::glue::MultiInsertStrategy::finish and diskann::graph::workingset::AsWorkingSet | | Accessor::Extended | Just gone! | | VectorIdBoxSlice | diskann::graph::glue::Batch (and Matrix) | | reborrow::Lower/AsyncLower | No longer needed |
Strategy Type Parameters (no longer ?Sized)
The T parameter on SearchStrategy, InsertStrategy, and SetElement is no longer ?Sized.
// Before
impl SearchStrategy for MyStrategy { ... }
impl SetElement for MyProvider { ... }
// After
impl SearchStrategy for MyStrategy { ... }
impl SetElement for MyProvider { ... }HRTB syntax is now generally needed, but makes contraints far more uniform.
Similarly, InplaceDeleteStrategy::DeleteElement has been tightened from Send + Sync + ?Sized to Copy + Send + Sync (sized). If your delete element was an unsized type like [f32], change it to a reference like &'a [f32].
Guard moved from SetElement to DataProvider
// Before
trait SetElement: DataProvider {
type Guard: Guard;
...
}
// After
trait DataProvider {
type Guard: Guard + 'static;
...
}
trait SetElement: DataProvider {
// Returns Self::Guard from DataProvider
fn set_element(...) -> Result;
}Move your Guard associated type from your SetElement impl to your DataProvider impl.
PruneStrategy gains WorkingSet
// Before
trait PruneStrategy {
type PruneAccessor: Accessor + ... + FillSet;
...
}
// After
trait PruneStrategy {
type WorkingSet: Send + Sync;
type PruneAccessor: Accessor + ... + workingset::Fill;
fn create_working_set(&self, capacity: usize) -> Self::WorkingSet;
...
}What to do: 1. Add a WorkingSet associated type. Use workingset::Map> as the default. Users of multi-insert will want to use workingset::Map, workingset::map::Ref>. 3. Add create_working_set returning a Map via Builder::new(Capacity::Default).build(capacity). 4. Replace FillSet bound on PruneAccessor with workingset::Fill.
FillSet to Fill
// Before
impl FillSet for MyAccessor {
fn fill_set(&mut self, ids: &[Id], map: &mut HashMap) -> Result { ... }
}
// After
impl Fill for MyAccessor {
type Error = ...;
type View = ... where Self: 'a, MyWorkingSet: 'a;
fn fill(
&'a mut self,
working_set: &'a mut MyWorkingSet,
itr: Itr,
) -> impl SendFuture, Self::Error>>
where
Itr: ExactSizeIterator + Clone + Send + Sync,
{ ... }
}Shortcut: If your WorkingSet is workingset::Map and your accessor's ElementRef converts Into, the blanket Fill impl works automatically, then you don't need to implement Fill at all.
New MultiInsertStrategy (replaces multi-insert portion of InsertStrategy)
If you use multi_insert, you now need a MultiInsertStrategy implementation:
trait MultiInsertStrategy: Send + Sync {
type WorkingSet: Send + Sync + 'static;
type Seed: AsWorkingSet + Send + Sync + 'static;
type FinishError: Into + std::fmt::Debug + Send + Sync;
type InsertStrategy: for InsertStrategy,
PruneStrategy: PruneStrategy,
>;
fn insert_strategy(&self) -> Self::InsertStrategy;
fn finish(&self, provider: &Provider, context: &Provider::Context,
batch: &Arc, ids: Itr,
) -> impl Future> + Send
where Itr: ExactSizeIterator + Send;
}What to do:
finishis called once after the batch is inserted. Use it to pre-populate working set
state (e.g., fetch quantized representations). Return a Seed that implements AsWorkingSet.
- For the common case, use
workingset::map::Builderas yourSeedtype. multi_insertnow takesArcwhereB: Batchinstead ofVectorIdBoxSlice.
Matrix implements Batch out of the box.
Using diskann::graph::workingset::Map and its associated infrastructure should largely work.
multi_insert call site
// Before index.multi_insert(strategy, context, vectors, ids).await?; // where vectors: VectorIdBoxSlice // After index.multi_insert::(strategy, context, vectors, ids).await?; // where vectors: Arc, B: Batch // DP: for SetElement> is required
The turbofish `` is often needed because HRTB bounds make inference conservative.
Search Post Processing (#828)
The Search trait now requires S: SearchStrategy at the trait level, and introduces two new generic parameters on the search method:
O- the output type written to the buffer (used to be a parameter ofSearchStrategy)PP— the post-processor, bounded byfor SearchPostProcess, T, O> + Send + SyncOB— the output buffer, bounded bySearchOutputBuffer + Send + ?Sized
Previously, OB was a trait-level generic and the post-processor was obtained internally from the strategy. Now both are method-level generics, giving callers control over each independently.
The output "id" type O has been removed from SearchStrategy entirely, which greatly simplifies things.
At the DiskANNIndex level, two entry points are provided:
search()— requiresS: DefaultPostProcessor, creates the strategy's default processor automatically, then delegates tosearch_with(). This is the common path.search_with()— requires onlyS: SearchStrategy, accepts any compatiblePP. This is the extension point for custom post-processing.
DefaultPostProcessor
Strategies opt in to default post-processing by implementing DefaultPostProcessor:
pub trait DefaultPostProcessor: SearchStrategy {
type Processor: for SearchPostProcess, T, O> + Send + Sync;
fn default_post_processor(&self) -> Self::Processor;
}The default_post_processor! macro covers the common case where the processor is Default-constructible. DefaultSearchStrategy is a convenience trait (with a blanket impl…) for SearchStrategy + DefaultPostProcessor.
Start-point filtering
The in-mem code used to rely on a special Internal type to customize post-processing for the inplace...
Excerpt shown — open the source for the full document.