Skip to main content

rusmes_config/
performance.rs

1//! Performance tuning configuration for RusMES.
2//!
3//! The `[performance]` TOML section controls thread counts and per-connection
4//! buffer sizes. All fields are optional — omitting the entire section (or
5//! individual fields) uses the `Default` values documented below.
6//!
7//! ## Example
8//!
9//! ```toml
10//! [performance]
11//! worker_threads = 4
12//! imap_pool_size = 128
13//! smtp_pool_size = 128
14//! read_buffer_kb = 32
15//! write_buffer_kb = 32
16//! ```
17
18use serde::{Deserialize, Serialize};
19
20/// Runtime performance tuning parameters.
21///
22/// Exposed via the `[performance]` TOML section. Defaults are conservative
23/// values that work well on typical single-node deployments. Increase pool
24/// sizes and buffer sizes on high-traffic installations with ample RAM.
25#[derive(Debug, Clone, Deserialize, Serialize)]
26pub struct PerformanceConfig {
27    /// Default: `None` (use Tokio's default, typically the number of logical
28    /// CPUs). Set to override the number of Tokio worker threads at runtime
29    /// startup. Values of `0` are rejected by validation.
30    #[serde(default)]
31    pub worker_threads: Option<usize>,
32
33    /// Default: `64`. Maximum number of concurrent IMAP connections the server
34    /// will accept per listener socket before new connections are queued.
35    #[serde(default = "default_pool_size")]
36    pub imap_pool_size: usize,
37
38    /// Default: `64`. Maximum number of concurrent SMTP connections the server
39    /// will accept per listener socket before new connections are queued.
40    #[serde(default = "default_pool_size")]
41    pub smtp_pool_size: usize,
42
43    /// Default: `64`. Read buffer size in kibibytes allocated per connection.
44    /// Larger values reduce system-call overhead on bulk transfers at the cost
45    /// of memory.
46    #[serde(default = "default_buffer_kb")]
47    pub read_buffer_kb: usize,
48
49    /// Default: `64`. Write buffer size in kibibytes allocated per connection.
50    /// Larger values reduce system-call overhead on bulk transfers at the cost
51    /// of memory.
52    #[serde(default = "default_buffer_kb")]
53    pub write_buffer_kb: usize,
54}
55
56fn default_pool_size() -> usize {
57    64
58}
59
60fn default_buffer_kb() -> usize {
61    64
62}
63
64impl Default for PerformanceConfig {
65    fn default() -> Self {
66        Self {
67            worker_threads: None,
68            imap_pool_size: default_pool_size(),
69            smtp_pool_size: default_pool_size(),
70            read_buffer_kb: default_buffer_kb(),
71            write_buffer_kb: default_buffer_kb(),
72        }
73    }
74}
75
76impl PerformanceConfig {
77    /// Validate performance configuration values.
78    ///
79    /// Returns an error if any pool size or buffer size is zero, or if
80    /// `worker_threads` is explicitly set to zero.
81    pub fn validate(&self) -> anyhow::Result<()> {
82        if let Some(threads) = self.worker_threads {
83            if threads == 0 {
84                anyhow::bail!("performance.worker_threads must be greater than 0");
85            }
86        }
87        if self.imap_pool_size == 0 {
88            anyhow::bail!("performance.imap_pool_size must be greater than 0");
89        }
90        if self.smtp_pool_size == 0 {
91            anyhow::bail!("performance.smtp_pool_size must be greater than 0");
92        }
93        if self.read_buffer_kb == 0 {
94            anyhow::bail!("performance.read_buffer_kb must be greater than 0");
95        }
96        if self.write_buffer_kb == 0 {
97            anyhow::bail!("performance.write_buffer_kb must be greater than 0");
98        }
99        Ok(())
100    }
101
102    /// Return `worker_threads` or a sensible fallback based on the number of
103    /// logical CPUs (minimum 1).
104    pub fn effective_worker_threads(&self) -> usize {
105        self.worker_threads.unwrap_or_else(|| {
106            std::thread::available_parallelism()
107                .map(|n| n.get())
108                .unwrap_or(1)
109        })
110    }
111}