1use std::path::PathBuf;
2use std::time::Duration;
3
4#[derive(Debug, Clone, Copy)]
5pub struct IOSchedulerConfig {
6 pub workers: usize,
8 #[cfg(target_os = "linux")]
10 pub iouring_queue_depth: usize,
11 #[cfg(target_os = "linux")]
13 pub iouring_fixed_buffers: usize,
14 #[cfg(target_os = "linux")]
16 pub iouring_sqpoll_idle_ms: Option<u32>,
17 pub fsync_on_write: bool,
19 pub wal_workers: usize,
21}
22
23impl IOSchedulerConfig {
24 pub fn default_workers() -> usize {
25 std::thread::available_parallelism()
26 .map(|n| n.get())
27 .unwrap_or(1)
28 }
29}
30
31impl Default for IOSchedulerConfig {
32 fn default() -> Self {
33 IOSchedulerConfig {
34 workers: Self::default_workers(),
35 #[cfg(target_os = "linux")]
36 iouring_queue_depth: 256,
37 #[cfg(target_os = "linux")]
38 iouring_fixed_buffers: 256,
39 #[cfg(target_os = "linux")]
40 iouring_sqpoll_idle_ms: None,
41 fsync_on_write: true,
42 wal_workers: std::cmp::max(1, Self::default_workers() / 2),
43 }
44 }
45}
46
47#[derive(Debug, Clone, Copy)]
48pub struct BufferPoolConfig {
49 pub buffer_pool_size: usize,
50 pub lru_k_k: usize,
51 pub tiny_lfu_enable: bool,
52 pub tiny_lfu_counters: usize,
53 pub admission_enable: bool,
54}
55
56impl Default for BufferPoolConfig {
57 fn default() -> Self {
58 BufferPoolConfig {
59 buffer_pool_size: 5000,
60 lru_k_k: 2,
61 tiny_lfu_enable: true,
62 tiny_lfu_counters: 4,
63 admission_enable: true,
64 }
65 }
66}
67
68#[derive(Debug, Clone)]
69pub struct WalConfig {
70 pub directory: PathBuf,
71 pub segment_size: u64,
72 pub sync_on_flush: bool,
73 pub persist_control_file_on_flush: bool,
74 pub writer_interval_ms: Option<u64>,
75 pub buffer_capacity: usize,
76 pub flush_coalesce_bytes: usize,
77 pub synchronous_commit: bool,
78 pub checkpoint_interval_ms: Option<u64>,
79 pub retain_segments: usize,
80}
81
82#[derive(Debug, Clone, Copy)]
83pub struct BackgroundConfig {
84 pub wal_writer_interval: Option<Duration>,
85 pub checkpoint_interval: Option<Duration>,
86 pub bg_writer_interval: Option<Duration>,
87 pub vacuum: IndexVacuumConfig,
88 pub mvcc_vacuum: MvccVacuumConfig,
89}
90
91pub fn background_config(
92 wal_config: &WalConfig,
93 vacuum_cfg: IndexVacuumConfig,
94 mvcc_cfg: MvccVacuumConfig,
95) -> BackgroundConfig {
96 let wal_writer_interval = wal_config.writer_interval_ms.and_then(duration_from_ms);
97 let checkpoint_interval = wal_config.checkpoint_interval_ms.and_then(duration_from_ms);
98
99 let env_interval = std::env::var("QUILL_BG_WRITER_INTERVAL_MS")
100 .ok()
101 .and_then(|raw| raw.parse::<u64>().ok());
102 let bg_interval_ms = env_interval.unwrap_or(vacuum_cfg.interval_ms);
103 let bg_writer_interval = duration_from_ms(bg_interval_ms);
104
105 let mvcc_interval_ms = std::env::var("QUILL_MVCC_VACUUM_INTERVAL_MS")
106 .ok()
107 .and_then(|raw| raw.parse::<u64>().ok())
108 .unwrap_or(mvcc_cfg.interval_ms);
109 let mvcc_batch = std::env::var("QUILL_MVCC_VACUUM_BATCH")
110 .ok()
111 .and_then(|raw| raw.parse::<usize>().ok())
112 .unwrap_or(mvcc_cfg.batch_limit)
113 .max(1);
114
115 BackgroundConfig {
116 wal_writer_interval,
117 checkpoint_interval,
118 bg_writer_interval,
119 vacuum: vacuum_cfg,
120 mvcc_vacuum: MvccVacuumConfig {
121 interval_ms: mvcc_interval_ms,
122 batch_limit: mvcc_batch,
123 },
124 }
125}
126
127fn duration_from_ms(ms: u64) -> Option<Duration> {
128 if ms == 0 {
129 None
130 } else {
131 Some(Duration::from_millis(ms))
132 }
133}
134
135impl Default for WalConfig {
136 fn default() -> Self {
137 WalConfig {
138 directory: PathBuf::from("wal"),
139 segment_size: 16 * 1024 * 1024, sync_on_flush: false,
141 persist_control_file_on_flush: false,
142 writer_interval_ms: Some(50),
143 buffer_capacity: 256,
144 flush_coalesce_bytes: 2 * 1024 * 1024,
145 synchronous_commit: false,
146 checkpoint_interval_ms: Some(5000),
147 retain_segments: 8,
148 }
149 }
150}
151
152#[derive(Debug, Clone, Copy)]
153pub struct BTreeConfig {
154 pub seq_batch_enable: bool,
155 pub seq_window: usize,
156 pub prefetch_enable: bool,
157 pub prefetch_window: usize,
158 pub debug_find_level: u8,
159 pub debug_insert_level: u8,
160 pub debug_split_level: u8,
161}
162
163impl Default for BTreeConfig {
164 fn default() -> Self {
165 BTreeConfig {
166 seq_batch_enable: true,
167 seq_window: 32,
168 prefetch_enable: true,
169 prefetch_window: 2,
170 debug_find_level: 0,
171 debug_insert_level: 0,
172 debug_split_level: 0,
173 }
174 }
175}
176
177#[derive(Debug, Clone, Copy)]
178pub struct IndexVacuumConfig {
179 pub interval_ms: u64,
181 pub trigger_threshold: usize,
183 pub batch_limit: usize,
185}
186
187impl Default for IndexVacuumConfig {
188 fn default() -> Self {
189 Self {
190 interval_ms: 10_000, trigger_threshold: 4096, batch_limit: 128, }
194 }
195}
196
197#[derive(Debug, Clone, Copy)]
198pub struct MvccVacuumConfig {
199 pub interval_ms: u64,
201 pub batch_limit: usize,
203}
204
205impl Default for MvccVacuumConfig {
206 fn default() -> Self {
207 Self {
208 interval_ms: 15_000, batch_limit: 512,
210 }
211 }
212}