use serde::{Deserialize, Serialize};
use super::allocation::{BottleneckType, ImpactLevel, PerformanceBottleneck};
use super::generic::MemoryAccessPattern;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FunctionCallTrackingInfo {
pub function_name: String,
pub module_path: String,
pub total_call_count: u64,
pub call_frequency_per_sec: f64,
pub avg_execution_time_ns: f64,
pub total_execution_time_ns: u64,
pub call_stack_info: CallStackInfo,
pub memory_allocations_per_call: f64,
pub performance_characteristics: FunctionPerformanceCharacteristics,
pub call_patterns: Vec<CallPattern>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CallStackInfo {
pub max_stack_depth: u32,
pub avg_stack_depth: f64,
pub common_call_sequences: Vec<CallSequence>,
pub recursive_calls: Vec<RecursiveCallInfo>,
pub stack_overflow_risk: StackOverflowRisk,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CallSequence {
pub function_sequence: Vec<String>,
pub frequency: u32,
pub avg_execution_time_ns: f64,
pub memory_usage_pattern: MemoryUsagePattern,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MemoryUsagePattern {
pub peak_memory_usage: usize,
pub avg_memory_usage: usize,
pub allocation_frequency: f64,
pub deallocation_frequency: f64,
pub leak_potential: LeakPotential,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum LeakPotential {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RecursiveCallInfo {
pub function_name: String,
pub max_recursion_depth: u32,
pub avg_recursion_depth: f64,
pub tail_recursion_potential: bool,
pub stack_usage_per_level: usize,
pub recursion_performance_impact: RecursionPerformanceImpact,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RecursionPerformanceImpact {
pub stack_overhead_per_call: usize,
pub call_overhead_ns: f64,
pub cache_impact: f64,
pub optimization_recommendations: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum StackOverflowRisk {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FunctionPerformanceCharacteristics {
pub cpu_usage_percent: f64,
pub memory_characteristics: FunctionMemoryCharacteristics,
pub io_characteristics: IOCharacteristics,
pub concurrency_characteristics: ConcurrencyCharacteristics,
pub bottlenecks: Vec<PerformanceBottleneck>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FunctionMemoryCharacteristics {
pub stack_memory_usage: usize,
pub heap_allocations: u32,
pub access_pattern: MemoryAccessPattern,
pub cache_efficiency: f64,
pub memory_bandwidth_utilization: f64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct IOCharacteristics {
pub file_io_operations: u32,
pub network_io_operations: u32,
pub avg_io_wait_time_ns: f64,
pub io_throughput_bytes_per_sec: f64,
pub io_efficiency_score: f64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ConcurrencyCharacteristics {
pub thread_safety_level: ThreadSafetyLevel,
pub lock_contention_frequency: f64,
pub parallel_execution_potential: f64,
pub synchronization_overhead_ns: f64,
pub deadlock_risk: DeadlockRisk,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ThreadSafetyLevel {
ThreadSafe,
ConditionallyThreadSafe,
NotThreadSafe,
Unknown,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum DeadlockRisk {
None,
Low,
Medium,
High,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CallPattern {
pub pattern_type: CallPatternType,
pub description: String,
pub frequency: u32,
pub performance_impact: f64,
pub optimization_potential: f64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum CallPatternType {
Sequential,
Recursive,
Iterative,
Conditional,
Parallel,
Asynchronous,
Callback,
EventDriven,
}
impl From<crate::core::types::FunctionCallTrackingInfo> for FunctionCallTrackingInfo {
fn from(old: crate::core::types::FunctionCallTrackingInfo) -> Self {
Self {
function_name: old.function_name,
module_path: old.module_path,
total_call_count: old.total_call_count,
call_frequency_per_sec: old.call_frequency_per_sec,
avg_execution_time_ns: old.avg_execution_time_ns,
total_execution_time_ns: old.total_execution_time_ns,
call_stack_info: CallStackInfo {
max_stack_depth: old.call_stack_info.max_stack_depth,
avg_stack_depth: old.call_stack_info.avg_stack_depth,
common_call_sequences: old
.call_stack_info
.common_call_sequences
.into_iter()
.map(|s| CallSequence {
function_sequence: s.function_sequence,
frequency: s.frequency,
avg_execution_time_ns: s.avg_execution_time_ns,
memory_usage_pattern: MemoryUsagePattern {
peak_memory_usage: s.memory_usage_pattern.peak_memory_usage,
avg_memory_usage: s.memory_usage_pattern.avg_memory_usage,
allocation_frequency: s.memory_usage_pattern.allocation_frequency,
deallocation_frequency: s.memory_usage_pattern.deallocation_frequency,
leak_potential: match s.memory_usage_pattern.leak_potential {
crate::core::types::LeakPotential::Low => LeakPotential::Low,
crate::core::types::LeakPotential::Medium => LeakPotential::Medium,
crate::core::types::LeakPotential::High => LeakPotential::High,
crate::core::types::LeakPotential::Critical => {
LeakPotential::Critical
}
},
},
})
.collect(),
recursive_calls: old
.call_stack_info
.recursive_calls
.into_iter()
.map(|r| RecursiveCallInfo {
function_name: r.function_name,
max_recursion_depth: r.max_recursion_depth,
avg_recursion_depth: r.avg_recursion_depth,
tail_recursion_potential: r.tail_recursion_potential,
stack_usage_per_level: r.stack_usage_per_level,
recursion_performance_impact: RecursionPerformanceImpact {
stack_overhead_per_call: r
.recursion_performance_impact
.stack_overhead_per_call,
call_overhead_ns: r.recursion_performance_impact.call_overhead_ns,
cache_impact: r.recursion_performance_impact.cache_impact,
optimization_recommendations: r
.recursion_performance_impact
.optimization_recommendations,
},
})
.collect(),
stack_overflow_risk: match old.call_stack_info.stack_overflow_risk {
crate::core::types::StackOverflowRisk::Low => StackOverflowRisk::Low,
crate::core::types::StackOverflowRisk::Medium => StackOverflowRisk::Medium,
crate::core::types::StackOverflowRisk::High => StackOverflowRisk::High,
crate::core::types::StackOverflowRisk::Critical => StackOverflowRisk::Critical,
},
},
memory_allocations_per_call: old.memory_allocations_per_call,
performance_characteristics: FunctionPerformanceCharacteristics {
cpu_usage_percent: old.performance_characteristics.cpu_usage_percent,
memory_characteristics: FunctionMemoryCharacteristics {
stack_memory_usage: old
.performance_characteristics
.memory_characteristics
.stack_memory_usage,
heap_allocations: old
.performance_characteristics
.memory_characteristics
.heap_allocations,
access_pattern: match old
.performance_characteristics
.memory_characteristics
.access_pattern
{
crate::core::types::MemoryAccessPattern::Sequential => {
MemoryAccessPattern::Sequential
}
crate::core::types::MemoryAccessPattern::Random => {
MemoryAccessPattern::Random
}
crate::core::types::MemoryAccessPattern::Strided { stride } => {
MemoryAccessPattern::Strided { stride }
}
crate::core::types::MemoryAccessPattern::Clustered => {
MemoryAccessPattern::Clustered
}
crate::core::types::MemoryAccessPattern::Mixed => {
MemoryAccessPattern::Mixed
}
},
cache_efficiency: old
.performance_characteristics
.memory_characteristics
.cache_efficiency,
memory_bandwidth_utilization: old
.performance_characteristics
.memory_characteristics
.memory_bandwidth_utilization,
},
io_characteristics: IOCharacteristics {
file_io_operations: old
.performance_characteristics
.io_characteristics
.file_io_operations,
network_io_operations: old
.performance_characteristics
.io_characteristics
.network_io_operations,
avg_io_wait_time_ns: old
.performance_characteristics
.io_characteristics
.avg_io_wait_time_ns,
io_throughput_bytes_per_sec: old
.performance_characteristics
.io_characteristics
.io_throughput_bytes_per_sec,
io_efficiency_score: old
.performance_characteristics
.io_characteristics
.io_efficiency_score,
},
concurrency_characteristics: ConcurrencyCharacteristics {
thread_safety_level: match old
.performance_characteristics
.concurrency_characteristics
.thread_safety_level
{
crate::core::types::ThreadSafetyLevel::ThreadSafe => {
ThreadSafetyLevel::ThreadSafe
}
crate::core::types::ThreadSafetyLevel::ConditionallyThreadSafe => {
ThreadSafetyLevel::ConditionallyThreadSafe
}
crate::core::types::ThreadSafetyLevel::NotThreadSafe => {
ThreadSafetyLevel::NotThreadSafe
}
crate::core::types::ThreadSafetyLevel::Unknown => {
ThreadSafetyLevel::Unknown
}
},
lock_contention_frequency: old
.performance_characteristics
.concurrency_characteristics
.lock_contention_frequency,
parallel_execution_potential: old
.performance_characteristics
.concurrency_characteristics
.parallel_execution_potential,
synchronization_overhead_ns: old
.performance_characteristics
.concurrency_characteristics
.synchronization_overhead_ns,
deadlock_risk: match old
.performance_characteristics
.concurrency_characteristics
.deadlock_risk
{
crate::core::types::DeadlockRisk::None => DeadlockRisk::None,
crate::core::types::DeadlockRisk::Low => DeadlockRisk::Low,
crate::core::types::DeadlockRisk::Medium => DeadlockRisk::Medium,
crate::core::types::DeadlockRisk::High => DeadlockRisk::High,
},
},
bottlenecks: old
.performance_characteristics
.bottlenecks
.into_iter()
.map(|b| PerformanceBottleneck {
bottleneck_type: match b.bottleneck_type {
crate::core::types::BottleneckType::MemoryAllocation => {
BottleneckType::MemoryAllocation
}
crate::core::types::BottleneckType::MemoryDeallocation => {
BottleneckType::MemoryDeallocation
}
crate::core::types::BottleneckType::CacheMiss => {
BottleneckType::CacheMiss
}
crate::core::types::BottleneckType::BranchMisprediction => {
BottleneckType::BranchMisprediction
}
crate::core::types::BottleneckType::FunctionCall => {
BottleneckType::FunctionCall
}
crate::core::types::BottleneckType::DataMovement => {
BottleneckType::DataMovement
}
crate::core::types::BottleneckType::Synchronization => {
BottleneckType::Synchronization
}
crate::core::types::BottleneckType::IO => BottleneckType::IO,
},
location: b.location,
severity: match b.severity {
crate::core::types::ImpactLevel::Low => ImpactLevel::Low,
crate::core::types::ImpactLevel::Medium => ImpactLevel::Medium,
crate::core::types::ImpactLevel::High => ImpactLevel::High,
crate::core::types::ImpactLevel::Critical => ImpactLevel::Critical,
},
description: b.description,
optimization_suggestion: b.optimization_suggestion,
})
.collect(),
},
call_patterns: old
.call_patterns
.into_iter()
.map(|p| CallPattern {
pattern_type: match p.pattern_type {
crate::core::types::CallPatternType::Sequential => {
CallPatternType::Sequential
}
crate::core::types::CallPatternType::Recursive => {
CallPatternType::Recursive
}
crate::core::types::CallPatternType::Iterative => {
CallPatternType::Iterative
}
crate::core::types::CallPatternType::Conditional => {
CallPatternType::Conditional
}
crate::core::types::CallPatternType::Parallel => CallPatternType::Parallel,
crate::core::types::CallPatternType::Asynchronous => {
CallPatternType::Asynchronous
}
crate::core::types::CallPatternType::Callback => CallPatternType::Callback,
crate::core::types::CallPatternType::EventDriven => {
CallPatternType::EventDriven
}
},
description: p.description,
frequency: p.frequency,
performance_impact: p.performance_impact,
optimization_potential: p.optimization_potential,
})
.collect(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_function_call_tracking_info() {
let info = FunctionCallTrackingInfo {
function_name: "test_func".to_string(),
module_path: "test::module".to_string(),
total_call_count: 100,
call_frequency_per_sec: 10.0,
avg_execution_time_ns: 1000.0,
total_execution_time_ns: 100000,
call_stack_info: CallStackInfo {
max_stack_depth: 5,
avg_stack_depth: 3.0,
common_call_sequences: vec![],
recursive_calls: vec![],
stack_overflow_risk: StackOverflowRisk::Low,
},
memory_allocations_per_call: 2.0,
performance_characteristics: FunctionPerformanceCharacteristics {
cpu_usage_percent: 5.0,
memory_characteristics: FunctionMemoryCharacteristics {
stack_memory_usage: 1024,
heap_allocations: 5,
access_pattern: MemoryAccessPattern::Sequential,
cache_efficiency: 0.9,
memory_bandwidth_utilization: 0.5,
},
io_characteristics: IOCharacteristics {
file_io_operations: 0,
network_io_operations: 0,
avg_io_wait_time_ns: 0.0,
io_throughput_bytes_per_sec: 0.0,
io_efficiency_score: 1.0,
},
concurrency_characteristics: ConcurrencyCharacteristics {
thread_safety_level: ThreadSafetyLevel::ThreadSafe,
lock_contention_frequency: 0.0,
parallel_execution_potential: 0.8,
synchronization_overhead_ns: 0.0,
deadlock_risk: DeadlockRisk::None,
},
bottlenecks: vec![],
},
call_patterns: vec![],
};
assert_eq!(info.function_name, "test_func");
assert_eq!(info.total_call_count, 100);
}
#[test]
fn test_call_pattern_type() {
let patterns = vec![
CallPatternType::Sequential,
CallPatternType::Recursive,
CallPatternType::Parallel,
];
for pattern in patterns {
assert!(!format!("{pattern:?}").is_empty());
}
}
}