1const DEFAULT_IN_MEMORY_CEILING_BYTES: u64 = 8 * 1024 * 1024;
8const DEFAULT_MAX_FAN_IN: u32 = 64;
10const DEFAULT_MAX_CONCURRENT_EXTERNAL: u32 = 8;
12const DEFAULT_FD_SAFETY_MARGIN: u32 = 96;
15const DEFAULT_MIN_RUN_BUFFER_BYTES: u64 = 1024 * 1024;
17const DEFAULT_MAX_RUN_BUFFER_BYTES: u64 = 256 * 1024 * 1024;
21
22#[derive(Debug, Clone)]
24pub struct SorterConfig {
25 in_memory_ceiling_bytes: u64,
26 max_fan_in: u32,
27 max_concurrent_external: u32,
28 fd_safety_margin: u32,
29 min_run_buffer_bytes: u64,
30 max_run_buffer_bytes: u64,
31}
32
33impl Default for SorterConfig {
34 fn default() -> Self {
35 Self {
36 in_memory_ceiling_bytes: DEFAULT_IN_MEMORY_CEILING_BYTES,
37 max_fan_in: DEFAULT_MAX_FAN_IN,
38 max_concurrent_external: DEFAULT_MAX_CONCURRENT_EXTERNAL,
39 fd_safety_margin: DEFAULT_FD_SAFETY_MARGIN,
40 min_run_buffer_bytes: DEFAULT_MIN_RUN_BUFFER_BYTES,
41 max_run_buffer_bytes: DEFAULT_MAX_RUN_BUFFER_BYTES,
42 }
43 }
44}
45
46impl SorterConfig {
47 #[must_use]
51 pub fn from_fd_limit(soft_fd_limit: u32) -> Self {
52 let usable = soft_fd_limit.saturating_sub(DEFAULT_FD_SAFETY_MARGIN);
53 let max_fan_in = (usable / DEFAULT_MAX_CONCURRENT_EXTERNAL).clamp(2, DEFAULT_MAX_FAN_IN);
54 Self {
55 max_fan_in,
56 ..Self::default()
57 }
58 }
59
60 #[must_use]
62 pub fn in_memory_ceiling_bytes(&self) -> u64 {
63 self.in_memory_ceiling_bytes
64 }
65
66 #[must_use]
68 pub fn max_fan_in(&self) -> u32 {
69 self.max_fan_in
70 }
71
72 #[must_use]
74 pub fn max_concurrent_external(&self) -> u32 {
75 self.max_concurrent_external
76 }
77
78 #[must_use]
80 pub fn fd_safety_margin(&self) -> u32 {
81 self.fd_safety_margin
82 }
83
84 #[must_use]
86 pub fn min_run_buffer_bytes(&self) -> u64 {
87 self.min_run_buffer_bytes
88 }
89
90 #[must_use]
92 pub fn max_run_buffer_bytes(&self) -> u64 {
93 self.max_run_buffer_bytes
94 }
95}