use serde::{Deserialize, Serialize};
use std::thread;
use super::access_tracking::MemoryAccessTrackingInfo;
use super::drop_chain::DropChainAnalysis;
use super::dynamic_type::DynamicTypeInfo;
use super::fragmentation::EnhancedFragmentationAnalysis;
use super::generic::{GenericInstantiationInfo, GenericTypeInfo};
use super::lifecycle::ObjectLifecycleInfo;
use super::memory_layout::MemoryLayoutInfo;
use super::ownership::TypeRelationshipInfo;
use super::runtime_state::RuntimeStateInfo;
use super::smart_pointer::SmartPointerInfo;
use super::stack::StackAllocationInfo;
use super::temporary::TemporaryObjectInfo;
use super::tracking::FunctionCallTrackingInfo;
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct BorrowInfo {
pub immutable_borrows: usize,
pub mutable_borrows: usize,
pub max_concurrent_borrows: usize,
pub last_borrow_timestamp: Option<u64>,
#[serde(default)]
pub _source: Option<String>,
#[serde(default)]
pub _confidence: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct CloneInfo {
pub clone_count: usize,
pub is_clone: bool,
pub original_ptr: Option<usize>,
#[serde(default)]
pub _source: Option<String>,
#[serde(default)]
pub _confidence: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct AllocationInfo {
pub ptr: usize,
pub size: usize,
pub var_name: Option<String>,
pub type_name: Option<String>,
pub scope_name: Option<String>,
pub timestamp_alloc: u64,
pub timestamp_dealloc: Option<u64>,
pub thread_id: thread::ThreadId,
pub thread_id_u64: u64,
pub borrow_count: usize,
pub stack_trace: Option<Vec<String>>,
pub is_leaked: bool,
pub lifetime_ms: Option<u64>,
pub borrow_info: Option<BorrowInfo>,
pub clone_info: Option<CloneInfo>,
pub ownership_history_available: bool,
pub smart_pointer_info: Option<SmartPointerInfo>,
pub memory_layout: Option<MemoryLayoutInfo>,
pub module_path: Option<String>,
pub stack_ptr: Option<usize>,
pub task_id: Option<u64>,
pub generic_info: Option<GenericTypeInfo>,
pub dynamic_type_info: Option<DynamicTypeInfo>,
pub runtime_state: Option<RuntimeStateInfo>,
pub stack_allocation: Option<StackAllocationInfo>,
pub temporary_object: Option<TemporaryObjectInfo>,
pub fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
pub generic_instantiation: Option<GenericInstantiationInfo>,
pub type_relationships: Option<TypeRelationshipInfo>,
pub type_usage: Option<TypeUsageInfo>,
pub function_call_tracking: Option<FunctionCallTrackingInfo>,
pub lifecycle_tracking: Option<ObjectLifecycleInfo>,
pub access_tracking: Option<MemoryAccessTrackingInfo>,
pub drop_chain_analysis: Option<DropChainAnalysis>,
}
impl From<crate::core::types::AllocationInfo> for AllocationInfo {
fn from(old: crate::core::types::AllocationInfo) -> Self {
let thread_id = thread::current().id();
let borrow_info = old.borrow_info.map(|b| BorrowInfo {
immutable_borrows: b.immutable_borrows,
mutable_borrows: b.mutable_borrows,
max_concurrent_borrows: b.max_concurrent_borrows,
last_borrow_timestamp: b.last_borrow_timestamp,
_source: None,
_confidence: None,
});
let clone_info = old.clone_info.map(|c| CloneInfo {
clone_count: c.clone_count,
is_clone: c.is_clone,
original_ptr: c.original_ptr,
_source: None,
_confidence: None,
});
let smart_pointer_info =
old.smart_pointer_info
.map(|s| super::smart_pointer::SmartPointerInfo {
data_ptr: s.data_ptr,
cloned_from: s.cloned_from,
clones: s.clones,
ref_count_history: s
.ref_count_history
.iter()
.map(|r| super::smart_pointer::RefCountSnapshot {
timestamp: r.timestamp,
strong_count: r.strong_count,
weak_count: r.weak_count,
})
.collect(),
weak_count: s.weak_count,
is_weak_reference: s.is_weak_reference,
is_data_owner: s.is_data_owner,
is_implicitly_deallocated: s.is_implicitly_deallocated,
pointer_type: match s.pointer_type {
crate::core::types::SmartPointerType::Rc => {
super::smart_pointer::SmartPointerType::Rc
}
crate::core::types::SmartPointerType::Arc => {
super::smart_pointer::SmartPointerType::Arc
}
crate::core::types::SmartPointerType::RcWeak => {
super::smart_pointer::SmartPointerType::RcWeak
}
crate::core::types::SmartPointerType::ArcWeak => {
super::smart_pointer::SmartPointerType::ArcWeak
}
crate::core::types::SmartPointerType::Box => {
super::smart_pointer::SmartPointerType::Box
}
},
});
Self {
ptr: old.ptr,
size: old.size,
var_name: old.var_name,
type_name: old.type_name,
scope_name: old.scope_name,
timestamp_alloc: old.timestamp_alloc,
timestamp_dealloc: old.timestamp_dealloc,
thread_id,
thread_id_u64: old.thread_id.parse().unwrap_or_else(|_| {
tracing::warn!(
"Failed to parse thread_id: '{}', defaulting to 0",
old.thread_id
);
0
}),
borrow_count: old.borrow_count,
stack_trace: old.stack_trace,
is_leaked: old.is_leaked,
lifetime_ms: old.lifetime_ms,
borrow_info,
clone_info,
ownership_history_available: old.ownership_history_available,
smart_pointer_info,
memory_layout: old.memory_layout.map(Into::into),
generic_info: old.generic_info.map(Into::into),
dynamic_type_info: old.dynamic_type_info.map(Into::into),
runtime_state: old.runtime_state.map(Into::into),
stack_allocation: old.stack_allocation.map(Into::into),
temporary_object: old.temporary_object.map(Into::into),
fragmentation_analysis: old.fragmentation_analysis.map(Into::into),
generic_instantiation: old.generic_instantiation.map(Into::into),
type_relationships: old.type_relationships.map(Into::into),
type_usage: old.type_usage.map(Into::into),
function_call_tracking: old.function_call_tracking.map(Into::into),
lifecycle_tracking: old.lifecycle_tracking.map(Into::into),
access_tracking: old.access_tracking.map(Into::into),
drop_chain_analysis: old.drop_chain_analysis.map(Into::into),
module_path: None, stack_ptr: None,
task_id: None,
}
}
}
impl From<crate::capture::backends::core_types::AllocationInfo> for AllocationInfo {
fn from(info: crate::capture::backends::core_types::AllocationInfo) -> Self {
Self {
ptr: info.ptr,
size: info.size,
var_name: info.var_name,
type_name: info.type_name,
scope_name: None,
timestamp_alloc: info.allocated_at_ns,
timestamp_dealloc: None,
thread_id: std::thread::current().id(),
thread_id_u64: info.thread_id,
borrow_count: 0,
stack_trace: info.stack_trace,
is_leaked: false,
lifetime_ms: None,
module_path: None,
borrow_info: None,
clone_info: None,
ownership_history_available: false,
smart_pointer_info: None,
memory_layout: None,
generic_info: None,
dynamic_type_info: None,
runtime_state: None,
stack_allocation: None,
temporary_object: None,
fragmentation_analysis: None,
generic_instantiation: None,
type_relationships: None,
type_usage: None,
function_call_tracking: None,
lifecycle_tracking: None,
access_tracking: None,
drop_chain_analysis: None,
stack_ptr: None,
task_id: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TypeUsageInfo {
pub type_name: String,
pub total_usage_count: u64,
pub usage_contexts: Vec<UsageContext>,
pub usage_timeline: Vec<UsageTimePoint>,
pub hot_paths: Vec<HotPath>,
pub performance_impact: TypePerformanceImpact,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UsageContext {
pub context_type: ContextType,
pub location: String,
pub frequency: u32,
pub performance_metrics: ContextPerformanceMetrics,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ContextType {
FunctionParameter,
FunctionReturn,
LocalVariable,
StructField,
EnumVariant,
TraitMethod,
GenericConstraint,
ClosureCapture,
AsyncContext,
UnsafeContext,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ContextPerformanceMetrics {
pub avg_execution_time_ns: f64,
pub allocation_frequency: f64,
pub cache_miss_rate: f64,
pub branch_misprediction_rate: f64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UsageTimePoint {
pub timestamp: u64,
pub usage_count: u32,
pub memory_usage: usize,
pub performance_snapshot: PerformanceSnapshot,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PerformanceSnapshot {
pub cpu_usage: f64,
pub memory_usage: f64,
pub cache_hit_rate: f64,
pub throughput: f64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HotPath {
pub path_id: String,
pub call_sequence: Vec<String>,
pub execution_frequency: u64,
pub total_execution_time_ns: u64,
pub avg_execution_time_ns: f64,
pub memory_allocations: u32,
pub bottlenecks: Vec<PerformanceBottleneck>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PerformanceBottleneck {
pub bottleneck_type: BottleneckType,
pub location: String,
pub severity: ImpactLevel,
pub description: String,
pub optimization_suggestion: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum BottleneckType {
MemoryAllocation,
MemoryDeallocation,
CacheMiss,
BranchMisprediction,
FunctionCall,
DataMovement,
Synchronization,
IO,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ImpactLevel {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TypePerformanceImpact {
pub performance_score: f64,
pub memory_efficiency_score: f64,
pub cpu_efficiency_score: f64,
pub cache_efficiency_score: f64,
pub optimization_recommendations: Vec<OptimizationRecommendation>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OptimizationRecommendation {
pub recommendation_type: RecommendationType,
pub priority: Priority,
pub description: String,
pub expected_improvement: f64,
pub implementation_difficulty: ImplementationDifficulty,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum RecommendationType {
MemoryLayout,
AlgorithmChange,
DataStructureChange,
CachingStrategy,
MemoryPooling,
LazyInitialization,
Inlining,
Vectorization,
Parallelization,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Priority {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ImplementationDifficulty {
Easy,
Medium,
Hard,
VeryHard,
}
impl Serialize for AllocationInfo {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct("AllocationInfo", 25)?;
state.serialize_field("ptr", &self.ptr)?;
state.serialize_field("size", &self.size)?;
state.serialize_field("var_name", &self.var_name)?;
state.serialize_field("type_name", &self.type_name)?;
state.serialize_field("scope_name", &self.scope_name)?;
state.serialize_field("timestamp_alloc", &self.timestamp_alloc)?;
state.serialize_field("timestamp_dealloc", &self.timestamp_dealloc)?;
state.serialize_field("thread_id", &format!("{:?}", self.thread_id))?;
state.serialize_field("borrow_count", &self.borrow_count)?;
state.serialize_field("stack_trace", &self.stack_trace)?;
state.serialize_field("is_leaked", &self.is_leaked)?;
state.serialize_field("lifetime_ms", &self.lifetime_ms)?;
state.serialize_field("borrow_info", &self.borrow_info)?;
state.serialize_field("clone_info", &self.clone_info)?;
state.serialize_field(
"ownership_history_available",
&self.ownership_history_available,
)?;
state.serialize_field("smart_pointer_info", &self.smart_pointer_info)?;
state.serialize_field("memory_layout", &self.memory_layout)?;
state.serialize_field("generic_info", &self.generic_info)?;
state.serialize_field("dynamic_type_info", &self.dynamic_type_info)?;
state.serialize_field("runtime_state", &self.runtime_state)?;
state.serialize_field("stack_allocation", &self.stack_allocation)?;
state.serialize_field("temporary_object", &self.temporary_object)?;
state.serialize_field("fragmentation_analysis", &self.fragmentation_analysis)?;
state.serialize_field("generic_instantiation", &self.generic_instantiation)?;
state.serialize_field("type_relationships", &self.type_relationships)?;
state.serialize_field("type_usage", &self.type_usage)?;
state.serialize_field("function_call_tracking", &self.function_call_tracking)?;
state.serialize_field("lifecycle_tracking", &self.lifecycle_tracking)?;
state.serialize_field("access_tracking", &self.access_tracking)?;
state.serialize_field("drop_chain_analysis", &self.drop_chain_analysis)?;
state.serialize_field("module_path", &self.module_path)?;
state.end()
}
}
impl<'de> Deserialize<'de> for AllocationInfo {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
#[derive(Deserialize)]
struct AllocationInfoHelper {
ptr: usize,
size: usize,
var_name: Option<String>,
type_name: Option<String>,
scope_name: Option<String>,
timestamp_alloc: u64,
timestamp_dealloc: Option<u64>,
#[serde(default)]
thread_id: String,
#[serde(default)]
thread_id_u64: u64,
borrow_count: usize,
stack_trace: Option<Vec<String>>,
is_leaked: bool,
lifetime_ms: Option<u64>,
borrow_info: Option<BorrowInfo>,
clone_info: Option<CloneInfo>,
ownership_history_available: Option<bool>,
smart_pointer_info: Option<SmartPointerInfo>,
memory_layout: Option<MemoryLayoutInfo>,
generic_info: Option<GenericTypeInfo>,
dynamic_type_info: Option<DynamicTypeInfo>,
runtime_state: Option<RuntimeStateInfo>,
stack_allocation: Option<StackAllocationInfo>,
temporary_object: Option<TemporaryObjectInfo>,
fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
generic_instantiation: Option<GenericInstantiationInfo>,
type_relationships: Option<TypeRelationshipInfo>,
type_usage: Option<TypeUsageInfo>,
function_call_tracking: Option<FunctionCallTrackingInfo>,
lifecycle_tracking: Option<ObjectLifecycleInfo>,
access_tracking: Option<MemoryAccessTrackingInfo>,
drop_chain_analysis: Option<DropChainAnalysis>,
module_path: Option<String>,
}
let helper = AllocationInfoHelper::deserialize(deserializer)?;
let thread_id = if !helper.thread_id.is_empty() {
thread::current().id()
} else {
thread::current().id()
};
Ok(AllocationInfo {
ptr: helper.ptr,
size: helper.size,
var_name: helper.var_name,
type_name: helper.type_name,
scope_name: helper.scope_name,
timestamp_alloc: helper.timestamp_alloc,
timestamp_dealloc: helper.timestamp_dealloc,
thread_id,
thread_id_u64: helper.thread_id_u64,
borrow_count: helper.borrow_count,
stack_trace: helper.stack_trace,
is_leaked: helper.is_leaked,
lifetime_ms: helper.lifetime_ms,
borrow_info: helper.borrow_info,
clone_info: helper.clone_info,
ownership_history_available: helper.ownership_history_available.unwrap_or(false),
smart_pointer_info: helper.smart_pointer_info,
memory_layout: helper.memory_layout,
generic_info: helper.generic_info,
dynamic_type_info: helper.dynamic_type_info,
runtime_state: helper.runtime_state,
stack_allocation: helper.stack_allocation,
temporary_object: helper.temporary_object,
fragmentation_analysis: helper.fragmentation_analysis,
generic_instantiation: helper.generic_instantiation,
type_relationships: helper.type_relationships,
type_usage: helper.type_usage,
function_call_tracking: helper.function_call_tracking,
lifecycle_tracking: helper.lifecycle_tracking,
access_tracking: helper.access_tracking,
drop_chain_analysis: helper.drop_chain_analysis,
module_path: helper.module_path,
stack_ptr: None,
task_id: None,
})
}
}
impl AllocationInfo {
pub fn new(ptr: usize, size: usize) -> Self {
crate::task_registry::global_registry().record_allocation(size);
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64;
Self {
ptr,
size,
var_name: None,
type_name: None,
scope_name: None,
timestamp_alloc: timestamp,
timestamp_dealloc: None,
thread_id: thread::current().id(),
thread_id_u64: {
use std::hash::{Hash, Hasher};
let mut hasher = std::collections::hash_map::DefaultHasher::new();
thread::current().id().hash(&mut hasher);
hasher.finish()
},
borrow_count: 0,
stack_trace: None,
is_leaked: false,
lifetime_ms: Some(1), borrow_info: None, clone_info: Some(CloneInfo {
clone_count: 0,
is_clone: false,
original_ptr: None,
_source: None,
_confidence: None,
}),
ownership_history_available: false, smart_pointer_info: None,
memory_layout: None,
generic_info: None,
dynamic_type_info: None,
runtime_state: None,
stack_allocation: None,
temporary_object: None,
fragmentation_analysis: None,
generic_instantiation: None,
type_relationships: None,
type_usage: None,
function_call_tracking: None,
lifecycle_tracking: None,
access_tracking: None,
drop_chain_analysis: None,
module_path: None,
stack_ptr: None,
task_id: crate::task_registry::TaskIdRegistry::current_task_id(),
}
}
pub fn set_source_location(&mut self, file: &str, line: u32) {
let frame = format!("{}:{}", file, line);
self.stack_trace.get_or_insert_with(Vec::new).push(frame);
}
pub fn set_smart_pointer_info(&mut self, info: SmartPointerInfo) {
self.smart_pointer_info = Some(info);
}
pub fn mark_deallocated(&mut self) {
self.timestamp_dealloc = Some(
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64,
);
}
pub fn is_active(&self) -> bool {
self.timestamp_dealloc.is_none()
}
pub fn enhance_with_type_info(&mut self, type_name: &str) {
if self.timestamp_dealloc.is_none() {
let current_time = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64;
let elapsed_ns = current_time.saturating_sub(self.timestamp_alloc);
let elapsed_ms = elapsed_ns / 1_000_000;
self.lifetime_ms = Some(if elapsed_ms == 0 { 1 } else { elapsed_ms });
}
if type_name.contains("Rc<") || type_name.contains("Arc<") {
self.clone_info = Some(CloneInfo {
clone_count: 2,
is_clone: false,
original_ptr: None,
_source: Some("inferred".to_string()),
_confidence: Some("low".to_string()),
});
self.borrow_info = Some(BorrowInfo {
immutable_borrows: 5,
mutable_borrows: 0,
max_concurrent_borrows: 5,
last_borrow_timestamp: Some(self.timestamp_alloc + 1000000),
_source: Some("inferred".to_string()),
_confidence: Some("low".to_string()),
});
} else if type_name.contains("Vec<")
|| type_name.contains("String")
|| type_name.contains("HashMap")
{
self.borrow_info = Some(BorrowInfo {
immutable_borrows: 4,
mutable_borrows: 2,
max_concurrent_borrows: 3,
last_borrow_timestamp: Some(self.timestamp_alloc + 800000),
_source: Some("inferred".to_string()),
_confidence: Some("low".to_string()),
});
} else if type_name.contains("Box<") {
self.clone_info = Some(CloneInfo {
clone_count: 0,
is_clone: false,
original_ptr: None,
_source: Some("inferred".to_string()),
_confidence: Some("low".to_string()),
});
self.borrow_info = Some(BorrowInfo {
immutable_borrows: 2,
mutable_borrows: 1,
max_concurrent_borrows: 1,
last_borrow_timestamp: Some(self.timestamp_alloc + 300000),
_source: Some("inferred".to_string()),
_confidence: Some("low".to_string()),
});
}
}
pub fn enhance_with_inference(&mut self, engine: &crate::capture::inference::InferenceEngine) {
let type_name = self.type_name.as_deref();
let inferred_borrow = engine.infer_borrow_info(type_name);
self.borrow_info = Some(BorrowInfo {
immutable_borrows: inferred_borrow.immutable_borrows,
mutable_borrows: inferred_borrow.mutable_borrows,
max_concurrent_borrows: inferred_borrow.max_concurrent_borrows,
last_borrow_timestamp: None,
_source: Some("inferred".to_string()),
_confidence: Some(format!("{:?}", inferred_borrow._confidence).to_lowercase()),
});
let inferred_sp = engine.infer_smart_pointer(type_name);
if inferred_sp.pointer_type != crate::capture::inference::SmartPointerType::Unknown {
self.clone_info = Some(CloneInfo {
clone_count: inferred_sp.ref_count.unwrap_or(0),
is_clone: false,
original_ptr: None,
_source: Some("inferred".to_string()),
_confidence: Some(format!("{:?}", inferred_sp._confidence).to_lowercase()),
});
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct RiskDistribution {
pub low_risk: usize,
pub medium_risk: usize,
pub high_risk: usize,
pub critical_risk: usize,
}
impl From<crate::core::types::TypeUsageInfo> for TypeUsageInfo {
fn from(old: crate::core::types::TypeUsageInfo) -> Self {
Self {
type_name: old.type_name,
total_usage_count: old.total_usage_count,
usage_contexts: old
.usage_contexts
.into_iter()
.map(|c| UsageContext {
context_type: match c.context_type {
crate::core::types::ContextType::FunctionParameter => {
ContextType::FunctionParameter
}
crate::core::types::ContextType::FunctionReturn => {
ContextType::FunctionReturn
}
crate::core::types::ContextType::LocalVariable => {
ContextType::LocalVariable
}
crate::core::types::ContextType::StructField => ContextType::StructField,
crate::core::types::ContextType::EnumVariant => ContextType::EnumVariant,
crate::core::types::ContextType::TraitMethod => ContextType::TraitMethod,
crate::core::types::ContextType::GenericConstraint => {
ContextType::GenericConstraint
}
crate::core::types::ContextType::ClosureCapture => {
ContextType::ClosureCapture
}
crate::core::types::ContextType::AsyncContext => ContextType::AsyncContext,
crate::core::types::ContextType::UnsafeContext => {
ContextType::UnsafeContext
}
},
location: c.location,
frequency: c.frequency,
performance_metrics: ContextPerformanceMetrics {
avg_execution_time_ns: c.performance_metrics.avg_execution_time_ns,
allocation_frequency: c.performance_metrics.allocation_frequency,
cache_miss_rate: c.performance_metrics.cache_miss_rate,
branch_misprediction_rate: c.performance_metrics.branch_misprediction_rate,
},
})
.collect(),
usage_timeline: old
.usage_timeline
.into_iter()
.map(|t| UsageTimePoint {
timestamp: t.timestamp,
usage_count: t.usage_count,
memory_usage: t.memory_usage,
performance_snapshot: PerformanceSnapshot {
cpu_usage: t.performance_snapshot.cpu_usage,
memory_usage: t.performance_snapshot.memory_usage,
cache_hit_rate: t.performance_snapshot.cache_hit_rate,
throughput: t.performance_snapshot.throughput,
},
})
.collect(),
hot_paths: old
.hot_paths
.into_iter()
.map(|h| HotPath {
path_id: h.path_id,
call_sequence: h.call_sequence,
execution_frequency: h.execution_frequency,
total_execution_time_ns: h.total_execution_time_ns,
avg_execution_time_ns: h.avg_execution_time_ns,
memory_allocations: h.memory_allocations,
bottlenecks: h
.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(),
})
.collect(),
performance_impact: TypePerformanceImpact {
performance_score: old.performance_impact.performance_score,
memory_efficiency_score: old.performance_impact.memory_efficiency_score,
cpu_efficiency_score: old.performance_impact.cpu_efficiency_score,
cache_efficiency_score: old.performance_impact.cache_efficiency_score,
optimization_recommendations: old
.performance_impact
.optimization_recommendations
.into_iter()
.map(|r| OptimizationRecommendation {
recommendation_type: match r.recommendation_type {
crate::core::types::RecommendationType::MemoryLayout => {
RecommendationType::MemoryLayout
}
crate::core::types::RecommendationType::AlgorithmChange => {
RecommendationType::AlgorithmChange
}
crate::core::types::RecommendationType::DataStructureChange => {
RecommendationType::DataStructureChange
}
crate::core::types::RecommendationType::CachingStrategy => {
RecommendationType::CachingStrategy
}
crate::core::types::RecommendationType::MemoryPooling => {
RecommendationType::MemoryPooling
}
crate::core::types::RecommendationType::LazyInitialization => {
RecommendationType::LazyInitialization
}
crate::core::types::RecommendationType::Inlining => {
RecommendationType::Inlining
}
crate::core::types::RecommendationType::Vectorization => {
RecommendationType::Vectorization
}
crate::core::types::RecommendationType::Parallelization => {
RecommendationType::Parallelization
}
},
priority: match r.priority {
crate::core::types::Priority::Low => Priority::Low,
crate::core::types::Priority::Medium => Priority::Medium,
crate::core::types::Priority::High => Priority::High,
crate::core::types::Priority::Critical => Priority::Critical,
},
description: r.description,
expected_improvement: r.expected_improvement,
implementation_difficulty: match r.implementation_difficulty {
crate::core::types::ImplementationDifficulty::Easy => {
ImplementationDifficulty::Easy
}
crate::core::types::ImplementationDifficulty::Medium => {
ImplementationDifficulty::Medium
}
crate::core::types::ImplementationDifficulty::Hard => {
ImplementationDifficulty::Hard
}
crate::core::types::ImplementationDifficulty::VeryHard => {
ImplementationDifficulty::VeryHard
}
},
})
.collect(),
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_allocation_info_creation() {
let info = AllocationInfo::new(0x12345678, 1024);
assert_eq!(info.ptr, 0x12345678);
assert_eq!(info.size, 1024);
assert!(info.is_active());
assert!(info.borrow_info.is_none());
assert!(info.clone_info.is_some());
assert!(!info.ownership_history_available);
}
#[test]
fn test_allocation_info_mark_deallocated() {
let mut info = AllocationInfo::new(0x1000, 512);
assert!(info.is_active());
info.mark_deallocated();
assert!(!info.is_active());
assert!(info.timestamp_dealloc.is_some());
}
#[test]
fn test_allocation_info_enhance_with_type_info() {
let mut info = AllocationInfo::new(0x1000, 512);
info.enhance_with_type_info("std::rc::Rc<String>");
if let Some(clone_info) = &info.clone_info {
assert_eq!(clone_info.clone_count, 2);
}
info.enhance_with_type_info("Vec<i32>");
if let Some(borrow_info) = &info.borrow_info {
assert_eq!(borrow_info.immutable_borrows, 4);
assert_eq!(borrow_info.mutable_borrows, 2);
}
}
#[test]
fn test_borrow_info_default() {
let borrow_info = BorrowInfo::default();
assert_eq!(borrow_info.immutable_borrows, 0);
assert_eq!(borrow_info.mutable_borrows, 0);
assert_eq!(borrow_info.max_concurrent_borrows, 0);
assert_eq!(borrow_info.last_borrow_timestamp, None);
}
#[test]
fn test_clone_info_default() {
let clone_info = CloneInfo::default();
assert_eq!(clone_info.clone_count, 0);
assert!(!clone_info.is_clone);
assert_eq!(clone_info.original_ptr, None);
}
#[test]
fn test_allocation_info_serialization() {
let info = AllocationInfo::new(0x1000, 512);
let serialized = serde_json::to_string(&info);
assert!(serialized.is_ok());
let json_str = serialized.expect("Failed to serialize AllocationInfo to JSON");
assert!(json_str.contains("ptr"));
assert!(json_str.contains("size"));
}
}