znippy_common/
common_config.rs1use crate::hostinfo;
2use once_cell::sync::Lazy;
3use std::cmp::min;
4
5#[derive(Debug, Clone)] pub struct StrategicConfig {
7 pub max_core_allowed: usize,
8 pub max_core_in_flight: usize,
9 pub max_core_in_compress: usize,
10 pub max_mem_allowed: u64,
11 pub min_free_memory_ratio: f32,
12 pub file_split_block_size: u64,
13 pub max_chunks: u32,
14 pub compression_level: i32,
15 pub zstd_output_buffer_size: usize,
16}
17
18pub static CONFIG: Lazy<StrategicConfig> = Lazy::new(strategic_confi_large);
19
20const SLOT_POOL_MEM_FRACTION: f64 = 0.5;
25
26pub fn slot_pool_budget_bytes() -> u64 {
58 if let Some(explicit) = std::env::var("ZNIPPY_SLOT_POOL_BYTES")
59 .ok()
60 .and_then(|raw| parse_byte_size(&raw))
61 {
62 log::info!("[slot_pool] budget {explicit} bytes (ZNIPPY_SLOT_POOL_BYTES)");
63 return explicit;
64 }
65
66 let host_available = hostinfo::mem_available_bytes().unwrap_or(0);
67 let headroom = match hostinfo::cgroup_memory() {
68 Some(cg) => cg.total_memory.saturating_sub(cg.rss).min(host_available.max(1)),
71 None => host_available,
72 };
73
74 let budget = (headroom as f64 * SLOT_POOL_MEM_FRACTION) as u64;
75 log::info!(
76 "[slot_pool] budget {} bytes ({:.0}% of {} bytes headroom)",
77 budget,
78 SLOT_POOL_MEM_FRACTION * 100.0,
79 headroom
80 );
81 budget
82}
83
84pub fn parse_byte_size(raw: &str) -> Option<u64> {
88 let s = raw.trim();
89 let (digits, unit) = s.split_at(s.find(|c: char| !c.is_ascii_digit()).unwrap_or(s.len()));
90 let n: u64 = digits.parse().ok()?;
91 let mult = match unit.trim().to_ascii_lowercase().as_str() {
92 "" | "b" => 1u64,
93 "k" | "kb" | "kib" => 1024,
94 "m" | "mb" | "mib" => 1024 * 1024,
95 "g" | "gb" | "gib" => 1024 * 1024 * 1024,
96 _ => return None,
97 };
98 n.checked_mul(mult)
99}
100
101pub fn strategic_config(resource: f32) -> StrategicConfig {
102 let total_memory = hostinfo::mem_total_bytes().unwrap_or(0);
103 let max_core_allowed =
107 hostinfo::physical_core_count().unwrap_or_else(hostinfo::logical_cpu_count);
108
109 let max_core_in_flight = ((max_core_allowed as f32) * 0.90).ceil() as usize;
110 let max_core_in_compress = max_core_allowed.saturating_sub(max_core_in_flight);
111 let min_free_memory_ratio = 1.0 - resource;
112 let compression_level = 19;
113 let max_mem_allowed = ((total_memory as f32) * (1.0 - min_free_memory_ratio)) as u64;
114 let file_split_block_size = 10 * 1024 * 1024;
115 let zstd_output_buffer_size = 1 * 1024 * 1024;
116
117 let max_chunks: u32 = (max_mem_allowed / file_split_block_size) as u32;
118
119 log::info!(
120 "[strategic_config] Detekterade {} kärnor och {} MiB minne",
121 max_core_allowed,
122 total_memory / (1024 * 1024)
125 );
126
127 let sc = StrategicConfig {
128 max_core_allowed,
129 max_core_in_flight,
130 max_core_in_compress,
131 max_mem_allowed,
132 min_free_memory_ratio,
133 file_split_block_size,
134 compression_level,
135 max_chunks,
136 zstd_output_buffer_size,
137 };
138 log_strategic_conf(&sc);
139 sc
140}
141
142fn strategic_confi_large() -> StrategicConfig {
143 let mut sc = strategic_config(1.0);
144
145 sc.max_chunks = min(sc.max_chunks as u64, 128) as u32;
147 log::info!(
148 "[strategic_config large] max_core_in_flight={} max_core_in_compress for zstd {} max_chunks {} ",
149 sc.max_core_in_flight,
150 sc.max_core_in_compress,
151 sc.max_chunks
152 );
153 log_strategic_conf(&sc);
154 sc
155}
156
157fn log_strategic_conf(sc: &StrategicConfig) {
158 log::info!(
159 "[strategic_config] max_core_in_flight: {} (10%)",
160 sc.max_core_in_flight
161 );
162
163 log::info!(
164 "[strategic_config] max_core_in_compress: {} (90%)",
165 sc.max_core_in_compress
166 );
167 log::info!(
168 "[strategic_config] min_free_memory_ratio: {:.0}%",
169 sc.min_free_memory_ratio * 100.0
170 );
171 log::info!(
172 "[strategic_config] compression_level: {}",
173 sc.compression_level
174 );
175
176 log::info!("[strategic_config] max_chunks: {}", sc.max_chunks);
177
178 log::info!(
179 "[strategic_config] zstd_output_buffer_size: {}",
180 sc.zstd_output_buffer_size
181 );
182}