Skip to main content

scirs2_sparse/adaptive_memory_compression/
config.rs

1//! Configuration for adaptive memory compression
2//!
3//! This module contains configuration structures and enums that control
4//! the behavior of the adaptive memory compression system.
5
6/// Configuration for adaptive memory compression
7#[derive(Debug, Clone)]
8pub struct AdaptiveCompressionConfig {
9    /// Maximum memory budget in bytes
10    pub memory_budget: usize,
11    /// Compression algorithm to use
12    pub compression_algorithm: CompressionAlgorithm,
13    /// Enable hierarchical compression
14    pub hierarchical_compression: bool,
15    /// Block size for compression
16    pub block_size: usize,
17    /// Compression threshold (compress when usage exceeds this ratio)
18    pub compression_threshold: f64,
19    /// Enable adaptive compression based on access patterns
20    pub adaptive_compression: bool,
21    /// Cache size for frequently accessed blocks
22    pub cache_size: usize,
23    /// Enable out-of-core processing
24    pub out_of_core: bool,
25    /// Temporary directory for out-of-core storage
26    pub temp_directory: String,
27    /// Enable memory mapping
28    pub memory_mapping: bool,
29}
30
31/// Compression algorithms for sparse matrix data
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum CompressionAlgorithm {
34    /// No compression
35    None,
36    /// Run-Length Encoding
37    RLE,
38    /// Delta encoding for indices
39    Delta,
40    /// Huffman coding
41    Huffman,
42    /// LZ77 compression
43    LZ77,
44    /// Sparse-specific compression
45    SparseOptimized,
46    /// Hybrid adaptive compression
47    Adaptive,
48}
49
50impl Default for AdaptiveCompressionConfig {
51    fn default() -> Self {
52        // Use reasonable defaults for 32-bit platforms (wasm32)
53        #[cfg(target_pointer_width = "32")]
54        let default_memory_budget = 512 * 1024 * 1024; // 512MB for 32-bit
55        #[cfg(target_pointer_width = "64")]
56        let default_memory_budget = 8usize * 1024 * 1024 * 1024; // 8GB for 64-bit
57
58        #[cfg(target_pointer_width = "32")]
59        let default_cache_size = 64 * 1024 * 1024; // 64MB cache for 32-bit
60        #[cfg(target_pointer_width = "64")]
61        let default_cache_size = 256 * 1024 * 1024; // 256MB cache for 64-bit
62
63        Self {
64            memory_budget: default_memory_budget,
65            compression_algorithm: CompressionAlgorithm::Adaptive,
66            hierarchical_compression: true,
67            block_size: 1024 * 1024, // 1MB blocks
68            compression_threshold: 0.8,
69            adaptive_compression: true,
70            cache_size: default_cache_size,
71            out_of_core: true,
72            temp_directory: {
73                let mut p = std::env::temp_dir();
74                p.push("scirs2_sparse");
75                p.to_string_lossy().into_owned()
76            },
77            memory_mapping: true,
78        }
79    }
80}
81
82impl AdaptiveCompressionConfig {
83    /// Create a new configuration with default values
84    pub fn new() -> Self {
85        Self::default()
86    }
87
88    /// Set memory budget
89    pub fn with_memory_budget(mut self, budget: usize) -> Self {
90        self.memory_budget = budget;
91        self
92    }
93
94    /// Set compression algorithm
95    pub fn with_compression_algorithm(mut self, algorithm: CompressionAlgorithm) -> Self {
96        self.compression_algorithm = algorithm;
97        self
98    }
99
100    /// Enable or disable hierarchical compression
101    pub fn with_hierarchical_compression(mut self, enabled: bool) -> Self {
102        self.hierarchical_compression = enabled;
103        self
104    }
105
106    /// Set block size for compression
107    pub fn with_block_size(mut self, size: usize) -> Self {
108        self.block_size = size;
109        self
110    }
111
112    /// Set compression threshold
113    pub fn with_compression_threshold(mut self, threshold: f64) -> Self {
114        self.compression_threshold = threshold;
115        self
116    }
117
118    /// Enable or disable adaptive compression
119    pub fn with_adaptive_compression(mut self, enabled: bool) -> Self {
120        self.adaptive_compression = enabled;
121        self
122    }
123
124    /// Set cache size
125    pub fn with_cache_size(mut self, size: usize) -> Self {
126        self.cache_size = size;
127        self
128    }
129
130    /// Enable or disable out-of-core processing
131    pub fn with_out_of_core(mut self, enabled: bool) -> Self {
132        self.out_of_core = enabled;
133        self
134    }
135
136    /// Set temporary directory for out-of-core storage
137    pub fn with_temp_directory(mut self, dir: impl Into<String>) -> Self {
138        self.temp_directory = dir.into();
139        self
140    }
141
142    /// Enable or disable memory mapping
143    pub fn with_memory_mapping(mut self, enabled: bool) -> Self {
144        self.memory_mapping = enabled;
145        self
146    }
147
148    /// Validate configuration parameters
149    pub fn validate(&self) -> Result<(), String> {
150        if self.memory_budget == 0 {
151            return Err("Memory budget must be greater than 0".to_string());
152        }
153
154        if self.block_size == 0 {
155            return Err("Block size must be greater than 0".to_string());
156        }
157
158        if self.compression_threshold < 0.0 || self.compression_threshold > 1.0 {
159            return Err("Compression threshold must be between 0.0 and 1.0".to_string());
160        }
161
162        if self.cache_size == 0 {
163            return Err("Cache size must be greater than 0".to_string());
164        }
165
166        if self.cache_size > self.memory_budget {
167            return Err("Cache size cannot exceed memory budget".to_string());
168        }
169
170        if self.temp_directory.is_empty() {
171            return Err("Temporary directory must be specified".to_string());
172        }
173
174        Ok(())
175    }
176
177    /// Create a lightweight configuration for testing
178    pub fn lightweight() -> Self {
179        Self {
180            memory_budget: 64 * 1024 * 1024, // 64MB
181            compression_algorithm: CompressionAlgorithm::RLE,
182            hierarchical_compression: false,
183            block_size: 64 * 1024, // 64KB blocks
184            compression_threshold: 0.9,
185            adaptive_compression: false,
186            cache_size: 16 * 1024 * 1024, // 16MB cache
187            out_of_core: false,
188            temp_directory: {
189                let mut p = std::env::temp_dir();
190                p.push("scirs2_test");
191                p.to_string_lossy().into_owned()
192            },
193            memory_mapping: false,
194        }
195    }
196
197    /// Create a high-performance configuration
198    pub fn high_performance() -> Self {
199        // Use reasonable defaults for 32-bit platforms (wasm32)
200        #[cfg(target_pointer_width = "32")]
201        let hp_memory_budget = 1024 * 1024 * 1024; // 1GB for 32-bit
202        #[cfg(target_pointer_width = "64")]
203        let hp_memory_budget = 32usize * 1024 * 1024 * 1024; // 32GB for 64-bit
204
205        #[cfg(target_pointer_width = "32")]
206        let hp_cache_size = 256 * 1024 * 1024; // 256MB cache for 32-bit
207        #[cfg(target_pointer_width = "64")]
208        let hp_cache_size = 2usize * 1024 * 1024 * 1024; // 2GB cache for 64-bit
209
210        Self {
211            memory_budget: hp_memory_budget,
212            compression_algorithm: CompressionAlgorithm::Adaptive,
213            hierarchical_compression: true,
214            block_size: 4 * 1024 * 1024, // 4MB blocks
215            compression_threshold: 0.7,
216            adaptive_compression: true,
217            cache_size: hp_cache_size,
218            out_of_core: true,
219            temp_directory: {
220                let mut p = std::env::temp_dir();
221                p.push("scirs2_hiperf");
222                p.to_string_lossy().into_owned()
223            },
224            memory_mapping: true,
225        }
226    }
227
228    /// Create a memory-efficient configuration
229    pub fn memory_efficient() -> Self {
230        Self {
231            memory_budget: 1024 * 1024 * 1024, // 1GB
232            compression_algorithm: CompressionAlgorithm::LZ77,
233            hierarchical_compression: true,
234            block_size: 256 * 1024, // 256KB blocks
235            compression_threshold: 0.5,
236            adaptive_compression: true,
237            cache_size: 128 * 1024 * 1024, // 128MB cache
238            out_of_core: true,
239            temp_directory: {
240                let mut p = std::env::temp_dir();
241                p.push("scirs2_memeff");
242                p.to_string_lossy().into_owned()
243            },
244            memory_mapping: true,
245        }
246    }
247}
248
249impl CompressionAlgorithm {
250    /// Check if the algorithm supports adaptive compression
251    pub fn supports_adaptive(&self) -> bool {
252        matches!(
253            self,
254            CompressionAlgorithm::Adaptive | CompressionAlgorithm::SparseOptimized
255        )
256    }
257
258    /// Get expected compression ratio for the algorithm
259    pub fn expected_compression_ratio(&self) -> f64 {
260        match self {
261            CompressionAlgorithm::None => 1.0,
262            CompressionAlgorithm::RLE => 0.6,
263            CompressionAlgorithm::Delta => 0.7,
264            CompressionAlgorithm::Huffman => 0.5,
265            CompressionAlgorithm::LZ77 => 0.4,
266            CompressionAlgorithm::SparseOptimized => 0.3,
267            CompressionAlgorithm::Adaptive => 0.25,
268        }
269    }
270
271    /// Get relative compression speed (higher = faster)
272    pub fn compression_speed(&self) -> f64 {
273        match self {
274            CompressionAlgorithm::None => 10.0,
275            CompressionAlgorithm::RLE => 8.0,
276            CompressionAlgorithm::Delta => 7.0,
277            CompressionAlgorithm::Huffman => 4.0,
278            CompressionAlgorithm::LZ77 => 3.0,
279            CompressionAlgorithm::SparseOptimized => 5.0,
280            CompressionAlgorithm::Adaptive => 2.0,
281        }
282    }
283
284    /// Get description of the algorithm
285    pub fn description(&self) -> &'static str {
286        match self {
287            CompressionAlgorithm::None => "No compression applied",
288            CompressionAlgorithm::RLE => "Run-Length Encoding for repeated values",
289            CompressionAlgorithm::Delta => "Delta encoding for sparse indices",
290            CompressionAlgorithm::Huffman => "Huffman coding for optimal entropy",
291            CompressionAlgorithm::LZ77 => "LZ77 dictionary-based compression",
292            CompressionAlgorithm::SparseOptimized => "Specialized sparse matrix compression",
293            CompressionAlgorithm::Adaptive => "Adaptive hybrid compression strategy",
294        }
295    }
296}