sz_rust_core/runtime/
worker.rs1use std::fmt;
19
20pub const DEFAULT_WORKER_NUM: usize = 0; pub const MIN_WORKER_NUM: usize = 1;
25
26pub const MAX_WORKER_NUM: usize = 256;
28
29#[derive(Debug, Clone, PartialEq, Eq)]
51pub struct WorkerConfig {
52 worker_num: usize,
54 reactor_num: usize,
56 task_worker_num: usize,
58}
59
60impl WorkerConfig {
61 pub fn new() -> Self {
63 let cpu = num_cpus::get();
64 Self {
65 worker_num: cpu,
66 reactor_num: cpu,
67 task_worker_num: cpu,
68 }
69 }
70
71 pub fn with_worker_num(mut self, n: usize) -> Self {
76 self.worker_num = if n == 0 {
77 num_cpus::get()
78 } else {
79 n.clamp(MIN_WORKER_NUM, MAX_WORKER_NUM)
80 };
81 self
82 }
83
84 pub fn with_reactor_num(mut self, n: usize) -> Self {
86 self.reactor_num = if n == 0 {
87 num_cpus::get()
88 } else {
89 n.clamp(MIN_WORKER_NUM, MAX_WORKER_NUM)
90 };
91 self
92 }
93
94 pub fn with_task_worker_num(mut self, n: usize) -> Self {
96 self.task_worker_num = if n == 0 {
97 num_cpus::get()
98 } else {
99 n.clamp(MIN_WORKER_NUM, MAX_WORKER_NUM)
100 };
101 self
102 }
103
104 pub fn worker_num(&self) -> usize {
106 self.worker_num
107 }
108
109 pub fn reactor_num(&self) -> usize {
111 self.reactor_num
112 }
113
114 pub fn task_worker_num(&self) -> usize {
116 self.task_worker_num
117 }
118
119 pub fn cpu_num(&self) -> usize {
121 num_cpus::get()
122 }
123
124 pub fn validate(&self) -> bool {
126 self.worker_num >= MIN_WORKER_NUM
127 && self.worker_num <= MAX_WORKER_NUM
128 && self.reactor_num >= MIN_WORKER_NUM
129 && self.reactor_num <= MAX_WORKER_NUM
130 && self.task_worker_num >= MIN_WORKER_NUM
131 && self.task_worker_num <= MAX_WORKER_NUM
132 }
133
134 pub fn from_env() -> Self {
139 let mut config = Self::new();
140 if let Ok(val) = std::env::var("SZ_RUST_WORKER_NUM") {
141 if let Ok(n) = val.parse::<usize>() {
142 config = config.with_worker_num(n);
143 }
144 }
145 config
146 }
147}
148
149impl Default for WorkerConfig {
150 fn default() -> Self {
151 Self::new()
152 }
153}
154
155impl fmt::Display for WorkerConfig {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 write!(
158 f,
159 "WorkerConfig{{worker_num={}, reactor_num={}, task_worker_num={}, cpu={}}}",
160 self.worker_num,
161 self.reactor_num,
162 self.task_worker_num,
163 self.cpu_num()
164 )
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_new_defaults_to_cpu_count() {
174 let config = WorkerConfig::new();
175 let cpu = num_cpus::get();
176 assert_eq!(config.worker_num(), cpu);
177 assert_eq!(config.reactor_num(), cpu);
178 assert_eq!(config.task_worker_num(), cpu);
179 }
180
181 #[test]
182 fn test_with_worker_num_custom() {
183 let config = WorkerConfig::new().with_worker_num(8);
184 assert_eq!(config.worker_num(), 8);
185 }
186
187 #[test]
188 fn test_with_worker_num_zero_falls_back_to_cpu() {
189 let config = WorkerConfig::new().with_worker_num(0);
190 assert_eq!(config.worker_num(), num_cpus::get());
191 }
192
193 #[test]
194 fn test_with_worker_num_exceeds_max_clamped() {
195 let config = WorkerConfig::new().with_worker_num(1024);
196 assert_eq!(config.worker_num(), MAX_WORKER_NUM);
197 }
198
199 #[test]
200 fn test_with_reactor_num_custom() {
201 let config = WorkerConfig::new().with_reactor_num(4);
202 assert_eq!(config.reactor_num(), 4);
203 }
204
205 #[test]
206 fn test_with_task_worker_num_custom() {
207 let config = WorkerConfig::new().with_task_worker_num(16);
208 assert_eq!(config.task_worker_num(), 16);
209 }
210
211 #[test]
212 fn test_cpu_num_matches_num_cpus() {
213 let config = WorkerConfig::new();
214 assert_eq!(config.cpu_num(), num_cpus::get());
215 }
216
217 #[test]
218 fn test_validate_valid_config() {
219 let config = WorkerConfig::new();
220 assert!(config.validate());
221 }
222
223 #[test]
224 fn test_validate_boundary_values() {
225 let config_min = WorkerConfig::new()
226 .with_worker_num(MIN_WORKER_NUM)
227 .with_reactor_num(MIN_WORKER_NUM)
228 .with_task_worker_num(MIN_WORKER_NUM);
229 assert!(config_min.validate());
230
231 let config_max = WorkerConfig::new()
232 .with_worker_num(MAX_WORKER_NUM)
233 .with_reactor_num(MAX_WORKER_NUM)
234 .with_task_worker_num(MAX_WORKER_NUM);
235 assert!(config_max.validate());
236 }
237
238 #[test]
239 fn test_from_env_default() {
240 std::env::remove_var("SZ_RUST_WORKER_NUM");
242 let config = WorkerConfig::from_env();
243 assert_eq!(config.worker_num(), num_cpus::get());
244 }
245
246 #[test]
247 fn test_from_env_custom() {
248 std::env::set_var("SZ_RUST_WORKER_NUM", "12");
249 let config = WorkerConfig::from_env();
250 assert_eq!(config.worker_num(), 12);
251 std::env::remove_var("SZ_RUST_WORKER_NUM");
252 }
253
254 #[test]
255 fn test_from_env_invalid_falls_back_to_default() {
256 std::env::set_var("SZ_RUST_WORKER_NUM", "not-a-number");
257 let config = WorkerConfig::from_env();
258 assert_eq!(config.worker_num(), num_cpus::get());
259 std::env::remove_var("SZ_RUST_WORKER_NUM");
260 }
261
262 #[test]
263 fn test_display_format() {
264 let config = WorkerConfig::new().with_worker_num(4);
265 let s = format!("{}", config);
266 assert!(s.contains("worker_num=4"));
267 assert!(s.contains("reactor_num="));
268 assert!(s.contains("task_worker_num="));
269 }
270
271 #[test]
272 fn test_default_equals_new() {
273 let config1 = WorkerConfig::default();
274 let config2 = WorkerConfig::new();
275 assert_eq!(config1, config2);
276 }
277
278 #[test]
279 fn test_clone_and_equality() {
280 let config1 = WorkerConfig::new().with_worker_num(4);
281 let config2 = config1.clone();
282 assert_eq!(config1, config2);
283 }
284
285 #[test]
286 fn test_builder_chaining() {
287 let config = WorkerConfig::new()
288 .with_worker_num(4)
289 .with_reactor_num(2)
290 .with_task_worker_num(8);
291 assert_eq!(config.worker_num(), 4);
292 assert_eq!(config.reactor_num(), 2);
293 assert_eq!(config.task_worker_num(), 8);
294 assert!(config.validate());
295 }
296}