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        Self {
53            memory_budget: 8 * 1024 * 1024 * 1024, // 8GB default
54            compression_algorithm: CompressionAlgorithm::Adaptive,
55            hierarchical_compression: true,
56            block_size: 1024 * 1024, // 1MB blocks
57            compression_threshold: 0.8,
58            adaptive_compression: true,
59            cache_size: 256 * 1024 * 1024, // 256MB cache
60            out_of_core: true,
61            temp_directory: "/tmp/scirs2_sparse".to_string(),
62            memory_mapping: true,
63        }
64    }
65}
66
67impl AdaptiveCompressionConfig {
68    /// Create a new configuration with default values
69    pub fn new() -> Self {
70        Self::default()
71    }
72
73    /// Set memory budget
74    pub fn with_memory_budget(mut self, budget: usize) -> Self {
75        self.memory_budget = budget;
76        self
77    }
78
79    /// Set compression algorithm
80    pub fn with_compression_algorithm(mut self, algorithm: CompressionAlgorithm) -> Self {
81        self.compression_algorithm = algorithm;
82        self
83    }
84
85    /// Enable or disable hierarchical compression
86    pub fn with_hierarchical_compression(mut self, enabled: bool) -> Self {
87        self.hierarchical_compression = enabled;
88        self
89    }
90
91    /// Set block size for compression
92    pub fn with_block_size(mut self, size: usize) -> Self {
93        self.block_size = size;
94        self
95    }
96
97    /// Set compression threshold
98    pub fn with_compression_threshold(mut self, threshold: f64) -> Self {
99        self.compression_threshold = threshold;
100        self
101    }
102
103    /// Enable or disable adaptive compression
104    pub fn with_adaptive_compression(mut self, enabled: bool) -> Self {
105        self.adaptive_compression = enabled;
106        self
107    }
108
109    /// Set cache size
110    pub fn with_cache_size(mut self, size: usize) -> Self {
111        self.cache_size = size;
112        self
113    }
114
115    /// Enable or disable out-of-core processing
116    pub fn with_out_of_core(mut self, enabled: bool) -> Self {
117        self.out_of_core = enabled;
118        self
119    }
120
121    /// Set temporary directory for out-of-core storage
122    pub fn with_temp_directory(mut self, dir: impl Into<String>) -> Self {
123        self.temp_directory = dir.into();
124        self
125    }
126
127    /// Enable or disable memory mapping
128    pub fn with_memory_mapping(mut self, enabled: bool) -> Self {
129        self.memory_mapping = enabled;
130        self
131    }
132
133    /// Validate configuration parameters
134    pub fn validate(&self) -> Result<(), String> {
135        if self.memory_budget == 0 {
136            return Err("Memory budget must be greater than 0".to_string());
137        }
138
139        if self.block_size == 0 {
140            return Err("Block size must be greater than 0".to_string());
141        }
142
143        if self.compression_threshold < 0.0 || self.compression_threshold > 1.0 {
144            return Err("Compression threshold must be between 0.0 and 1.0".to_string());
145        }
146
147        if self.cache_size == 0 {
148            return Err("Cache size must be greater than 0".to_string());
149        }
150
151        if self.cache_size > self.memory_budget {
152            return Err("Cache size cannot exceed memory budget".to_string());
153        }
154
155        if self.temp_directory.is_empty() {
156            return Err("Temporary directory must be specified".to_string());
157        }
158
159        Ok(())
160    }
161
162    /// Create a lightweight configuration for testing
163    pub fn lightweight() -> Self {
164        Self {
165            memory_budget: 64 * 1024 * 1024, // 64MB
166            compression_algorithm: CompressionAlgorithm::RLE,
167            hierarchical_compression: false,
168            block_size: 64 * 1024, // 64KB blocks
169            compression_threshold: 0.9,
170            adaptive_compression: false,
171            cache_size: 16 * 1024 * 1024, // 16MB cache
172            out_of_core: false,
173            temp_directory: "/tmp/scirs2_test".to_string(),
174            memory_mapping: false,
175        }
176    }
177
178    /// Create a high-performance configuration
179    pub fn high_performance() -> Self {
180        Self {
181            memory_budget: 32 * 1024 * 1024 * 1024, // 32GB
182            compression_algorithm: CompressionAlgorithm::Adaptive,
183            hierarchical_compression: true,
184            block_size: 4 * 1024 * 1024, // 4MB blocks
185            compression_threshold: 0.7,
186            adaptive_compression: true,
187            cache_size: 2 * 1024 * 1024 * 1024, // 2GB cache
188            out_of_core: true,
189            temp_directory: "/tmp/scirs2_hiperf".to_string(),
190            memory_mapping: true,
191        }
192    }
193
194    /// Create a memory-efficient configuration
195    pub fn memory_efficient() -> Self {
196        Self {
197            memory_budget: 1024 * 1024 * 1024, // 1GB
198            compression_algorithm: CompressionAlgorithm::LZ77,
199            hierarchical_compression: true,
200            block_size: 256 * 1024, // 256KB blocks
201            compression_threshold: 0.5,
202            adaptive_compression: true,
203            cache_size: 128 * 1024 * 1024, // 128MB cache
204            out_of_core: true,
205            temp_directory: "/tmp/scirs2_memeff".to_string(),
206            memory_mapping: true,
207        }
208    }
209}
210
211impl CompressionAlgorithm {
212    /// Check if the algorithm supports adaptive compression
213    pub fn supports_adaptive(&self) -> bool {
214        matches!(
215            self,
216            CompressionAlgorithm::Adaptive | CompressionAlgorithm::SparseOptimized
217        )
218    }
219
220    /// Get expected compression ratio for the algorithm
221    pub fn expected_compression_ratio(&self) -> f64 {
222        match self {
223            CompressionAlgorithm::None => 1.0,
224            CompressionAlgorithm::RLE => 0.6,
225            CompressionAlgorithm::Delta => 0.7,
226            CompressionAlgorithm::Huffman => 0.5,
227            CompressionAlgorithm::LZ77 => 0.4,
228            CompressionAlgorithm::SparseOptimized => 0.3,
229            CompressionAlgorithm::Adaptive => 0.25,
230        }
231    }
232
233    /// Get relative compression speed (higher = faster)
234    pub fn compression_speed(&self) -> f64 {
235        match self {
236            CompressionAlgorithm::None => 10.0,
237            CompressionAlgorithm::RLE => 8.0,
238            CompressionAlgorithm::Delta => 7.0,
239            CompressionAlgorithm::Huffman => 4.0,
240            CompressionAlgorithm::LZ77 => 3.0,
241            CompressionAlgorithm::SparseOptimized => 5.0,
242            CompressionAlgorithm::Adaptive => 2.0,
243        }
244    }
245
246    /// Get description of the algorithm
247    pub fn description(&self) -> &'static str {
248        match self {
249            CompressionAlgorithm::None => "No compression applied",
250            CompressionAlgorithm::RLE => "Run-Length Encoding for repeated values",
251            CompressionAlgorithm::Delta => "Delta encoding for sparse indices",
252            CompressionAlgorithm::Huffman => "Huffman coding for optimal entropy",
253            CompressionAlgorithm::LZ77 => "LZ77 dictionary-based compression",
254            CompressionAlgorithm::SparseOptimized => "Specialized sparse matrix compression",
255            CompressionAlgorithm::Adaptive => "Adaptive hybrid compression strategy",
256        }
257    }
258}