Skip to main content

runmat_snapshot/
lib.rs

1//! # RunMat Snapshot Creator
2//!
3//! High-performance snapshot system for preloading the RunMat standard library.
4//! Inspired by V8's snapshot architecture, this provides:
5//!
6//! - **Zero-copy serialization** with memory mapping
7//! - **Multi-tier compression** with LZ4 and ZSTD
8//! - **Integrity validation** with SHA-256 checksums  
9//! - **Concurrent loading** with lock-free data structures
10//! - **Progressive enhancement** with fallback mechanisms
11//!
12//! ## Architecture
13//!
14//! ```text
15//! ┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
16//! │  Standard Lib   │ -> │   Snapshot       │ -> │   Runtime       │
17//! │  Components     │    │   Generator      │    │   Loader        │
18//! │                 │    │                  │    │                 │
19//! │ • Builtins      │    │ • Serialization  │    │ • Memory Map    │
20//! │ • HIR Cache     │    │ • Compression    │    │ • Validation    │
21//! │ • Bytecode      │    │ • Validation     │    │ • Integration   │
22//! │ • GC Presets    │    │ • Optimization   │    │ • Performance   │
23//! └─────────────────┘    └──────────────────┘    └─────────────────┘
24//! ```
25
26use std::cell::RefCell;
27use std::collections::HashMap;
28use std::path::{Path, PathBuf};
29use std::rc::Rc;
30use std::sync::Arc;
31
32/// Type alias for builtin function dispatch table to reduce complexity
33type BuiltinDispatchTable =
34    Arc<RwLock<Vec<fn(&[runmat_builtins::Value]) -> runmat_builtins::BuiltinFuture>>>;
35use std::time::Duration;
36
37use parking_lot::RwLock;
38use serde::{Deserialize, Serialize};
39
40pub mod builder;
41pub mod compression;
42pub mod format;
43pub mod loader;
44pub mod presets;
45pub mod validation;
46
47pub use builder::SnapshotBuilder;
48pub use format::{SnapshotFormat, SnapshotHeader, SnapshotMetadata};
49pub use loader::SnapshotLoader;
50
51/// Core snapshot data containing preloaded standard library components
52#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct Snapshot {
54    /// Snapshot metadata
55    pub metadata: SnapshotMetadata,
56
57    /// Preloaded builtin functions with optimized dispatch table
58    pub builtins: BuiltinRegistry,
59
60    /// Cached HIR representations of standard library functions
61    pub hir_cache: HirCache,
62
63    /// Precompiled bytecode for common operations
64    pub bytecode_cache: BytecodeCache,
65
66    /// GC configuration presets
67    pub gc_presets: GcPresetCache,
68
69    /// Runtime optimization hints
70    pub optimization_hints: OptimizationHints,
71}
72
73/// Optimized builtin function registry for fast dispatch
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct BuiltinRegistry {
76    /// Function name to index mapping for O(1) lookup
77    pub name_index: HashMap<String, usize>,
78
79    /// Function metadata array (aligned for cache efficiency)
80    pub functions: Vec<BuiltinMetadata>,
81
82    /// Function dispatch table (runtime-generated)
83    #[serde(skip)]
84    pub dispatch_table: BuiltinDispatchTable,
85}
86
87/// Metadata for a builtin function
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct BuiltinMetadata {
90    pub name: String,
91    pub arity: BuiltinArity,
92    pub category: BuiltinCategory,
93    pub complexity: ComputationalComplexity,
94    pub optimization_level: OptimizationLevel,
95}
96
97/// Function arity specification
98#[derive(Debug, Clone, Serialize, Deserialize)]
99pub enum BuiltinArity {
100    /// Exact number of arguments
101    Exact(usize),
102    /// Range of arguments (min, max)
103    Range(usize, usize),
104    /// Variadic (minimum arguments)
105    Variadic(usize),
106}
107
108/// Builtin function categories for optimization
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub enum BuiltinCategory {
111    Math,
112    LinearAlgebra,
113    Statistics,
114    MatrixOps,
115    Trigonometric,
116    Comparison,
117    Utility,
118}
119
120/// Computational complexity for scheduling hints
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub enum ComputationalComplexity {
123    Constant,
124    Linear,
125    Quadratic,
126    Cubic,
127    Exponential,
128}
129
130/// Optimization level for JIT compilation hints
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
132pub enum OptimizationLevel {
133    None,
134    Basic,
135    Aggressive,
136    MaxPerformance,
137}
138
139/// Cached HIR representations
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct HirCache {
142    /// Standard library function HIR
143    pub functions: HashMap<String, runmat_hir::HirAssembly>,
144
145    /// Common expression patterns
146    pub patterns: Vec<HirPattern>,
147
148    /// Type inference cache
149    pub type_cache: HashMap<String, runmat_hir::Type>,
150}
151
152/// HIR pattern for common expressions
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct HirPattern {
155    pub name: String,
156    pub pattern: runmat_hir::HirAssembly,
157    pub frequency: u32,
158    pub optimization_priority: OptimizationLevel,
159}
160
161/// Precompiled bytecode cache
162#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct BytecodeCache {
164    /// Standard library bytecode
165    pub stdlib_bytecode: HashMap<String, runmat_vm::Bytecode>,
166
167    /// Common operation bytecode sequences
168    pub operation_sequences: Vec<BytecodeSequence>,
169
170    /// Hotspot bytecode (frequently executed)
171    pub hotspots: Vec<HotspotBytecode>,
172}
173
174/// Bytecode sequence for common operations
175#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct BytecodeSequence {
177    pub name: String,
178    pub bytecode: runmat_vm::Bytecode,
179    pub usage_count: u64,
180    pub average_execution_time: Duration,
181}
182
183/// Hotspot bytecode with JIT compilation hints
184#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct HotspotBytecode {
186    pub name: String,
187    pub bytecode: runmat_vm::Bytecode,
188    pub execution_frequency: u64,
189    pub jit_compilation_threshold: u32,
190    pub optimization_hints: Vec<OptimizationHint>,
191}
192
193/// GC configuration presets
194#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct GcPresetCache {
196    /// Named GC configurations
197    pub presets: HashMap<String, runmat_gc::GcConfig>,
198
199    /// Default preset name
200    pub default_preset: String,
201
202    /// Performance characteristics for each preset
203    pub performance_profiles: HashMap<String, GcPerformanceProfile>,
204}
205
206/// GC performance profile
207#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct GcPerformanceProfile {
209    pub average_allocation_rate: f64,
210    pub average_collection_time: Duration,
211    pub memory_overhead: f64,
212    pub throughput_impact: f64,
213}
214
215/// Runtime optimization hints
216#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct OptimizationHints {
218    /// JIT compilation hints
219    pub jit_hints: Vec<JitHint>,
220
221    /// Memory layout hints
222    pub memory_hints: Vec<MemoryHint>,
223
224    /// Execution pattern hints
225    pub execution_hints: Vec<ExecutionHint>,
226}
227
228/// JIT compilation hint
229#[derive(Debug, Clone, Serialize, Deserialize)]
230pub struct JitHint {
231    pub pattern: String,
232    pub hint_type: JitHintType,
233    pub priority: OptimizationLevel,
234    pub expected_performance_gain: f64,
235}
236
237/// Types of JIT hints
238#[derive(Debug, Clone, Serialize, Deserialize)]
239pub enum JitHintType {
240    InlineCandidate,
241    LoopOptimization,
242    VectorizeCandidate,
243    ConstantFolding,
244    DeadCodeElimination,
245}
246
247/// Memory layout optimization hint
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct MemoryHint {
250    pub data_structure: String,
251    pub hint_type: MemoryHintType,
252    pub alignment: usize,
253    pub prefetch_pattern: PrefetchPattern,
254}
255
256/// Types of memory hints
257#[derive(Debug, Clone, Serialize, Deserialize)]
258pub enum MemoryHintType {
259    CacheLocalityOptimization,
260    PrefetchOptimization,
261    AlignmentOptimization,
262    CompressionCandidate,
263}
264
265/// Memory prefetch patterns
266#[derive(Debug, Clone, Serialize, Deserialize)]
267pub enum PrefetchPattern {
268    Sequential,
269    Random,
270    Strided(usize),
271    Hierarchical,
272}
273
274/// Execution pattern hint
275#[derive(Debug, Clone, Serialize, Deserialize)]
276pub struct ExecutionHint {
277    pub pattern: String,
278    pub hint_type: ExecutionHintType,
279    pub frequency: u64,
280    pub optimization_potential: f64,
281}
282
283/// Types of execution hints
284#[derive(Debug, Clone, Serialize, Deserialize)]
285pub enum ExecutionHintType {
286    HotPath,
287    ColdPath,
288    BranchPrediction,
289    ParallelizationCandidate,
290}
291
292/// Optimization hint for hotspot bytecode
293#[derive(Debug, Clone, Serialize, Deserialize)]
294pub struct OptimizationHint {
295    pub hint_type: String,
296    pub parameters: HashMap<String, String>,
297    pub expected_speedup: f64,
298}
299
300/// Snapshot loading statistics
301#[derive(Debug, Clone)]
302pub struct LoadingStats {
303    pub load_time: Duration,
304    pub decompression_time: Duration,
305    pub validation_time: Duration,
306    pub initialization_time: Duration,
307    pub total_size: u64,
308    pub compressed_size: u64,
309    pub compression_ratio: f64,
310    pub builtin_count: u64,
311    pub cache_hit_rate: f64,
312}
313
314impl LoadingStats {
315    pub fn compression_efficiency(&self) -> f64 {
316        1.0 - (self.compressed_size as f64 / self.total_size as f64)
317    }
318
319    pub fn loading_throughput(&self) -> f64 {
320        self.total_size as f64 / self.load_time.as_secs_f64()
321    }
322}
323
324/// Error types for snapshot operations
325#[derive(thiserror::Error, Debug)]
326pub enum SnapshotError {
327    #[error("IO error: {0}")]
328    Io(#[from] std::io::Error),
329
330    #[error("Serialization error: {0}")]
331    Serialization(#[from] bincode::Error),
332
333    #[error("Compression error: {message}")]
334    Compression { message: String },
335
336    #[error("Validation error: {message}")]
337    Validation { message: String },
338
339    #[error("Version mismatch: expected {expected}, found {found}")]
340    VersionMismatch { expected: String, found: String },
341
342    #[error("Corrupted snapshot: {reason}")]
343    Corrupted { reason: String },
344
345    #[error("Configuration error: {message}")]
346    Configuration { message: String },
347}
348
349/// Result type for snapshot operations
350pub type SnapshotResult<T> = std::result::Result<T, SnapshotError>;
351
352/// Snapshot configuration
353#[derive(Debug, Clone)]
354pub struct SnapshotConfig {
355    /// Enable compression
356    pub compression_enabled: bool,
357
358    /// Compression algorithm
359    pub compression_algorithm: CompressionAlgorithm,
360
361    /// Compression level (1-9)
362    pub compression_level: u32,
363
364    /// Enable validation
365    pub validation_enabled: bool,
366
367    /// Memory mapping for loading
368    pub memory_mapping_enabled: bool,
369
370    /// Parallel loading
371    pub parallel_loading: bool,
372
373    /// Progress reporting
374    pub progress_reporting: bool,
375
376    /// Maximum optimization level to apply while building snapshot hints
377    pub max_optimization_level: OptimizationLevel,
378
379    /// Maximum cache size
380    pub max_cache_size: usize,
381
382    /// Cache eviction policy
383    pub cache_eviction_policy: CacheEvictionPolicy,
384}
385
386/// Compression algorithm options
387#[derive(Debug, Clone)]
388pub enum CompressionAlgorithm {
389    None,
390    Lz4,
391    Zstd,
392    Auto, // Choose best based on data characteristics
393}
394
395/// Cache eviction policies
396#[derive(Debug, Clone)]
397pub enum CacheEvictionPolicy {
398    LeastRecentlyUsed,
399    LeastFrequentlyUsed,
400    TimeToLive(Duration),
401    Adaptive,
402}
403
404impl Default for SnapshotConfig {
405    fn default() -> Self {
406        Self {
407            compression_enabled: true,
408            compression_algorithm: CompressionAlgorithm::Auto,
409            compression_level: 6,
410            validation_enabled: true,
411            memory_mapping_enabled: true,
412            parallel_loading: true,
413            progress_reporting: false,
414            max_optimization_level: OptimizationLevel::MaxPerformance,
415            max_cache_size: 128 * 1024 * 1024, // 128MB
416            cache_eviction_policy: CacheEvictionPolicy::Adaptive,
417        }
418    }
419}
420
421/// Main snapshot interface
422pub struct SnapshotManager {
423    config: SnapshotConfig,
424    cache: RefCell<HashMap<PathBuf, Rc<Snapshot>>>,
425    stats: RefCell<HashMap<PathBuf, LoadingStats>>,
426}
427
428impl SnapshotManager {
429    /// Create a new snapshot manager
430    pub fn new(config: SnapshotConfig) -> Self {
431        Self {
432            config,
433            cache: RefCell::new(HashMap::new()),
434            stats: RefCell::new(HashMap::new()),
435        }
436    }
437
438    /// Create a snapshot from the current standard library
439    pub fn create_snapshot<P: AsRef<Path>>(&self, output_path: P) -> SnapshotResult<()> {
440        let builder = SnapshotBuilder::new(self.config.clone());
441        builder.build_and_save(output_path)
442    }
443
444    /// Load a snapshot from disk
445    pub fn load_snapshot<P: AsRef<Path>>(&self, snapshot_path: P) -> SnapshotResult<Rc<Snapshot>> {
446        let path = snapshot_path.as_ref().to_path_buf();
447
448        // Check cache first
449        {
450            let cache = self.cache.borrow();
451            if let Some(snapshot) = cache.get(&path) {
452                return Ok(Rc::clone(snapshot));
453            }
454        }
455
456        // Load from disk
457        let mut loader = SnapshotLoader::new(self.config.clone());
458        let (snapshot, stats) = loader.load(&path)?;
459        let snapshot = Rc::new(snapshot);
460
461        // Update cache and stats
462        {
463            let mut cache = self.cache.borrow_mut();
464            cache.insert(path.clone(), Rc::clone(&snapshot));
465        }
466        {
467            let mut stats_map = self.stats.borrow_mut();
468            stats_map.insert(path, stats);
469        }
470
471        Ok(snapshot)
472    }
473
474    /// Get loading statistics for a snapshot
475    pub fn get_stats<P: AsRef<Path>>(&self, snapshot_path: P) -> Option<LoadingStats> {
476        let stats = self.stats.borrow();
477        stats.get(snapshot_path.as_ref()).cloned()
478    }
479
480    /// Clear snapshot cache
481    pub fn clear_cache(&self) {
482        let mut cache = self.cache.borrow_mut();
483        cache.clear();
484        let mut stats = self.stats.borrow_mut();
485        stats.clear();
486    }
487
488    /// Get cache statistics
489    pub fn cache_stats(&self) -> (usize, usize) {
490        let cache = self.cache.borrow();
491        let total_size = cache
492            .values()
493            .map(|snapshot| bincode::serialized_size(&**snapshot).unwrap_or(0) as usize)
494            .sum();
495        (cache.len(), total_size)
496    }
497}
498
499impl Default for SnapshotManager {
500    fn default() -> Self {
501        Self::new(SnapshotConfig::default())
502    }
503}
504
505#[cfg(test)]
506mod tests {
507    use super::*;
508
509    #[test]
510    fn test_snapshot_config_default() {
511        let config = SnapshotConfig::default();
512        assert!(config.compression_enabled);
513        assert!(config.validation_enabled);
514        assert!(config.memory_mapping_enabled);
515        assert!(config.parallel_loading);
516    }
517
518    #[test]
519    fn test_snapshot_manager_creation() {
520        let manager = SnapshotManager::default();
521        let (cache_entries, cache_size) = manager.cache_stats();
522        assert_eq!(cache_entries, 0);
523        assert_eq!(cache_size, 0);
524    }
525
526    #[test]
527    fn test_loading_stats_calculations() {
528        let stats = LoadingStats {
529            load_time: Duration::from_millis(100),
530            decompression_time: Duration::from_millis(20),
531            validation_time: Duration::from_millis(10),
532            initialization_time: Duration::from_millis(5),
533            total_size: 1000,
534            compressed_size: 600,
535            compression_ratio: 0.4,
536            builtin_count: 50,
537            cache_hit_rate: 0.8,
538        };
539
540        assert_eq!(stats.compression_efficiency(), 0.4);
541        assert_eq!(stats.loading_throughput(), 10000.0); // bytes per second
542    }
543}