From 98a70f53a8ea96954384bb56307a488d263eaf14 Mon Sep 17 00:00:00 2001 From: backurs Date: Thu, 5 Feb 2026 13:04:32 -0800 Subject: [PATCH 1/7] save max_record_size and leaf_page_size --- .../graph/provider/async_/bf_tree/provider.rs | 68 +++++++++++++++---- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs index 6ed94989c..9c4633793 100644 --- a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs +++ b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs @@ -1778,11 +1778,18 @@ where } } +#[derive(Serialize, Deserialize, Clone)] +pub struct BfTreeParams { + pub bytes: usize, + pub max_record_size: usize, + pub leaf_page_size: usize, +} + #[derive(Serialize, Deserialize, Clone)] pub struct QuantParams { pub num_pq_bytes: usize, pub max_fp_vecs_per_fill: usize, - pub bytes_quant: usize, + pub params_quant: BfTreeParams, } #[derive(Serialize, Deserialize, Clone)] @@ -1793,8 +1800,8 @@ pub struct SavedParams { pub metric: String, pub max_degree: u32, pub prefix: String, - pub bytes_vector: usize, - pub bytes_neighbor: usize, + pub params_vector: BfTreeParams, + pub params_neighbor: BfTreeParams, pub quant_params: Option, } @@ -1903,11 +1910,15 @@ where .map_err(|e| ANNError::log_index_error(format!("Failed to parse metric: {}", e)))?; let vector_path = BfTreePaths::vectors_bftree(&saved_params.prefix); - let mut vector_config = Config::new(&vector_path, saved_params.bytes_vector); + let mut vector_config = Config::new(&vector_path, saved_params.params_vector.bytes); + vector_config.cb_max_record_size(saved_params.params_vector.max_record_size); + vector_config.leaf_page_size(saved_params.params_vector.leaf_page_size); vector_config.storage_backend(bf_tree::StorageBackend::Std); let neighbor_path = BfTreePaths::neighbors_bftree(&saved_params.prefix); - let mut neighbor_config = Config::new(&neighbor_path, saved_params.bytes_neighbor); + let mut neighbor_config = Config::new(&neighbor_path, saved_params.params_neighbor.bytes); + neighbor_config.cb_max_record_size(saved_params.params_neighbor.max_record_size); + neighbor_config.leaf_page_size(saved_params.params_neighbor.leaf_page_size); neighbor_config.storage_backend(bf_tree::StorageBackend::Std); let vector_index = @@ -2036,15 +2047,21 @@ where .map_err(|e| ANNError::log_index_error(format!("Failed to parse metric: {}", e)))?; let vector_path = BfTreePaths::vectors_bftree(&saved_params.prefix); - let mut vector_config = Config::new(&vector_path, saved_params.bytes_vector); + let mut vector_config = Config::new(&vector_path, saved_params.params_vector.bytes); + vector_config.cb_max_record_size(saved_params.params_vector.max_record_size); + vector_config.leaf_page_size(saved_params.params_vector.leaf_page_size); vector_config.storage_backend(bf_tree::StorageBackend::Std); let neighbor_path = BfTreePaths::neighbors_bftree(&saved_params.prefix); - let mut neighbor_config = Config::new(&neighbor_path, saved_params.bytes_neighbor); + let mut neighbor_config = Config::new(&neighbor_path, saved_params.params_neighbor.bytes); + neighbor_config.cb_max_record_size(saved_params.params_neighbor.max_record_size); + neighbor_config.leaf_page_size(saved_params.params_neighbor.leaf_page_size); neighbor_config.storage_backend(bf_tree::StorageBackend::Std); let quant_path = BfTreePaths::quant_bftree(&saved_params.prefix); - let mut quant_config = Config::new(&quant_path, quant_params.bytes_quant); + let mut quant_config = Config::new(&quant_path, quant_params.params_quant.bytes); + quant_config.cb_max_record_size(quant_params.params_quant.max_record_size); + quant_config.leaf_page_size(quant_params.params_quant.leaf_page_size); quant_config.storage_backend(bf_tree::StorageBackend::Std); let vector_index = @@ -2333,6 +2350,8 @@ mod tests { let bytes_vector = 1024 * 1024; let mut vector_config = Config::new(&vector_path, bytes_vector); + vector_config.leaf_page_size(8192); + vector_config.cb_max_record_size(1024); vector_config.storage_backend(bf_tree::StorageBackend::Std); let bytes_neighbor = 1024 * 1024; @@ -2391,6 +2410,9 @@ mod tests { ); } + assert_eq!(vector_config.get_leaf_page_size(), 8192); + assert_eq!(vector_config.get_cb_max_record_size(), 1024); + let storage = FileStorageProvider; let metric_str = params.metric.as_str(); @@ -2401,8 +2423,16 @@ mod tests { metric: metric_str.to_string(), max_degree: params.max_degree, prefix: prefix.clone(), - bytes_vector, - bytes_neighbor, + params_vector: BfTreeParams { + bytes: bytes_vector, + leaf_page_size: vector_config.get_leaf_page_size(), + max_record_size: vector_config.get_cb_max_record_size(), + }, + params_neighbor: BfTreeParams { + bytes: bytes_neighbor, + leaf_page_size: neighbor_config.get_leaf_page_size(), + max_record_size: neighbor_config.get_cb_max_record_size(), + }, quant_params: None, }; @@ -2584,12 +2614,24 @@ mod tests { metric: metric_str.to_string(), max_degree: params.max_degree, prefix: prefix.clone(), - bytes_vector, - bytes_neighbor, + params_vector: BfTreeParams { + bytes: bytes_vector, + leaf_page_size: vector_config.get_leaf_page_size(), + max_record_size: vector_config.get_cb_max_record_size(), + }, + params_neighbor: BfTreeParams { + bytes: bytes_neighbor, + leaf_page_size: neighbor_config.get_leaf_page_size(), + max_record_size: neighbor_config.get_cb_max_record_size(), + }, quant_params: Some(QuantParams { num_pq_bytes, max_fp_vecs_per_fill: params.max_fp_vecs_per_fill.unwrap_or(0), - bytes_quant, + params_quant: BfTreeParams { + bytes: bytes_quant, + leaf_page_size: quant_config.get_leaf_page_size(), + max_record_size: quant_config.get_cb_max_record_size(), + }, }), }; From 10673e9a7c344ad39097b548a5e2d9358a67107b Mon Sep 17 00:00:00 2001 From: backurs Date: Thu, 5 Feb 2026 16:01:13 -0800 Subject: [PATCH 2/7] apply function to simplify the code --- .../graph/provider/async_/bf_tree/provider.rs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs index 9c4633793..cc18bb7bc 100644 --- a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs +++ b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs @@ -1785,6 +1785,14 @@ pub struct BfTreeParams { pub leaf_page_size: usize, } +impl BfTreeParams { + /// Apply the saved BfTree parameters to a Config. + pub fn apply(&self, config: &mut Config) { + config.cb_max_record_size(self.max_record_size); + config.leaf_page_size(self.leaf_page_size); + } +} + #[derive(Serialize, Deserialize, Clone)] pub struct QuantParams { pub num_pq_bytes: usize, @@ -1911,14 +1919,12 @@ where let vector_path = BfTreePaths::vectors_bftree(&saved_params.prefix); let mut vector_config = Config::new(&vector_path, saved_params.params_vector.bytes); - vector_config.cb_max_record_size(saved_params.params_vector.max_record_size); - vector_config.leaf_page_size(saved_params.params_vector.leaf_page_size); + saved_params.params_vector.apply(&mut vector_config); vector_config.storage_backend(bf_tree::StorageBackend::Std); let neighbor_path = BfTreePaths::neighbors_bftree(&saved_params.prefix); let mut neighbor_config = Config::new(&neighbor_path, saved_params.params_neighbor.bytes); - neighbor_config.cb_max_record_size(saved_params.params_neighbor.max_record_size); - neighbor_config.leaf_page_size(saved_params.params_neighbor.leaf_page_size); + saved_params.params_neighbor.apply(&mut neighbor_config); neighbor_config.storage_backend(bf_tree::StorageBackend::Std); let vector_index = @@ -2048,20 +2054,17 @@ where let vector_path = BfTreePaths::vectors_bftree(&saved_params.prefix); let mut vector_config = Config::new(&vector_path, saved_params.params_vector.bytes); - vector_config.cb_max_record_size(saved_params.params_vector.max_record_size); - vector_config.leaf_page_size(saved_params.params_vector.leaf_page_size); + saved_params.params_vector.apply(&mut vector_config); vector_config.storage_backend(bf_tree::StorageBackend::Std); let neighbor_path = BfTreePaths::neighbors_bftree(&saved_params.prefix); let mut neighbor_config = Config::new(&neighbor_path, saved_params.params_neighbor.bytes); - neighbor_config.cb_max_record_size(saved_params.params_neighbor.max_record_size); - neighbor_config.leaf_page_size(saved_params.params_neighbor.leaf_page_size); + saved_params.params_neighbor.apply(&mut neighbor_config); neighbor_config.storage_backend(bf_tree::StorageBackend::Std); let quant_path = BfTreePaths::quant_bftree(&saved_params.prefix); let mut quant_config = Config::new(&quant_path, quant_params.params_quant.bytes); - quant_config.cb_max_record_size(quant_params.params_quant.max_record_size); - quant_config.leaf_page_size(quant_params.params_quant.leaf_page_size); + quant_params.params_quant.apply(&mut quant_config); quant_config.storage_backend(bf_tree::StorageBackend::Std); let vector_index = From b37cc0e1577c29a76b55692ed7dbaaf2db567642 Mon Sep 17 00:00:00 2001 From: backurs Date: Thu, 5 Feb 2026 16:47:47 -0800 Subject: [PATCH 3/7] apply -> create change --- .../graph/provider/async_/bf_tree/provider.rs | 45 +++++++++---------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs index cc18bb7bc..da5a26bae 100644 --- a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs +++ b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs @@ -1786,10 +1786,13 @@ pub struct BfTreeParams { } impl BfTreeParams { - /// Apply the saved BfTree parameters to a Config. - pub fn apply(&self, config: &mut Config) { + /// Build a BfTree Config from the saved parameters and a file path. + pub fn to_config(&self, path: &std::path::Path) -> Config { + let mut config = Config::new(path, self.bytes); config.cb_max_record_size(self.max_record_size); config.leaf_page_size(self.leaf_page_size); + config.storage_backend(bf_tree::StorageBackend::Std); + config } } @@ -1917,15 +1920,12 @@ where let metric = Metric::from_str(&saved_params.metric) .map_err(|e| ANNError::log_index_error(format!("Failed to parse metric: {}", e)))?; - let vector_path = BfTreePaths::vectors_bftree(&saved_params.prefix); - let mut vector_config = Config::new(&vector_path, saved_params.params_vector.bytes); - saved_params.params_vector.apply(&mut vector_config); - vector_config.storage_backend(bf_tree::StorageBackend::Std); - - let neighbor_path = BfTreePaths::neighbors_bftree(&saved_params.prefix); - let mut neighbor_config = Config::new(&neighbor_path, saved_params.params_neighbor.bytes); - saved_params.params_neighbor.apply(&mut neighbor_config); - neighbor_config.storage_backend(bf_tree::StorageBackend::Std); + let vector_config = saved_params + .params_vector + .to_config(&BfTreePaths::vectors_bftree(&saved_params.prefix)); + let neighbor_config = saved_params + .params_neighbor + .to_config(&BfTreePaths::neighbors_bftree(&saved_params.prefix)); let vector_index = BfTree::new_from_snapshot(vector_config.clone(), None).map_err(super::ConfigError)?; @@ -2052,20 +2052,15 @@ where let metric = Metric::from_str(&saved_params.metric) .map_err(|e| ANNError::log_index_error(format!("Failed to parse metric: {}", e)))?; - let vector_path = BfTreePaths::vectors_bftree(&saved_params.prefix); - let mut vector_config = Config::new(&vector_path, saved_params.params_vector.bytes); - saved_params.params_vector.apply(&mut vector_config); - vector_config.storage_backend(bf_tree::StorageBackend::Std); - - let neighbor_path = BfTreePaths::neighbors_bftree(&saved_params.prefix); - let mut neighbor_config = Config::new(&neighbor_path, saved_params.params_neighbor.bytes); - saved_params.params_neighbor.apply(&mut neighbor_config); - neighbor_config.storage_backend(bf_tree::StorageBackend::Std); - - let quant_path = BfTreePaths::quant_bftree(&saved_params.prefix); - let mut quant_config = Config::new(&quant_path, quant_params.params_quant.bytes); - quant_params.params_quant.apply(&mut quant_config); - quant_config.storage_backend(bf_tree::StorageBackend::Std); + let vector_config = saved_params + .params_vector + .to_config(&BfTreePaths::vectors_bftree(&saved_params.prefix)); + let neighbor_config = saved_params + .params_neighbor + .to_config(&BfTreePaths::neighbors_bftree(&saved_params.prefix)); + let quant_config = quant_params + .params_quant + .to_config(&BfTreePaths::quant_bftree(&saved_params.prefix)); let vector_index = BfTree::new_from_snapshot(vector_config.clone(), None).map_err(super::ConfigError)?; From b31f00db639ea453c7901d479434c6e0ad9c8728 Mon Sep 17 00:00:00 2001 From: backurs Date: Sat, 7 Feb 2026 16:10:46 -0800 Subject: [PATCH 4/7] pass less parameters to save_with --- .../graph/provider/async_/bf_tree/provider.rs | 117 +++++++++++++----- 1 file changed, 88 insertions(+), 29 deletions(-) diff --git a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs index da5a26bae..22c8e6c6f 100644 --- a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs +++ b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs @@ -1816,6 +1816,26 @@ pub struct SavedParams { pub quant_params: Option, } +#[derive(Serialize, Deserialize, Clone)] +pub struct BfTreeParamsInput { + pub bytes: usize, + pub max_record_size: usize, + pub leaf_page_size: usize, +} + +#[derive(Serialize, Deserialize, Clone)] +pub struct QuantParamsInput { + pub params_quant: BfTreeParamsInput, +} + +#[derive(Serialize, Deserialize, Clone)] +pub struct SavedParamsInput { + pub prefix: String, + pub params_vector: BfTreeParamsInput, + pub params_neighbor: BfTreeParamsInput, + pub quant_params: Option, +} + /// Helper struct for generating consistent file paths for BfTreeProvider persistence. /// Centralizes all path patterns to avoid hardcoded strings throughout the codebase. pub struct BfTreePaths; @@ -1854,7 +1874,7 @@ impl BfTreePaths { // SaveWith/LoadWith for BfTreeProvider with TableDeleteProviderAsync -impl SaveWith for BfTreeProvider +impl SaveWith for BfTreeProvider where T: VectorRepr, { @@ -1864,15 +1884,36 @@ where async fn save_with

