Skip to main content

nodedb_types/config/tuning/
mod.rs

1mod data_plane;
2mod engines;
3mod memory;
4mod network;
5mod shutdown;
6
7pub use data_plane::{DataPlaneTuning, QueryTuning};
8pub use engines::{
9    DEFAULT_MAX_DEPTH, DEFAULT_MAX_VISITED, GraphTuning, KvTuning, SparseTuning, TimeseriesToning,
10    VectorTuning,
11};
12pub use memory::MemoryTuning;
13pub use network::{BridgeTuning, ClusterTransportTuning, NetworkTuning, WalTuning};
14pub use shutdown::ShutdownTuning;
15
16use serde::{Deserialize, Serialize};
17
18/// Top-level tuning configuration.
19///
20/// All fields have sensible defaults derived from the current hardcoded values.
21/// Override via the `[tuning]` section in `config.toml`.
22#[derive(Debug, Clone, Default, Serialize, Deserialize)]
23pub struct TuningConfig {
24    #[serde(default)]
25    pub data_plane: DataPlaneTuning,
26    #[serde(default)]
27    pub query: QueryTuning,
28    #[serde(default)]
29    pub vector: VectorTuning,
30    #[serde(default)]
31    pub sparse: SparseTuning,
32    #[serde(default)]
33    pub graph: GraphTuning,
34    #[serde(default)]
35    pub timeseries: TimeseriesToning,
36    #[serde(default)]
37    pub kv: KvTuning,
38    #[serde(default)]
39    pub bridge: BridgeTuning,
40    #[serde(default)]
41    pub network: NetworkTuning,
42    #[serde(default)]
43    pub wal: WalTuning,
44    #[serde(default)]
45    pub cluster_transport: ClusterTransportTuning,
46    #[serde(default)]
47    pub memory: MemoryTuning,
48    #[serde(default)]
49    pub shutdown: ShutdownTuning,
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    #[test]
57    fn default_tuning_roundtrip() {
58        let cfg = TuningConfig::default();
59        let toml_str = toml::to_string_pretty(&cfg).expect("serialize");
60        let parsed: TuningConfig = toml::from_str(&toml_str).expect("deserialize");
61
62        assert_eq!(parsed.data_plane.idle_poll_timeout_ms, 100);
63        assert_eq!(parsed.query.sort_run_size, 100_000);
64        assert_eq!(parsed.vector.flat_index_threshold, 10_000);
65        assert_eq!(parsed.sparse.bm25_k1, 1.2);
66        assert_eq!(parsed.graph.max_visited, 100_000);
67        assert_eq!(parsed.timeseries.memtable_budget_bytes, 64 * 1024 * 1024);
68        assert_eq!(parsed.kv.default_capacity, 16_384);
69        assert_eq!(parsed.kv.rehash_load_factor, 0.75);
70        assert_eq!(parsed.kv.expiry_reap_budget, 1024);
71        assert_eq!(parsed.bridge.slab_page_size, 64 * 1024);
72        assert_eq!(parsed.network.default_deadline_secs, 30);
73        assert_eq!(parsed.wal.write_buffer_size, 2 * 1024 * 1024);
74        assert_eq!(parsed.cluster_transport.raft_tick_interval_ms, 10);
75        // New ClusterTransportTuning fields.
76        assert_eq!(
77            parsed.cluster_transport.broadcast_threshold_bytes,
78            8 * 1024 * 1024
79        );
80        assert_eq!(parsed.cluster_transport.ghost_sweep_interval_secs, 1800);
81        assert_eq!(parsed.cluster_transport.health_ping_interval_secs, 5);
82        assert_eq!(parsed.cluster_transport.health_failure_threshold, 3);
83        // New QueryTuning fields.
84        assert_eq!(parsed.query.doc_cache_entries, 4096);
85        assert_eq!(parsed.query.columnar_flush_threshold, 65_536);
86        assert_eq!(parsed.query.compaction_target_bytes, 256 * 1024 * 1024);
87        // New MemoryTuning fields.
88        assert_eq!(parsed.memory.overflow_initial_bytes, 64 * 1024 * 1024);
89        assert_eq!(parsed.memory.overflow_max_bytes, 1024 * 1024 * 1024);
90        assert_eq!(parsed.memory.doc_cache_entries, 4096);
91        assert_eq!(parsed.shutdown.deadline_ms, 900);
92    }
93
94    #[test]
95    fn partial_override() {
96        let toml_str = r#"
97[query]
98sort_run_size = 50000
99
100[network]
101default_deadline_secs = 60
102"#;
103        let cfg: TuningConfig = toml::from_str(toml_str).expect("deserialize");
104        assert_eq!(cfg.query.sort_run_size, 50_000);
105        assert_eq!(cfg.network.default_deadline_secs, 60);
106        assert_eq!(cfg.query.aggregate_scan_cap, 10_000_000);
107        assert_eq!(cfg.vector.seal_threshold, 65_536);
108        // Unset fields retain defaults.
109        assert_eq!(cfg.query.columnar_flush_threshold, 65_536);
110        assert_eq!(cfg.query.compaction_target_bytes, 256 * 1024 * 1024);
111    }
112
113    #[test]
114    fn empty_toml_yields_defaults() {
115        let cfg: TuningConfig = toml::from_str("").expect("deserialize");
116        assert_eq!(cfg.data_plane.max_consecutive_panics, 3);
117        assert_eq!(cfg.graph.max_depth, 10);
118        // Memory tuning defaults.
119        assert_eq!(cfg.memory.overflow_initial_bytes, 64 * 1024 * 1024);
120        assert_eq!(cfg.memory.overflow_max_bytes, 1024 * 1024 * 1024);
121        assert_eq!(cfg.memory.doc_cache_entries, 4096);
122        // Cluster transport new defaults.
123        assert_eq!(
124            cfg.cluster_transport.broadcast_threshold_bytes,
125            8 * 1024 * 1024
126        );
127        assert_eq!(cfg.cluster_transport.ghost_sweep_interval_secs, 1800);
128        assert_eq!(cfg.cluster_transport.health_ping_interval_secs, 5);
129        assert_eq!(cfg.cluster_transport.health_failure_threshold, 3);
130    }
131
132    #[test]
133    fn memory_tuning_override() {
134        let toml_str = r#"
135[memory]
136overflow_initial_bytes = 134217728
137overflow_max_bytes = 2147483648
138doc_cache_entries = 8192
139"#;
140        let cfg: TuningConfig = toml::from_str(toml_str).expect("deserialize");
141        assert_eq!(cfg.memory.overflow_initial_bytes, 128 * 1024 * 1024);
142        assert_eq!(cfg.memory.overflow_max_bytes, 2 * 1024 * 1024 * 1024);
143        assert_eq!(cfg.memory.doc_cache_entries, 8192);
144    }
145}