memscope-rs 0.2.0

A memory tracking library for Rust applications.
Documentation
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClosureInfo {
    pub ptr: usize,
    pub captures: Vec<CaptureInfo>,
    pub creation_timestamp: u64,
    pub thread_id: String,
    pub call_site: String,
    pub memory_footprint: ClosureFootprint,
    pub optimization_potential: OptimizationPotential,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CaptureInfo {
    pub var_name: String,
    pub var_ptr: usize,
    pub mode: CaptureMode,
    pub var_type: String,
    pub size: usize,
    pub lifetime_bound: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum CaptureMode {
    ByValue,
    ByReference,
    ByMutableReference,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClosureFootprint {
    pub total_size: usize,
    pub capture_count: usize,
    pub by_value_count: usize,
    pub by_ref_count: usize,
    pub by_mut_ref_count: usize,
    pub estimated_heap_usage: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OptimizationPotential {
    pub level: OptimizationLevel,
    pub potential_savings: usize,
    pub suggestions: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum OptimizationLevel {
    None,
    Low,
    Medium,
    High,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CaptureEvent {
    pub closure_ptr: usize,
    pub captured_var: CaptureInfo,
    pub event_type: CaptureEventType,
    pub timestamp: u64,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum CaptureEventType {
    Captured,
    Released,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DetectedClosure {
    pub ptr: usize,
    pub type_name: String,
    pub size: usize,
    pub estimated_captures: usize,
    pub closure_type: ClosureType,
    pub creation_context: CreationContext,
    pub memory_impact: MemoryImpact,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ClosureType {
    Fn,
    FnMut,
    FnOnce,
    Unknown,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreationContext {
    pub scope_name: Option<String>,
    pub thread_id: String,
    pub timestamp: u64,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum MemoryImpact {
    Minimal,
    Low,
    Medium,
    High,
    VeryHigh,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CaptureStatistics {
    pub total_closures: usize,
    pub total_captures: usize,
    pub avg_captures_per_closure: f64,
    pub total_memory_usage: usize,
    pub captures_by_mode: HashMap<CaptureMode, usize>,
    pub captures_by_type: HashMap<String, usize>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OptimizationSuggestion {
    pub category: OptimizationCategory,
    pub priority: SuggestionPriority,
    pub description: String,
    pub recommendation: String,
    pub estimated_impact: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum OptimizationCategory {
    Memory,
    Performance,
    Lifetime,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum SuggestionPriority {
    Low,
    Medium,
    High,
    Critical,
}

#[derive(Debug)]
pub struct LifetimeGraph {
    relationships: HashMap<usize, Vec<LifetimeRelationship>>,
}

impl Default for LifetimeGraph {
    fn default() -> Self {
        Self::new()
    }
}

impl LifetimeGraph {
    pub fn new() -> Self {
        Self {
            relationships: HashMap::new(),
        }
    }

    pub fn add_closure_relationships(&mut self, closure_ptr: usize, captures: &[CaptureInfo]) {
        let relationships: Vec<LifetimeRelationship> = captures
            .iter()
            .map(|capture| LifetimeRelationship {
                captured_var_ptr: capture.var_ptr,
                capture_mode: capture.mode.clone(),
                relationship_type: self.classify_relationship(&capture.mode),
            })
            .collect();

        self.relationships.insert(closure_ptr, relationships);
    }

    pub fn remove_closure(&mut self, closure_ptr: usize) {
        self.relationships.remove(&closure_ptr);
    }

    fn classify_relationship(&self, mode: &CaptureMode) -> RelationshipType {
        match mode {
            CaptureMode::ByValue => RelationshipType::Ownership,
            CaptureMode::ByReference => RelationshipType::SharedBorrow,
            CaptureMode::ByMutableReference => RelationshipType::ExclusiveBorrow,
        }
    }

    pub fn analyze_lifetimes(&self) -> LifetimeAnalysis {
        let mut potential_issues = Vec::new();
        let mut lifetime_patterns = Vec::new();

        for (closure_ptr, relationships) in &self.relationships {
            let has_value_captures = relationships
                .iter()
                .any(|r| r.capture_mode == CaptureMode::ByValue);
            let has_ref_captures = relationships.iter().any(|r| {
                matches!(
                    r.capture_mode,
                    CaptureMode::ByReference | CaptureMode::ByMutableReference
                )
            });

            if has_value_captures && has_ref_captures {
                potential_issues.push(LifetimeIssue {
                    closure_ptr: *closure_ptr,
                    issue_type: LifetimeIssueType::MixedCaptureMode,
                    description: "Closure mixes value and reference captures".to_string(),
                    severity: IssueSeverity::Medium,
                    suggestion: "Consider consistent capture strategy".to_string(),
                });
            }

            if relationships.len() > 5 {
                lifetime_patterns.push(LifetimePattern {
                    pattern_type: LifetimePatternType::ManyCaptures,
                    description: format!("Closure captures {} variables", relationships.len()),
                    impact: if relationships.len() > 10 {
                        PatternImpact::High
                    } else {
                        PatternImpact::Medium
                    },
                });
            }
        }

        LifetimeAnalysis {
            total_relationships: self.relationships.len(),
            potential_issues,
            lifetime_patterns,
        }
    }
}

#[derive(Debug, Clone)]
pub struct LifetimeRelationship {
    pub captured_var_ptr: usize,
    pub capture_mode: CaptureMode,
    pub relationship_type: RelationshipType,
}

#[derive(Debug, Clone, PartialEq)]
pub enum RelationshipType {
    Ownership,
    SharedBorrow,
    ExclusiveBorrow,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct LifetimeAnalysis {
    pub total_relationships: usize,
    pub potential_issues: Vec<LifetimeIssue>,
    pub lifetime_patterns: Vec<LifetimePattern>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LifetimeIssue {
    pub closure_ptr: usize,
    pub issue_type: LifetimeIssueType,
    pub description: String,
    pub severity: IssueSeverity,
    pub suggestion: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum LifetimeIssueType {
    MixedCaptureMode,
    PotentialDanglingReference,
    UnnecessaryCapture,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum IssueSeverity {
    Low,
    Medium,
    High,
    Critical,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LifetimePattern {
    pub pattern_type: LifetimePatternType,
    pub description: String,
    pub impact: PatternImpact,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum LifetimePatternType {
    ManyCaptures,
    LongLivedClosure,
    FrequentCreation,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PatternImpact {
    Low,
    Medium,
    High,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClosureAnalysisReport {
    pub detected_closures: Vec<DetectedClosure>,
    pub capture_statistics: CaptureStatistics,
    pub optimization_suggestions: Vec<OptimizationSuggestion>,
    pub lifetime_analysis: LifetimeAnalysis,
    pub analysis_timestamp: u64,
}