memscope_rs/unified/strategies/
hybrid_strategy.rs

1// Hybrid Memory Tracking Strategy
2// Combines thread-local and async tracking for complex applications
3// Handles mixed thread and async environments
4
5use crate::unified::strategies::{AsyncStrategy, ThreadLocalStrategy};
6use crate::unified::tracking_dispatcher::{
7    MemoryTracker, TrackerConfig, TrackerError, TrackerStatistics, TrackerType,
8};
9use tracing::{debug, info};
10
11/// Hybrid memory tracking strategy
12/// Combines both thread-local and async tracking capabilities
13/// Optimized for applications mixing traditional threads with async tasks
14pub struct HybridStrategy {
15    /// Thread-local tracking component
16    thread_tracker: ThreadLocalStrategy,
17    /// Async tracking component
18    async_tracker: AsyncStrategy,
19    /// Configuration for hybrid operation
20    config: Option<TrackerConfig>,
21    /// Strategy coordination state
22    coordination_state: HybridCoordinationState,
23}
24
25/// Coordination state for hybrid tracking
26/// Manages interaction between thread-local and async components
27#[derive(Debug, Clone)]
28struct HybridCoordinationState {
29    /// Whether hybrid tracking is active
30    is_active: bool,
31    /// Primary tracking mode
32    _primary_mode: TrackingMode,
33    /// Fallback mode when primary fails
34    _fallback_mode: TrackingMode,
35}
36
37/// Tracking mode for hybrid strategy
38#[derive(Debug, Clone, PartialEq)]
39enum TrackingMode {
40    /// Both modes active simultaneously
41    DualMode,
42    /// Automatic mode selection based on context
43    Adaptive,
44}
45
46impl Default for HybridCoordinationState {
47    /// Initialize with adaptive mode
48    fn default() -> Self {
49        Self {
50            is_active: false,
51            _primary_mode: TrackingMode::Adaptive,
52            _fallback_mode: TrackingMode::DualMode,
53        }
54    }
55}
56
57impl HybridStrategy {
58    /// Create new hybrid strategy instance
59    pub fn new() -> Self {
60        debug!("Creating new hybrid strategy");
61
62        Self {
63            thread_tracker: ThreadLocalStrategy::new(),
64            async_tracker: AsyncStrategy::new(),
65            config: None,
66            coordination_state: HybridCoordinationState::default(),
67        }
68    }
69}
70
71impl MemoryTracker for HybridStrategy {
72    /// Initialize both tracking components
73    fn initialize(&mut self, config: TrackerConfig) -> Result<(), TrackerError> {
74        debug!("Initializing hybrid strategy with config: {:?}", config);
75
76        // Initialize both components with same config
77        self.thread_tracker.initialize(config.clone())?;
78        self.async_tracker.initialize(config.clone())?;
79
80        self.config = Some(config);
81
82        info!("Hybrid strategy initialized successfully");
83        Ok(())
84    }
85
86    /// Start both tracking components
87    fn start_tracking(&mut self) -> Result<(), TrackerError> {
88        debug!("Starting hybrid tracking");
89
90        // Start both components
91        self.thread_tracker.start_tracking()?;
92        self.async_tracker.start_tracking()?;
93
94        self.coordination_state.is_active = true;
95
96        info!("Hybrid tracking started successfully");
97        Ok(())
98    }
99
100    /// Stop both components and merge data
101    fn stop_tracking(&mut self) -> Result<Vec<u8>, TrackerError> {
102        debug!("Stopping hybrid tracking");
103
104        // Stop both components
105        let thread_data = self.thread_tracker.stop_tracking()?;
106        let async_data = self.async_tracker.stop_tracking()?;
107
108        // Merge data (simplified - would need sophisticated merging in real implementation)
109        let thread_json: serde_json::Value = serde_json::from_slice(&thread_data)?;
110        let async_json: serde_json::Value = serde_json::from_slice(&async_data)?;
111
112        let mut merged = serde_json::Map::new();
113        merged.insert("thread_data".to_string(), thread_json);
114        merged.insert("async_data".to_string(), async_json);
115        merged.insert(
116            "strategy_type".to_string(),
117            serde_json::Value::String("hybrid".to_string()),
118        );
119
120        let merged_json = serde_json::to_string_pretty(&merged).map_err(|e| {
121            TrackerError::DataCollectionFailed {
122                reason: format!("Failed to merge hybrid data: {e}"),
123            }
124        })?;
125
126        self.coordination_state.is_active = false;
127
128        info!("Hybrid tracking stopped and data merged");
129        Ok(merged_json.into_bytes())
130    }
131
132    /// Get combined statistics from both components
133    fn get_statistics(&self) -> TrackerStatistics {
134        let thread_stats = self.thread_tracker.get_statistics();
135        let async_stats = self.async_tracker.get_statistics();
136
137        TrackerStatistics {
138            allocations_tracked: thread_stats.allocations_tracked + async_stats.allocations_tracked,
139            memory_tracked_bytes: thread_stats.memory_tracked_bytes
140                + async_stats.memory_tracked_bytes,
141            overhead_bytes: thread_stats.overhead_bytes + async_stats.overhead_bytes,
142            tracking_duration_ms: thread_stats
143                .tracking_duration_ms
144                .max(async_stats.tracking_duration_ms),
145        }
146    }
147
148    /// Check if either component is active
149    fn is_active(&self) -> bool {
150        self.coordination_state.is_active
151            && (self.thread_tracker.is_active() || self.async_tracker.is_active())
152    }
153
154    /// Return hybrid tracker type
155    fn tracker_type(&self) -> TrackerType {
156        TrackerType::HybridTracker
157    }
158}
159
160impl Default for HybridStrategy {
161    fn default() -> Self {
162        Self::new()
163    }
164}
165
166#[cfg(test)]
167mod tests {
168    use super::*;
169
170    #[test]
171    fn test_hybrid_strategy_creation() {
172        let strategy = HybridStrategy::new();
173        assert!(!strategy.is_active());
174        assert_eq!(strategy.tracker_type(), TrackerType::HybridTracker);
175    }
176
177    #[test]
178    fn test_hybrid_initialization() {
179        let mut strategy = HybridStrategy::new();
180        let config = TrackerConfig::default();
181
182        let result = strategy.initialize(config);
183        assert!(result.is_ok());
184    }
185
186    #[test]
187    fn test_hybrid_tracking_lifecycle() {
188        let mut strategy = HybridStrategy::new();
189        strategy.initialize(TrackerConfig::default()).unwrap();
190
191        // Start tracking
192        assert!(strategy.start_tracking().is_ok());
193        assert!(strategy.is_active());
194
195        // Stop tracking
196        let data = strategy.stop_tracking();
197        assert!(data.is_ok());
198        assert!(!strategy.is_active());
199    }
200}