Skip to main content

memscope_rs/capture/types/
tracking.rs

1//! Function call tracking types.
2//!
3//! This module contains types for tracking function calls,
4//! call stacks, and performance characteristics.
5
6use serde::{Deserialize, Serialize};
7
8use super::allocation::{BottleneckType, ImpactLevel, PerformanceBottleneck};
9use super::generic::MemoryAccessPattern;
10
11/// Function call tracking information.
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13pub struct FunctionCallTrackingInfo {
14    /// Function name.
15    pub function_name: String,
16    /// Module path.
17    pub module_path: String,
18    /// Total call count.
19    pub total_call_count: u64,
20    /// Call frequency per second.
21    pub call_frequency_per_sec: f64,
22    /// Average execution time per call.
23    pub avg_execution_time_ns: f64,
24    /// Total execution time.
25    pub total_execution_time_ns: u64,
26    /// Call stack information.
27    pub call_stack_info: CallStackInfo,
28    /// Memory allocations per call.
29    pub memory_allocations_per_call: f64,
30    /// Performance characteristics.
31    pub performance_characteristics: FunctionPerformanceCharacteristics,
32    /// Call patterns.
33    pub call_patterns: Vec<CallPattern>,
34}
35
36/// Call stack information.
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38pub struct CallStackInfo {
39    /// Maximum call stack depth.
40    pub max_stack_depth: u32,
41    /// Average call stack depth.
42    pub avg_stack_depth: f64,
43    /// Most common call sequences.
44    pub common_call_sequences: Vec<CallSequence>,
45    /// Recursive call detection.
46    pub recursive_calls: Vec<RecursiveCallInfo>,
47    /// Stack overflow risk assessment.
48    pub stack_overflow_risk: StackOverflowRisk,
49}
50
51/// Call sequence information.
52#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
53pub struct CallSequence {
54    /// Sequence of function names.
55    pub function_sequence: Vec<String>,
56    /// Frequency of this sequence.
57    pub frequency: u32,
58    /// Average execution time for this sequence.
59    pub avg_execution_time_ns: f64,
60    /// Memory usage pattern for this sequence.
61    pub memory_usage_pattern: MemoryUsagePattern,
62}
63
64/// Memory usage pattern.
65#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
66pub struct MemoryUsagePattern {
67    /// Peak memory usage in sequence.
68    pub peak_memory_usage: usize,
69    /// Average memory usage.
70    pub avg_memory_usage: usize,
71    /// Memory allocation frequency.
72    pub allocation_frequency: f64,
73    /// Memory deallocation frequency.
74    pub deallocation_frequency: f64,
75    /// Memory leak potential.
76    pub leak_potential: LeakPotential,
77}
78
79/// Memory leak potential assessment.
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
81pub enum LeakPotential {
82    /// Low memory leak potential.
83    Low,
84    /// Medium memory leak potential.
85    Medium,
86    /// High memory leak potential.
87    High,
88    /// Critical memory leak potential.
89    Critical,
90}
91
92/// Recursive call information.
93#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
94pub struct RecursiveCallInfo {
95    /// Function name.
96    pub function_name: String,
97    /// Maximum recursion depth.
98    pub max_recursion_depth: u32,
99    /// Average recursion depth.
100    pub avg_recursion_depth: f64,
101    /// Tail recursion optimization potential.
102    pub tail_recursion_potential: bool,
103    /// Stack usage per recursion level.
104    pub stack_usage_per_level: usize,
105    /// Performance impact of recursion.
106    pub recursion_performance_impact: RecursionPerformanceImpact,
107}
108
109/// Recursion performance impact.
110#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
111pub struct RecursionPerformanceImpact {
112    /// Stack overhead per call.
113    pub stack_overhead_per_call: usize,
114    /// Function call overhead.
115    pub call_overhead_ns: f64,
116    /// Cache impact of deep recursion.
117    pub cache_impact: f64,
118    /// Optimization recommendations.
119    pub optimization_recommendations: Vec<String>,
120}
121
122/// Stack overflow risk assessment.
123#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
124pub enum StackOverflowRisk {
125    /// Low stack overflow risk.
126    Low,
127    /// Medium stack overflow risk.
128    Medium,
129    /// High stack overflow risk.
130    High,
131    /// Critical stack overflow risk.
132    Critical,
133}
134
135/// Function performance characteristics.
136#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
137pub struct FunctionPerformanceCharacteristics {
138    /// CPU usage percentage.
139    pub cpu_usage_percent: f64,
140    /// Memory usage characteristics.
141    pub memory_characteristics: FunctionMemoryCharacteristics,
142    /// I/O characteristics.
143    pub io_characteristics: IOCharacteristics,
144    /// Concurrency characteristics.
145    pub concurrency_characteristics: ConcurrencyCharacteristics,
146    /// Performance bottlenecks.
147    pub bottlenecks: Vec<PerformanceBottleneck>,
148}
149
150/// Function memory characteristics.
151#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
152pub struct FunctionMemoryCharacteristics {
153    /// Stack memory usage.
154    pub stack_memory_usage: usize,
155    /// Heap memory allocations.
156    pub heap_allocations: u32,
157    /// Memory access pattern.
158    pub access_pattern: MemoryAccessPattern,
159    /// Cache efficiency.
160    pub cache_efficiency: f64,
161    /// Memory bandwidth utilization.
162    pub memory_bandwidth_utilization: f64,
163}
164
165/// I/O characteristics.
166#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
167pub struct IOCharacteristics {
168    /// File I/O operations.
169    pub file_io_operations: u32,
170    /// Network I/O operations.
171    pub network_io_operations: u32,
172    /// Average I/O wait time.
173    pub avg_io_wait_time_ns: f64,
174    /// I/O throughput.
175    pub io_throughput_bytes_per_sec: f64,
176    /// I/O efficiency score.
177    pub io_efficiency_score: f64,
178}
179
180/// Concurrency characteristics.
181#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
182pub struct ConcurrencyCharacteristics {
183    /// Thread safety level.
184    pub thread_safety_level: ThreadSafetyLevel,
185    /// Lock contention frequency.
186    pub lock_contention_frequency: f64,
187    /// Parallel execution potential.
188    pub parallel_execution_potential: f64,
189    /// Synchronization overhead.
190    pub synchronization_overhead_ns: f64,
191    /// Deadlock risk assessment.
192    pub deadlock_risk: DeadlockRisk,
193}
194
195/// Thread safety levels.
196#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
197pub enum ThreadSafetyLevel {
198    /// Thread safe.
199    ThreadSafe,
200    /// Conditionally thread safe.
201    ConditionallyThreadSafe,
202    /// Not thread safe.
203    NotThreadSafe,
204    /// Unknown thread safety.
205    Unknown,
206}
207
208/// Deadlock risk assessment.
209#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
210pub enum DeadlockRisk {
211    /// No deadlock risk.
212    None,
213    /// Low deadlock risk.
214    Low,
215    /// Medium deadlock risk.
216    Medium,
217    /// High deadlock risk.
218    High,
219}
220
221/// Call pattern information.
222#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
223pub struct CallPattern {
224    /// Pattern type.
225    pub pattern_type: CallPatternType,
226    /// Pattern description.
227    pub description: String,
228    /// Frequency of this pattern.
229    pub frequency: u32,
230    /// Performance impact.
231    pub performance_impact: f64,
232    /// Optimization potential.
233    pub optimization_potential: f64,
234}
235
236/// Types of call patterns.
237#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
238pub enum CallPatternType {
239    /// Sequential call pattern.
240    Sequential,
241    /// Recursive call pattern.
242    Recursive,
243    /// Iterative call pattern.
244    Iterative,
245    /// Conditional call pattern.
246    Conditional,
247    /// Parallel call pattern.
248    Parallel,
249    /// Asynchronous call pattern.
250    Asynchronous,
251    /// Callback call pattern.
252    Callback,
253    /// Event-driven call pattern.
254    EventDriven,
255}
256
257impl From<crate::core::types::FunctionCallTrackingInfo> for FunctionCallTrackingInfo {
258    fn from(old: crate::core::types::FunctionCallTrackingInfo) -> Self {
259        Self {
260            function_name: old.function_name,
261            module_path: old.module_path,
262            total_call_count: old.total_call_count,
263            call_frequency_per_sec: old.call_frequency_per_sec,
264            avg_execution_time_ns: old.avg_execution_time_ns,
265            total_execution_time_ns: old.total_execution_time_ns,
266            call_stack_info: CallStackInfo {
267                max_stack_depth: old.call_stack_info.max_stack_depth,
268                avg_stack_depth: old.call_stack_info.avg_stack_depth,
269                common_call_sequences: old
270                    .call_stack_info
271                    .common_call_sequences
272                    .into_iter()
273                    .map(|s| CallSequence {
274                        function_sequence: s.function_sequence,
275                        frequency: s.frequency,
276                        avg_execution_time_ns: s.avg_execution_time_ns,
277                        memory_usage_pattern: MemoryUsagePattern {
278                            peak_memory_usage: s.memory_usage_pattern.peak_memory_usage,
279                            avg_memory_usage: s.memory_usage_pattern.avg_memory_usage,
280                            allocation_frequency: s.memory_usage_pattern.allocation_frequency,
281                            deallocation_frequency: s.memory_usage_pattern.deallocation_frequency,
282                            leak_potential: match s.memory_usage_pattern.leak_potential {
283                                crate::core::types::LeakPotential::Low => LeakPotential::Low,
284                                crate::core::types::LeakPotential::Medium => LeakPotential::Medium,
285                                crate::core::types::LeakPotential::High => LeakPotential::High,
286                                crate::core::types::LeakPotential::Critical => {
287                                    LeakPotential::Critical
288                                }
289                            },
290                        },
291                    })
292                    .collect(),
293                recursive_calls: old
294                    .call_stack_info
295                    .recursive_calls
296                    .into_iter()
297                    .map(|r| RecursiveCallInfo {
298                        function_name: r.function_name,
299                        max_recursion_depth: r.max_recursion_depth,
300                        avg_recursion_depth: r.avg_recursion_depth,
301                        tail_recursion_potential: r.tail_recursion_potential,
302                        stack_usage_per_level: r.stack_usage_per_level,
303                        recursion_performance_impact: RecursionPerformanceImpact {
304                            stack_overhead_per_call: r
305                                .recursion_performance_impact
306                                .stack_overhead_per_call,
307                            call_overhead_ns: r.recursion_performance_impact.call_overhead_ns,
308                            cache_impact: r.recursion_performance_impact.cache_impact,
309                            optimization_recommendations: r
310                                .recursion_performance_impact
311                                .optimization_recommendations,
312                        },
313                    })
314                    .collect(),
315                stack_overflow_risk: match old.call_stack_info.stack_overflow_risk {
316                    crate::core::types::StackOverflowRisk::Low => StackOverflowRisk::Low,
317                    crate::core::types::StackOverflowRisk::Medium => StackOverflowRisk::Medium,
318                    crate::core::types::StackOverflowRisk::High => StackOverflowRisk::High,
319                    crate::core::types::StackOverflowRisk::Critical => StackOverflowRisk::Critical,
320                },
321            },
322            memory_allocations_per_call: old.memory_allocations_per_call,
323            performance_characteristics: FunctionPerformanceCharacteristics {
324                cpu_usage_percent: old.performance_characteristics.cpu_usage_percent,
325                memory_characteristics: FunctionMemoryCharacteristics {
326                    stack_memory_usage: old
327                        .performance_characteristics
328                        .memory_characteristics
329                        .stack_memory_usage,
330                    heap_allocations: old
331                        .performance_characteristics
332                        .memory_characteristics
333                        .heap_allocations,
334                    access_pattern: match old
335                        .performance_characteristics
336                        .memory_characteristics
337                        .access_pattern
338                    {
339                        crate::core::types::MemoryAccessPattern::Sequential => {
340                            MemoryAccessPattern::Sequential
341                        }
342                        crate::core::types::MemoryAccessPattern::Random => {
343                            MemoryAccessPattern::Random
344                        }
345                        crate::core::types::MemoryAccessPattern::Strided { stride } => {
346                            MemoryAccessPattern::Strided { stride }
347                        }
348                        crate::core::types::MemoryAccessPattern::Clustered => {
349                            MemoryAccessPattern::Clustered
350                        }
351                        crate::core::types::MemoryAccessPattern::Mixed => {
352                            MemoryAccessPattern::Mixed
353                        }
354                    },
355                    cache_efficiency: old
356                        .performance_characteristics
357                        .memory_characteristics
358                        .cache_efficiency,
359                    memory_bandwidth_utilization: old
360                        .performance_characteristics
361                        .memory_characteristics
362                        .memory_bandwidth_utilization,
363                },
364                io_characteristics: IOCharacteristics {
365                    file_io_operations: old
366                        .performance_characteristics
367                        .io_characteristics
368                        .file_io_operations,
369                    network_io_operations: old
370                        .performance_characteristics
371                        .io_characteristics
372                        .network_io_operations,
373                    avg_io_wait_time_ns: old
374                        .performance_characteristics
375                        .io_characteristics
376                        .avg_io_wait_time_ns,
377                    io_throughput_bytes_per_sec: old
378                        .performance_characteristics
379                        .io_characteristics
380                        .io_throughput_bytes_per_sec,
381                    io_efficiency_score: old
382                        .performance_characteristics
383                        .io_characteristics
384                        .io_efficiency_score,
385                },
386                concurrency_characteristics: ConcurrencyCharacteristics {
387                    thread_safety_level: match old
388                        .performance_characteristics
389                        .concurrency_characteristics
390                        .thread_safety_level
391                    {
392                        crate::core::types::ThreadSafetyLevel::ThreadSafe => {
393                            ThreadSafetyLevel::ThreadSafe
394                        }
395                        crate::core::types::ThreadSafetyLevel::ConditionallyThreadSafe => {
396                            ThreadSafetyLevel::ConditionallyThreadSafe
397                        }
398                        crate::core::types::ThreadSafetyLevel::NotThreadSafe => {
399                            ThreadSafetyLevel::NotThreadSafe
400                        }
401                        crate::core::types::ThreadSafetyLevel::Unknown => {
402                            ThreadSafetyLevel::Unknown
403                        }
404                    },
405                    lock_contention_frequency: old
406                        .performance_characteristics
407                        .concurrency_characteristics
408                        .lock_contention_frequency,
409                    parallel_execution_potential: old
410                        .performance_characteristics
411                        .concurrency_characteristics
412                        .parallel_execution_potential,
413                    synchronization_overhead_ns: old
414                        .performance_characteristics
415                        .concurrency_characteristics
416                        .synchronization_overhead_ns,
417                    deadlock_risk: match old
418                        .performance_characteristics
419                        .concurrency_characteristics
420                        .deadlock_risk
421                    {
422                        crate::core::types::DeadlockRisk::None => DeadlockRisk::None,
423                        crate::core::types::DeadlockRisk::Low => DeadlockRisk::Low,
424                        crate::core::types::DeadlockRisk::Medium => DeadlockRisk::Medium,
425                        crate::core::types::DeadlockRisk::High => DeadlockRisk::High,
426                    },
427                },
428                bottlenecks: old
429                    .performance_characteristics
430                    .bottlenecks
431                    .into_iter()
432                    .map(|b| PerformanceBottleneck {
433                        bottleneck_type: match b.bottleneck_type {
434                            crate::core::types::BottleneckType::MemoryAllocation => {
435                                BottleneckType::MemoryAllocation
436                            }
437                            crate::core::types::BottleneckType::MemoryDeallocation => {
438                                BottleneckType::MemoryDeallocation
439                            }
440                            crate::core::types::BottleneckType::CacheMiss => {
441                                BottleneckType::CacheMiss
442                            }
443                            crate::core::types::BottleneckType::BranchMisprediction => {
444                                BottleneckType::BranchMisprediction
445                            }
446                            crate::core::types::BottleneckType::FunctionCall => {
447                                BottleneckType::FunctionCall
448                            }
449                            crate::core::types::BottleneckType::DataMovement => {
450                                BottleneckType::DataMovement
451                            }
452                            crate::core::types::BottleneckType::Synchronization => {
453                                BottleneckType::Synchronization
454                            }
455                            crate::core::types::BottleneckType::IO => BottleneckType::IO,
456                        },
457                        location: b.location,
458                        severity: match b.severity {
459                            crate::core::types::ImpactLevel::Low => ImpactLevel::Low,
460                            crate::core::types::ImpactLevel::Medium => ImpactLevel::Medium,
461                            crate::core::types::ImpactLevel::High => ImpactLevel::High,
462                            crate::core::types::ImpactLevel::Critical => ImpactLevel::Critical,
463                        },
464                        description: b.description,
465                        optimization_suggestion: b.optimization_suggestion,
466                    })
467                    .collect(),
468            },
469            call_patterns: old
470                .call_patterns
471                .into_iter()
472                .map(|p| CallPattern {
473                    pattern_type: match p.pattern_type {
474                        crate::core::types::CallPatternType::Sequential => {
475                            CallPatternType::Sequential
476                        }
477                        crate::core::types::CallPatternType::Recursive => {
478                            CallPatternType::Recursive
479                        }
480                        crate::core::types::CallPatternType::Iterative => {
481                            CallPatternType::Iterative
482                        }
483                        crate::core::types::CallPatternType::Conditional => {
484                            CallPatternType::Conditional
485                        }
486                        crate::core::types::CallPatternType::Parallel => CallPatternType::Parallel,
487                        crate::core::types::CallPatternType::Asynchronous => {
488                            CallPatternType::Asynchronous
489                        }
490                        crate::core::types::CallPatternType::Callback => CallPatternType::Callback,
491                        crate::core::types::CallPatternType::EventDriven => {
492                            CallPatternType::EventDriven
493                        }
494                    },
495                    description: p.description,
496                    frequency: p.frequency,
497                    performance_impact: p.performance_impact,
498                    optimization_potential: p.optimization_potential,
499                })
500                .collect(),
501        }
502    }
503}
504
505#[cfg(test)]
506mod tests {
507    use super::*;
508
509    #[test]
510    fn test_function_call_tracking_info() {
511        let info = FunctionCallTrackingInfo {
512            function_name: "test_func".to_string(),
513            module_path: "test::module".to_string(),
514            total_call_count: 100,
515            call_frequency_per_sec: 10.0,
516            avg_execution_time_ns: 1000.0,
517            total_execution_time_ns: 100000,
518            call_stack_info: CallStackInfo {
519                max_stack_depth: 5,
520                avg_stack_depth: 3.0,
521                common_call_sequences: vec![],
522                recursive_calls: vec![],
523                stack_overflow_risk: StackOverflowRisk::Low,
524            },
525            memory_allocations_per_call: 2.0,
526            performance_characteristics: FunctionPerformanceCharacteristics {
527                cpu_usage_percent: 5.0,
528                memory_characteristics: FunctionMemoryCharacteristics {
529                    stack_memory_usage: 1024,
530                    heap_allocations: 5,
531                    access_pattern: MemoryAccessPattern::Sequential,
532                    cache_efficiency: 0.9,
533                    memory_bandwidth_utilization: 0.5,
534                },
535                io_characteristics: IOCharacteristics {
536                    file_io_operations: 0,
537                    network_io_operations: 0,
538                    avg_io_wait_time_ns: 0.0,
539                    io_throughput_bytes_per_sec: 0.0,
540                    io_efficiency_score: 1.0,
541                },
542                concurrency_characteristics: ConcurrencyCharacteristics {
543                    thread_safety_level: ThreadSafetyLevel::ThreadSafe,
544                    lock_contention_frequency: 0.0,
545                    parallel_execution_potential: 0.8,
546                    synchronization_overhead_ns: 0.0,
547                    deadlock_risk: DeadlockRisk::None,
548                },
549                bottlenecks: vec![],
550            },
551            call_patterns: vec![],
552        };
553
554        assert_eq!(info.function_name, "test_func");
555        assert_eq!(info.total_call_count, 100);
556    }
557
558    #[test]
559    fn test_call_pattern_type() {
560        let patterns = vec![
561            CallPatternType::Sequential,
562            CallPatternType::Recursive,
563            CallPatternType::Parallel,
564        ];
565
566        for pattern in patterns {
567            assert!(!format!("{pattern:?}").is_empty());
568        }
569    }
570}