caching_performance/
caching_performance.rs

1//! Template Caching and Performance Example
2//!
3//! This example demonstrates the performance benefits of template caching
4//! and various optimization features in the Tron template engine.
5
6use tron::{TemplateCache, CacheConfig, TemplateLoader, LoaderConfig, TronTemplate};
7use std::time::{Duration, Instant};
8
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    println!("=== Tron Template Caching and Performance Example ===\n");
11
12    // 1. Basic template caching
13    demonstrate_basic_caching()?;
14    
15    // 2. Cache performance comparison
16    demonstrate_cache_performance()?;
17    
18    // 3. Cache configuration and tuning
19    demonstrate_cache_configuration()?;
20    
21    // 4. Advanced loader with caching
22    demonstrate_loader_caching()?;
23    
24    // 5. Cache statistics and monitoring
25    demonstrate_cache_monitoring()?;
26
27    Ok(())
28}
29
30fn demonstrate_basic_caching() -> Result<(), Box<dyn std::error::Error>> {
31    println!("1. Basic Template Caching:");
32    
33    let cache = TemplateCache::new();
34    
35    // Create and cache some templates
36    let templates = vec![
37        ("function", TronTemplate::new("fn @[name]@(@[params]@) -> @[return_type]@ { @[body]@ }")?),
38        ("struct", TronTemplate::new("struct @[name]@ { @[fields]@ }")?),
39        ("impl", TronTemplate::new("impl @[name]@ { @[methods]@ }")?),
40    ];
41    
42    // Insert templates into cache
43    for (name, template) in &templates {
44        cache.insert_template(template.clone())?;
45        println!("   - Cached template: {}", name);
46    }
47    
48    println!("   - Cache size: {}", cache.size());
49    
50    // Retrieve from cache
51    if let Some(_template) = cache.get_by_content("fn @[name]@(@[params]@) -> @[return_type]@ { @[body]@ }") {
52        println!("   - Successfully retrieved function template from cache");
53    }
54    
55    println!();
56    Ok(())
57}
58
59fn demonstrate_cache_performance() -> Result<(), Box<dyn std::error::Error>> {
60    println!("2. Cache Performance Comparison:");
61    
62    let template_content = "fn @[name]@(@[params]@) -> @[return_type]@ {\n    @[body]@\n}";
63    let iterations = 1000;
64    
65    // Without caching - parse template every time
66    let start = Instant::now();
67    for _ in 0..iterations {
68        let _template = TronTemplate::new(template_content)?;
69    }
70    let no_cache_duration = start.elapsed();
71    
72    // With caching - parse once, retrieve from cache
73    let cache = TemplateCache::new();
74    let template = TronTemplate::new(template_content)?;
75    cache.insert_template(template)?;
76    
77    let start = Instant::now();
78    for _ in 0..iterations {
79        let _cached_template = cache.get_by_content(template_content);
80    }
81    let cache_duration = start.elapsed();
82    
83    println!("   - Without caching: {:?} ({} iterations)", no_cache_duration, iterations);
84    println!("   - With caching:    {:?} ({} iterations)", cache_duration, iterations);
85    println!("   - Performance improvement: {:.2}x faster", 
86             no_cache_duration.as_nanos() as f64 / cache_duration.as_nanos() as f64);
87    
88    println!();
89    Ok(())
90}
91
92fn demonstrate_cache_configuration() -> Result<(), Box<dyn std::error::Error>> {
93    println!("3. Cache Configuration and Tuning:");
94    
95    // High-performance cache configuration
96    let config = CacheConfig {
97        max_size: 50,                                    // Limit cache size
98        max_age: Some(Duration::from_secs(300)),        // 5 minute TTL
99        track_file_changes: true,                       // Watch for file modifications
100        enable_stats: true,                             // Track performance metrics
101    };
102    
103    let cache = TemplateCache::with_config(config);
104    
105    println!("   - Max cache size: 50 templates");
106    println!("   - Max entry age: 5 minutes");
107    println!("   - File change tracking: enabled");
108    println!("   - Statistics tracking: enabled");
109    
110    // Add some templates to test eviction
111    for i in 0..55 {
112        let template = TronTemplate::new(&format!("Template {} content @[placeholder]@", i))?;
113        cache.insert_template(template)?;
114    }
115    
116    println!("   - Added 55 templates, cache size: {} (evicted {})", 
117             cache.size(), 55 - cache.size());
118    
119    // Check statistics
120    if let Some(stats) = cache.stats() {
121        println!("   - Cache hits: {}", stats.hits);
122        println!("   - Cache misses: {}", stats.misses);
123        println!("   - Evictions: {}", stats.evictions);
124    }
125    
126    println!();
127    Ok(())
128}
129
130fn demonstrate_loader_caching() -> Result<(), Box<dyn std::error::Error>> {
131    println!("4. Advanced Loader with Caching:");
132    
133    // Configure loader with caching enabled
134    let loader_config = LoaderConfig {
135        enable_caching: true,
136        cache_config: CacheConfig {
137            max_size: 100,
138            max_age: Some(Duration::from_secs(600)), // 10 minutes
139            track_file_changes: true,
140            enable_stats: true,
141        },
142        ..LoaderConfig::default()
143    };
144    
145    let mut loader = TemplateLoader::with_config(loader_config);
146    
147    // Load templates with caching
148    println!("   - Loading templates from directory (with caching)...");
149    let start = Instant::now();
150    let templates = loader.load_from_directory("templates")?;
151    let first_load_time = start.elapsed();
152    
153    println!("   - First load: {} templates in {:?}", templates.len(), first_load_time);
154    println!("   - Cache size: {}", loader.cache_size());
155    
156    // Load again to test cache performance  
157    let start = Instant::now();
158    let _templates = loader.load_from_directory("templates")?;
159    let cached_load_time = start.elapsed();
160    
161    println!("   - Cached load: {:?} ({}x faster)", 
162             cached_load_time,
163             first_load_time.as_nanos() / cached_load_time.as_nanos().max(1));
164    
165    // Show cache statistics
166    if let Some(stats) = loader.cache_stats() {
167        println!("   - Cache hit ratio: {:.2}%", stats.hit_ratio() * 100.0);
168        println!("   - Total hits: {}, misses: {}", stats.hits, stats.misses);
169    }
170    
171    println!();
172    Ok(())
173}
174
175fn demonstrate_cache_monitoring() -> Result<(), Box<dyn std::error::Error>> {
176    println!("5. Cache Statistics and Monitoring:");
177    
178    let cache = TemplateCache::with_config(CacheConfig {
179        enable_stats: true,
180        max_size: 10,
181        ..CacheConfig::default()
182    });
183    
184    // Generate some cache activity
185    let templates = vec![
186        "Template A: @[content]@",
187        "Template B: @[data]@",
188        "Template C: @[info]@",
189        "Template D: @[value]@",
190        "Template E: @[result]@",
191    ];
192    
193    // Insert templates
194    for template_content in &templates {
195        let template = TronTemplate::new(template_content)?;
196        cache.insert_template(template)?;
197    }
198    
199    // Create cache hits and misses
200    for _ in 0..10 {
201        // Cache hits
202        let _hit = cache.get_by_content(templates[0]);
203        let _hit = cache.get_by_content(templates[1]);
204        
205        // Cache misses
206        let _miss = cache.get_by_content("Nonexistent template @[x]@");
207    }
208    
209    // Add more templates to trigger eviction
210    for i in 6..15 {
211        let template = TronTemplate::new(&format!("Template {}: @[data]@", i))?;
212        cache.insert_template(template)?;
213    }
214    
215    // Display comprehensive statistics
216    if let Some(stats) = cache.stats() {
217        println!("   - Cache Performance Metrics:");
218        println!("     * Total requests: {}", stats.hits + stats.misses);
219        println!("     * Cache hits: {}", stats.hits);
220        println!("     * Cache misses: {}", stats.misses);
221        println!("     * Hit ratio: {:.2}%", stats.hit_ratio() * 100.0);
222        println!("     * Evictions: {}", stats.evictions);
223        println!("     * Invalidations: {}", stats.invalidations);
224    }
225    
226    println!("   - Current cache size: {}", cache.size());
227    println!("   - Cache is empty: {}", cache.is_empty());
228    
229    // Clean up expired entries
230    cache.cleanup_expired();
231    println!("   - After cleanup: {} templates", cache.size());
232    
233    println!();
234    Ok(())
235}
236
237#[cfg(test)]
238mod tests {
239    use super::*;
240
241    #[test]
242    fn test_cache_performance_benefits() -> Result<(), Box<dyn std::error::Error>> {
243        let cache = TemplateCache::new();
244        let template = TronTemplate::new("Test template @[placeholder]@")?;
245        
246        // Cache the template
247        cache.insert_template(template.clone())?;
248        
249        // Verify cache hit
250        let cached = cache.get_by_content("Test template @[placeholder]@");
251        assert!(cached.is_some());
252        assert_eq!(cached.unwrap().content(), template.content());
253        
254        Ok(())
255    }
256    
257    #[test]
258    fn test_loader_caching_integration() -> Result<(), Box<dyn std::error::Error>> {
259        let config = LoaderConfig {
260            enable_caching: true,
261            ..LoaderConfig::default()
262        };
263        
264        let loader = TemplateLoader::with_config(config);
265        assert!(loader.cache_size() == 0);
266        
267        // Cache should be enabled
268        assert!(loader.cache_stats().is_some());
269        
270        Ok(())
271    }
272}