( &self, storage: &P, - saved_params: &SavedParams, + saved_params_input: &SavedParamsInput, ) -> Result where P: StorageWriteProvider, { + let saved_params = SavedParams { + max_points: self.max_points(), + frozen_points: NonZeroUsize::new(self.num_start_points()) + .ok_or_else(|| ANNError::log_index_error("num_start_points is zero"))?, + dim: self.dim(), + metric: self.metric().as_str().to_string(), + max_degree: self.max_degree(), + prefix: saved_params_input.prefix.clone(), + params_vector: BfTreeParams { + bytes: saved_params_input.params_vector.bytes, + max_record_size: saved_params_input.params_vector.max_record_size, + leaf_page_size: saved_params_input.params_vector.leaf_page_size, + }, + params_neighbor: BfTreeParams { + bytes: saved_params_input.params_neighbor.bytes, + max_record_size: saved_params_input.params_neighbor.max_record_size, + leaf_page_size: saved_params_input.params_neighbor.leaf_page_size, + }, + quant_params: None, // No quantization parameters + }; + // Save only essential parameters as JSON { let params_filename = BfTreePaths::params_json(&saved_params.prefix); - let params_json = serde_json::to_string(saved_params).map_err(|e| { + let params_json = serde_json::to_string(&saved_params).map_err(|e| { ANNError::log_index_error(format!("Failed to serialize params: {}", e)) })?; let mut params_writer = storage.create_for_write(¶ms_filename)?; @@ -1967,7 +2008,8 @@ where } } -impl SaveWith for BfTreeProvider +impl SaveWith + for BfTreeProvider where T: VectorRepr, { @@ -1977,15 +2019,47 @@ where async fn save_with

( &self, storage: &P, - saved_params: &SavedParams, + saved_params_input: &SavedParamsInput, ) -> Result where P: StorageWriteProvider, { + let saved_params = SavedParams { + max_points: self.max_points(), + frozen_points: NonZeroUsize::new(self.num_start_points()) + .ok_or_else(|| ANNError::log_index_error("num_start_points is zero"))?, + dim: self.dim(), + metric: self.metric().as_str().to_string(), + max_degree: self.max_degree(), + prefix: saved_params_input.prefix.clone(), + params_vector: BfTreeParams { + bytes: saved_params_input.params_vector.bytes, + max_record_size: saved_params_input.params_vector.max_record_size, + leaf_page_size: saved_params_input.params_vector.leaf_page_size, + }, + params_neighbor: BfTreeParams { + bytes: saved_params_input.params_neighbor.bytes, + max_record_size: saved_params_input.params_neighbor.max_record_size, + leaf_page_size: saved_params_input.params_neighbor.leaf_page_size, + }, + quant_params: saved_params_input + .quant_params + .as_ref() + .map(|qp| QuantParams { + num_pq_bytes: self.quant_vectors.pq_chunks(), + max_fp_vecs_per_fill: self.max_fp_vecs_per_fill, + params_quant: BfTreeParams { + bytes: qp.params_quant.bytes, + max_record_size: qp.params_quant.max_record_size, + leaf_page_size: qp.params_quant.leaf_page_size, + }, + }), + }; + // Save only essential parameters as JSON { let params_filename = BfTreePaths::params_json(&saved_params.prefix); - let params_json = serde_json::to_string(saved_params).map_err(|e| { + let params_json = serde_json::to_string(&saved_params).map_err(|e| { ANNError::log_index_error(format!("Failed to serialize params: {}", e)) })?; let mut params_writer = storage.create_for_write(¶ms_filename)?; @@ -2413,20 +2487,14 @@ mod tests { let storage = FileStorageProvider; - let metric_str = params.metric.as_str(); - let saved_params = SavedParams { - max_points: params.max_points, - frozen_points: params.num_start_points, - dim: params.dim, - metric: metric_str.to_string(), - max_degree: params.max_degree, + let saved_params = SavedParamsInput { prefix: prefix.clone(), - params_vector: BfTreeParams { + params_vector: BfTreeParamsInput { bytes: bytes_vector, leaf_page_size: vector_config.get_leaf_page_size(), max_record_size: vector_config.get_cb_max_record_size(), }, - params_neighbor: BfTreeParams { + params_neighbor: BfTreeParamsInput { bytes: bytes_neighbor, leaf_page_size: neighbor_config.get_leaf_page_size(), max_record_size: neighbor_config.get_cb_max_record_size(), @@ -2603,29 +2671,20 @@ mod tests { let storage = FileStorageProvider; // Create SavedParamsQuant outside of save_with - let metric_str = params.metric.as_str(); - let num_pq_bytes = pq_table.get_num_chunks(); - let saved_params = SavedParams { - max_points: params.max_points, - frozen_points: params.num_start_points, - dim: params.dim, - metric: metric_str.to_string(), - max_degree: params.max_degree, + let saved_params = SavedParamsInput { prefix: prefix.clone(), - params_vector: BfTreeParams { + params_vector: BfTreeParamsInput { bytes: bytes_vector, leaf_page_size: vector_config.get_leaf_page_size(), max_record_size: vector_config.get_cb_max_record_size(), }, - params_neighbor: BfTreeParams { + params_neighbor: BfTreeParamsInput { bytes: bytes_neighbor, leaf_page_size: neighbor_config.get_leaf_page_size(), max_record_size: neighbor_config.get_cb_max_record_size(), }, - quant_params: Some(QuantParams { - num_pq_bytes, - max_fp_vecs_per_fill: params.max_fp_vecs_per_fill.unwrap_or(0), - params_quant: BfTreeParams { + quant_params: Some(QuantParamsInput { + params_quant: BfTreeParamsInput { bytes: bytes_quant, leaf_page_size: quant_config.get_leaf_page_size(), max_record_size: quant_config.get_cb_max_record_size(), From 252905a48a029205dd4c77a6538d21ffdea6bf26 Mon Sep 17 00:00:00 2001 From: backurs Date: Tue, 10 Feb 2026 13:38:02 -0800 Subject: [PATCH 5/7] save_with only receives string --- Cargo.toml | 2 +- .../async_/bf_tree/neighbor_provider.rs | 5 + .../graph/provider/async_/bf_tree/provider.rs | 118 +++++------------- .../async_/bf_tree/quant_vector_provider.rs | 5 + .../async_/bf_tree/vector_provider.rs | 5 + 5 files changed, 45 insertions(+), 90 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e71dff557..a856a1ed2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,7 +67,7 @@ diskann-tools = { path = "diskann-tools", version = "0.45.0" } anyhow = "1.0.98" approx = "0.5.1" arc-swap = "1.7.1" -bf-tree = "0.4.7" +bf-tree = "0.4.8" bincode = "1.3.3" bit-set = "0.8.0" bytemuck = "1.23.0" diff --git a/diskann-providers/src/model/graph/provider/async_/bf_tree/neighbor_provider.rs b/diskann-providers/src/model/graph/provider/async_/bf_tree/neighbor_provider.rs index fca472aa8..fa19850d5 100644 --- a/diskann-providers/src/model/graph/provider/async_/bf_tree/neighbor_provider.rs +++ b/diskann-providers/src/model/graph/provider/async_/bf_tree/neighbor_provider.rs @@ -47,6 +47,11 @@ impl NeighborProvider { } } + /// Access the BfTree config + pub(crate) fn config(&self) -> &Config { + self.adjacency_list_index.config() + } + /// Create a snapshot of the adjacency list index /// pub fn snapshot(&self) { diff --git a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs index 22c8e6c6f..298356d9d 100644 --- a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs +++ b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs @@ -1816,26 +1816,6 @@ pub struct SavedParams { pub quant_params: Option, } -#[derive(Serialize, Deserialize, Clone)] -pub struct BfTreeParamsInput { - pub bytes: usize, - pub max_record_size: usize, - pub leaf_page_size: usize, -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct QuantParamsInput { - pub params_quant: BfTreeParamsInput, -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct SavedParamsInput { - pub prefix: String, - pub params_vector: BfTreeParamsInput, - pub params_neighbor: BfTreeParamsInput, - pub quant_params: Option, -} - /// Helper struct for generating consistent file paths for BfTreeProvider persistence. /// Centralizes all path patterns to avoid hardcoded strings throughout the codebase. pub struct BfTreePaths; @@ -1874,7 +1854,7 @@ impl BfTreePaths { // SaveWith/LoadWith for BfTreeProvider with TableDeleteProviderAsync -impl SaveWith for BfTreeProvider +impl SaveWith for BfTreeProvider where T: VectorRepr, { @@ -1884,7 +1864,7 @@ where async fn save_with

( &self, storage: &P, - saved_params_input: &SavedParamsInput, + prefix: &String, ) -> Result where P: StorageWriteProvider, @@ -1896,16 +1876,16 @@ where dim: self.dim(), metric: self.metric().as_str().to_string(), max_degree: self.max_degree(), - prefix: saved_params_input.prefix.clone(), + prefix: prefix.clone(), params_vector: BfTreeParams { - bytes: saved_params_input.params_vector.bytes, - max_record_size: saved_params_input.params_vector.max_record_size, - leaf_page_size: saved_params_input.params_vector.leaf_page_size, + bytes: self.full_vectors.config().get_cb_size_byte(), + max_record_size: self.full_vectors.config().get_cb_max_record_size(), + leaf_page_size: self.full_vectors.config().get_leaf_page_size(), }, params_neighbor: BfTreeParams { - bytes: saved_params_input.params_neighbor.bytes, - max_record_size: saved_params_input.params_neighbor.max_record_size, - leaf_page_size: saved_params_input.params_neighbor.leaf_page_size, + bytes: self.neighbor_provider.config().get_cb_size_byte(), + max_record_size: self.neighbor_provider.config().get_cb_max_record_size(), + leaf_page_size: self.neighbor_provider.config().get_leaf_page_size(), }, quant_params: None, // No quantization parameters }; @@ -2008,7 +1988,7 @@ where } } -impl SaveWith +impl SaveWith for BfTreeProvider where T: VectorRepr, @@ -2019,7 +1999,7 @@ where async fn save_with

( &self, storage: &P, - saved_params_input: &SavedParamsInput, + prefix: &String, ) -> Result where P: StorageWriteProvider, @@ -2031,29 +2011,26 @@ where dim: self.dim(), metric: self.metric().as_str().to_string(), max_degree: self.max_degree(), - prefix: saved_params_input.prefix.clone(), + prefix: prefix.clone(), params_vector: BfTreeParams { - bytes: saved_params_input.params_vector.bytes, - max_record_size: saved_params_input.params_vector.max_record_size, - leaf_page_size: saved_params_input.params_vector.leaf_page_size, + bytes: self.full_vectors.config().get_cb_size_byte(), + max_record_size: self.full_vectors.config().get_cb_max_record_size(), + leaf_page_size: self.full_vectors.config().get_leaf_page_size(), }, params_neighbor: BfTreeParams { - bytes: saved_params_input.params_neighbor.bytes, - max_record_size: saved_params_input.params_neighbor.max_record_size, - leaf_page_size: saved_params_input.params_neighbor.leaf_page_size, + bytes: self.neighbor_provider.config().get_cb_size_byte(), + max_record_size: self.neighbor_provider.config().get_cb_max_record_size(), + leaf_page_size: self.neighbor_provider.config().get_leaf_page_size(), }, - quant_params: saved_params_input - .quant_params - .as_ref() - .map(|qp| QuantParams { - num_pq_bytes: self.quant_vectors.pq_chunks(), - max_fp_vecs_per_fill: self.max_fp_vecs_per_fill, - params_quant: BfTreeParams { - bytes: qp.params_quant.bytes, - max_record_size: qp.params_quant.max_record_size, - leaf_page_size: qp.params_quant.leaf_page_size, - }, - }), + quant_params: Some(QuantParams { + num_pq_bytes: self.quant_vectors.pq_chunks(), + max_fp_vecs_per_fill: self.max_fp_vecs_per_fill, + params_quant: BfTreeParams { + bytes: self.quant_vectors.config().get_cb_size_byte(), + max_record_size: self.quant_vectors.config().get_cb_max_record_size(), + leaf_page_size: self.quant_vectors.config().get_leaf_page_size(), + }, + }), }; // Save only essential parameters as JSON @@ -2487,22 +2464,7 @@ mod tests { let storage = FileStorageProvider; - let saved_params = SavedParamsInput { - prefix: prefix.clone(), - params_vector: BfTreeParamsInput { - bytes: bytes_vector, - leaf_page_size: vector_config.get_leaf_page_size(), - max_record_size: vector_config.get_cb_max_record_size(), - }, - params_neighbor: BfTreeParamsInput { - bytes: bytes_neighbor, - leaf_page_size: neighbor_config.get_leaf_page_size(), - max_record_size: neighbor_config.get_cb_max_record_size(), - }, - quant_params: None, - }; - - provider.save_with(&storage, &saved_params).await.unwrap(); + provider.save_with(&storage, &prefix).await.unwrap(); // Load using trait method (includes delete bitmap) let loaded_provider = BfTreeProvider::::load_with( @@ -2670,29 +2632,7 @@ mod tests { let storage = FileStorageProvider; - // Create SavedParamsQuant outside of save_with - let saved_params = SavedParamsInput { - prefix: prefix.clone(), - params_vector: BfTreeParamsInput { - bytes: bytes_vector, - leaf_page_size: vector_config.get_leaf_page_size(), - max_record_size: vector_config.get_cb_max_record_size(), - }, - params_neighbor: BfTreeParamsInput { - bytes: bytes_neighbor, - leaf_page_size: neighbor_config.get_leaf_page_size(), - max_record_size: neighbor_config.get_cb_max_record_size(), - }, - quant_params: Some(QuantParamsInput { - params_quant: BfTreeParamsInput { - bytes: bytes_quant, - leaf_page_size: quant_config.get_leaf_page_size(), - max_record_size: quant_config.get_cb_max_record_size(), - }, - }), - }; - - provider.save_with(&storage, &saved_params).await.unwrap(); + provider.save_with(&storage, &prefix).await.unwrap(); // Load using trait method (includes delete bitmap and quantization) let loaded_provider = diff --git a/diskann-providers/src/model/graph/provider/async_/bf_tree/quant_vector_provider.rs b/diskann-providers/src/model/graph/provider/async_/bf_tree/quant_vector_provider.rs index 21204d2ca..a0582748b 100644 --- a/diskann-providers/src/model/graph/provider/async_/bf_tree/quant_vector_provider.rs +++ b/diskann-providers/src/model/graph/provider/async_/bf_tree/quant_vector_provider.rs @@ -69,6 +69,11 @@ impl QuantVectorProvider { self.metric } + /// Access the BfTree config + pub(crate) fn config(&self) -> &Config { + self.quant_vector_index.config() + } + /// Create a snapshot of the quant vector index /// pub fn snapshot(&self) { diff --git a/diskann-providers/src/model/graph/provider/async_/bf_tree/vector_provider.rs b/diskann-providers/src/model/graph/provider/async_/bf_tree/vector_provider.rs index 589295640..1a67034b5 100644 --- a/diskann-providers/src/model/graph/provider/async_/bf_tree/vector_provider.rs +++ b/diskann-providers/src/model/graph/provider/async_/bf_tree/vector_provider.rs @@ -96,6 +96,11 @@ impl VectorProvider { .collect() } + /// Access the BfTree config + pub(crate) fn config(&self) -> &Config { + self.vector_index.config() + } + /// Create a snapshot of the vector index /// #[inline(always)] From 683a05de8a1f8b2ad7b191519310edc2c9e68469 Mon Sep 17 00:00:00 2001 From: backurs Date: Tue, 10 Feb 2026 13:42:25 -0800 Subject: [PATCH 6/7] fmt --- .../graph/provider/async_/bf_tree/provider.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs index 298356d9d..8650b969f 100644 --- a/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs +++ b/diskann-providers/src/model/graph/provider/async_/bf_tree/provider.rs @@ -1861,11 +1861,7 @@ where type Ok = usize; type Error = ANNError; - async fn save_with

( - &self, - storage: &P, - prefix: &String, - ) -> Result + async fn save_with

(&self, storage: &P, prefix: &String) -> Result where P: StorageWriteProvider, { @@ -1988,19 +1984,14 @@ where } } -impl SaveWith - for BfTreeProvider +impl SaveWith for BfTreeProvider where T: VectorRepr, { type Ok = usize; type Error = ANNError; - async fn save_with

( - &self, - storage: &P, - prefix: &String, - ) -> Result + async fn save_with

(&self, storage: &P, prefix: &String) -> Result where P: StorageWriteProvider, { From 0c02ecd735636b99be7ffbfa957d77d7e573db80 Mon Sep 17 00:00:00 2001 From: backurs Date: Tue, 10 Feb 2026 14:00:47 -0800 Subject: [PATCH 7/7] Cargo.lock --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b96d771ee..42a570970 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -105,9 +105,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bf-tree" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cce2075c711f351f0aa52c05e645cc41f1b3cc0cdba1ad12c5f67c121c1bb7d" +checksum = "dc59924517d26b63895ed60675e01a8dc27ee1d24d2b62cd6a272e7bd0af19a0" dependencies = [ "cfg-if", "io-uring",