performance_monitor.py
CrazyFly/python/utils/performance_monitor.py
"""
Performance Monitoring System for Quadrotor Control System
=========================================================
This module provides a comprehensive performance monitoring system
for tracking system metrics, resource usage, and real-time performance
analysis.
Key Features:
- Real-time system metrics monitoring
- CPU, memory, and network usage tracking
- Control loop performance analysis
- Latency and jitter measurement
- Performance bottleneck detection
- Resource usage alerts
- Performance data visualization
- Historical performance analysis
- Performance reporting and export
The performance monitor enables comprehensive tracking and analysis
of system performance for optimization and debugging.
Author: [Your Name]
Date: [Current Date]
License: MIT
"""
import numpy as np
import time
import threading
import psutil
import os
from typing import Dict, List, Tuple, Optional, Any, Callable
from dataclasses import dataclass, field
from enum import Enum
from pathlib import Path
import logging
from datetime import datetime
import json
import matplotlib.pyplot as plt
from collections import deque
import statistics
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class MetricType(Enum):
"""Enumeration of metric types."""
CPU_USAGE = "cpu_usage"
MEMORY_USAGE = "memory_usage"
NETWORK_IO = "network_io"
DISK_IO = "disk_io"
CONTROL_LATENCY = "control_latency"
SENSOR_LATENCY = "sensor_latency"
COMMUNICATION_LATENCY = "communication_latency"
THREAD_COUNT = "thread_count"
PROCESS_COUNT = "process_count"
TEMPERATURE = "temperature"
BATTERY_LEVEL = "battery_level"
CUSTOM = "custom"
class AlertLevel(Enum):
"""Enumeration of alert levels."""
INFO = "info"
WARNING = "warning"
ERROR = "error"
CRITICAL = "critical"
@dataclass
class PerformanceMetric:
"""
Performance metric data structure.
Attributes:
name (str): Metric name
value (float): Metric value
unit (str): Unit of measurement
timestamp (float): Timestamp in seconds
metric_type (MetricType): Type of metric
metadata (Dict[str, Any]): Additional metadata
"""
name: str
value: float
unit: str
timestamp: float
metric_type: MetricType
metadata: Dict[str, Any] = field(default_factory=dict)
@dataclass
class PerformanceAlert:
"""
Performance alert data structure.
Attributes:
metric_name (str): Name of the metric that triggered the alert
alert_level (AlertLevel): Alert level
message (str): Alert message
timestamp (float): Timestamp when alert was triggered
threshold (float): Threshold that was exceeded
current_value (float): Current value that triggered the alert
"""
metric_name: str
alert_level: AlertLevel
message: str
timestamp: float
threshold: float
current_value: float
@dataclass
class PerformanceConfig:
"""
Performance monitoring configuration.
Attributes:
update_interval (float): Update interval in seconds
history_length (int): Number of historical data points to keep
enable_cpu_monitoring (bool): Enable CPU monitoring
enable_memory_monitoring (bool): Enable memory monitoring
enable_network_monitoring (bool): Enable network monitoring
enable_disk_monitoring (bool): Enable disk monitoring
enable_control_monitoring (bool): Enable control loop monitoring
alert_thresholds (Dict[str, float]): Alert thresholds for metrics
enable_alerts (bool): Enable performance alerts
enable_logging (bool): Enable performance logging
log_file (str): Performance log file path
"""
update_interval: float = 1.0
history_length: int = 1000
enable_cpu_monitoring: bool = True
enable_memory_monitoring: bool = True
enable_network_monitoring: bool = True
enable_disk_monitoring: bool = False
enable_control_monitoring: bool = True
alert_thresholds: Dict[str, float] = field(default_factory=dict)
enable_alerts: bool = True
enable_logging: bool = True
log_file: str = "performance.log"
class PerformanceCollector:
"""
Performance data collector.
This class collects various system performance metrics
using the psutil library and custom timing measurements.
"""
def __init__(self):
"""Initialize performance collector."""
self.cpu_times = deque(maxlen=2)
self.network_io = deque(maxlen=2)
self.disk_io = deque(maxlen=2)
# Initialize baseline measurements
self._initialize_baselines()
logger.info("Performance collector initialized")
def _initialize_baselines(self):
"""Initialize baseline measurements."""
self.cpu_times.append(psutil.cpu_times_percent())
self.network_io.append(psutil.net_io_counters())
self.disk_io.append(psutil.disk_io_counters())
def collect_cpu_metrics(self) -> Dict[str, float]:
"""
Collect CPU performance metrics.
Returns:
Dict[str, float]: CPU metrics
"""
cpu_times = psutil.cpu_times_percent()
self.cpu_times.append(cpu_times)
if len(self.cpu_times) >= 2:
# Calculate CPU usage change
prev_times = self.cpu_times[0]
curr_times = self.cpu_times[1]
total_prev = sum(prev_times)
total_curr = sum(curr_times)
if total_prev > 0:
cpu_usage = ((total_curr - total_prev) / total_prev) * 100
else:
cpu_usage = 0.0
else:
cpu_usage = 0.0
return {
'cpu_percent': psutil.cpu_percent(interval=0.1),
'cpu_count': psutil.cpu_count(),
'cpu_freq': psutil.cpu_freq().current if psutil.cpu_freq() else 0.0,
'cpu_usage_change': cpu_usage
}
def collect_memory_metrics(self) -> Dict[str, float]:
"""
Collect memory performance metrics.
Returns:
Dict[str, float]: Memory metrics
"""
memory = psutil.virtual_memory()
return {
'memory_percent': memory.percent,
'memory_used': memory.used / (1024**3), # GB
'memory_available': memory.available / (1024**3), # GB
'memory_total': memory.total / (1024**3), # GB
'memory_free': memory.free / (1024**3), # GB
'swap_percent': psutil.swap_memory().percent if hasattr(psutil, 'swap_memory') else 0.0
}
def collect_network_metrics(self) -> Dict[str, float]:
"""
Collect network performance metrics.
Returns:
Dict[str, float]: Network metrics
"""
network_io = psutil.net_io_counters()
self.network_io.append(network_io)
if len(self.network_io) >= 2:
# Calculate network I/O rates
prev_io = self.network_io[0]
curr_io = self.network_io[1]
bytes_sent_rate = (curr_io.bytes_sent - prev_io.bytes_sent) / 1024 # KB/s
bytes_recv_rate = (curr_io.bytes_recv - prev_io.bytes_recv) / 1024 # KB/s
packets_sent_rate = curr_io.packets_sent - prev_io.packets_sent
packets_recv_rate = curr_io.packets_recv - prev_io.packets_recv
else:
bytes_sent_rate = 0.0
bytes_recv_rate = 0.0
packets_sent_rate = 0.0
packets_recv_rate = 0.0
return {
'bytes_sent_rate': bytes_sent_rate,
'bytes_recv_rate': bytes_recv_rate,
'packets_sent_rate': packets_sent_rate,
'packets_recv_rate': packets_recv_rate,
'bytes_sent_total': network_io.bytes_sent / (1024**3), # GB
'bytes_recv_total': network_io.bytes_recv / (1024**3), # GB
'packets_sent_total': network_io.packets_sent,
'packets_recv_total': network_io.packets_recv
}
def collect_disk_metrics(self) -> Dict[str, float]:
"""
Collect disk performance metrics.
Returns:
Dict[str, float]: Disk metrics
"""
disk_io = psutil.disk_io_counters()
self.disk_io.append(disk_io)
if len(self.disk_io) >= 2:
# Calculate disk I/O rates
prev_io = self.disk_io[0]
curr_io = self.disk_io[1]
read_bytes_rate = (curr_io.read_bytes - prev_io.read_bytes) / 1024 # KB/s
write_bytes_rate = (curr_io.write_bytes - prev_io.write_bytes) / 1024 # KB/s
read_count_rate = curr_io.read_count - prev_io.read_count
write_count_rate = curr_io.write_count - prev_io.write_count
else:
read_bytes_rate = 0.0
write_bytes_rate = 0.0
read_count_rate = 0.0
write_count_rate = 0.0
# Disk usage
disk_usage = psutil.disk_usage('/')
return {
'read_bytes_rate': read_bytes_rate,
'write_bytes_rate': write_bytes_rate,
'read_count_rate': read_count_rate,
'write_count_rate': write_count_rate,
'disk_percent': disk_usage.percent,
'disk_used': disk_usage.used / (1024**3), # GB
'disk_free': disk_usage.free / (1024**3), # GB
'disk_total': disk_usage.total / (1024**3) # GB
}
def collect_process_metrics(self) -> Dict[str, float]:
"""
Collect process performance metrics.
Returns:
Dict[str, float]: Process metrics
"""
current_process = psutil.Process()
return {
'process_cpu_percent': current_process.cpu_percent(),
'process_memory_percent': current_process.memory_percent(),
'process_memory_rss': current_process.memory_info().rss / (1024**2), # MB
'process_memory_vms': current_process.memory_info().vms / (1024**2), # MB
'process_threads': current_process.num_threads(),
'process_open_files': len(current_process.open_files()),
'process_connections': len(current_process.connections())
}
def collect_system_metrics(self) -> Dict[str, float]:
"""
Collect general system metrics.
Returns:
Dict[str, float]: System metrics
"""
return {
'thread_count': threading.active_count(),
'process_count': len(psutil.pids()),
'load_average': psutil.getloadavg()[0] if hasattr(psutil, 'getloadavg') else 0.0,
'boot_time': psutil.boot_time(),
'uptime': time.time() - psutil.boot_time()
}
class PerformanceAnalyzer:
"""
Performance data analyzer.
This class analyzes performance data to detect trends,
bottlenecks, and anomalies.
"""
def __init__(self, history_length: int = 1000):
"""
Initialize performance analyzer.
Args:
history_length (int): Length of historical data to keep
"""
self.history_length = history_length
self.metric_history: Dict[str, deque] = {}
self.analysis_results: Dict[str, Any] = {}
logger.info("Performance analyzer initialized")
def add_metric(self, metric: PerformanceMetric):
"""
Add a metric to the analyzer.
Args:
metric (PerformanceMetric): Performance metric
"""
if metric.name not in self.metric_history:
self.metric_history[metric.name] = deque(maxlen=self.history_length)
self.metric_history[metric.name].append(metric)
def analyze_metric(self, metric_name: str) -> Dict[str, Any]:
"""
Analyze a specific metric.
Args:
metric_name (str): Name of the metric to analyze
Returns:
Dict[str, Any]: Analysis results
"""
if metric_name not in self.metric_history:
return {}
history = list(self.metric_history[metric_name])
if not history:
return {}
values = [metric.value for metric in history]
timestamps = [metric.timestamp for metric in history]
# Basic statistics
stats = {
'count': len(values),
'mean': statistics.mean(values),
'median': statistics.median(values),
'std': statistics.stdev(values) if len(values) > 1 else 0.0,
'min': min(values),
'max': max(values),
'range': max(values) - min(values)
}
# Trend analysis
if len(values) >= 2:
# Linear trend
x = np.array(timestamps)
y = np.array(values)
coeffs = np.polyfit(x, y, 1)
trend_slope = coeffs[0]
trend_intercept = coeffs[1]
# R-squared
y_pred = coeffs[0] * x + coeffs[1]
ss_res = np.sum((y - y_pred) ** 2)
ss_tot = np.sum((y - np.mean(y)) ** 2)
r_squared = 1 - (ss_res / ss_tot) if ss_tot > 0 else 0.0
stats.update({
'trend_slope': trend_slope,
'trend_intercept': trend_intercept,
'r_squared': r_squared,
'trend_direction': 'increasing' if trend_slope > 0 else 'decreasing' if trend_slope < 0 else 'stable'
})
# Anomaly detection
if len(values) >= 3:
# Simple outlier detection using z-score
mean_val = statistics.mean(values)
std_val = statistics.stdev(values)
outliers = []
for i, value in enumerate(values):
z_score = abs((value - mean_val) / std_val) if std_val > 0 else 0.0
if z_score > 2.0: # 2 standard deviations
outliers.append({
'index': i,
'value': value,
'z_score': z_score,
'timestamp': timestamps[i]
})
stats['outliers'] = outliers
stats['outlier_count'] = len(outliers)
# Performance indicators
if len(values) >= 10:
# Moving averages
window_size = min(10, len(values))
recent_values = values[-window_size:]
stats['moving_average'] = statistics.mean(recent_values)
# Volatility
if len(recent_values) > 1:
stats['volatility'] = statistics.stdev(recent_values)
else:
stats['volatility'] = 0.0
return stats
def analyze_all_metrics(self) -> Dict[str, Dict[str, Any]]:
"""
Analyze all metrics.
Returns:
Dict[str, Dict[str, Any]]: Analysis results for all metrics
"""
results = {}
for metric_name in self.metric_history:
results[metric_name] = self.analyze_metric(metric_name)
self.analysis_results = results
return results
def detect_bottlenecks(self) -> List[Dict[str, Any]]:
"""
Detect performance bottlenecks.
Returns:
List[Dict[str, Any]]: List of detected bottlenecks
"""
bottlenecks = []
# Analyze all metrics first
self.analyze_all_metrics()
# Check for high CPU usage
if 'cpu_percent' in self.analysis_results:
cpu_stats = self.analysis_results['cpu_percent']
if cpu_stats.get('mean', 0) > 80.0:
bottlenecks.append({
'type': 'high_cpu_usage',
'metric': 'cpu_percent',
'severity': 'high' if cpu_stats['mean'] > 90.0 else 'medium',
'value': cpu_stats['mean'],
'threshold': 80.0,
'description': f"High CPU usage: {cpu_stats['mean']:.1f}%"
})
# Check for high memory usage
if 'memory_percent' in self.analysis_results:
memory_stats = self.analysis_results['memory_percent']
if memory_stats.get('mean', 0) > 85.0:
bottlenecks.append({
'type': 'high_memory_usage',
'metric': 'memory_percent',
'severity': 'high' if memory_stats['mean'] > 95.0 else 'medium',
'value': memory_stats['mean'],
'threshold': 85.0,
'description': f"High memory usage: {memory_stats['mean']:.1f}%"
})
# Check for high latency
for metric_name in self.metric_history:
if 'latency' in metric_name.lower():
latency_stats = self.analysis_results.get(metric_name, {})
if latency_stats.get('mean', 0) > 0.1: # 100ms threshold
bottlenecks.append({
'type': 'high_latency',
'metric': metric_name,
'severity': 'high' if latency_stats['mean'] > 0.5 else 'medium',
'value': latency_stats['mean'],
'threshold': 0.1,
'description': f"High latency in {metric_name}: {latency_stats['mean']:.3f}s"
})
return bottlenecks
def generate_report(self) -> Dict[str, Any]:
"""
Generate a comprehensive performance report.
Returns:
Dict[str, Any]: Performance report
"""
# Analyze all metrics
analysis = self.analyze_all_metrics()
# Detect bottlenecks
bottlenecks = self.detect_bottlenecks()
# Generate summary
total_metrics = len(self.metric_history)
total_data_points = sum(len(history) for history in self.metric_history.values())
report = {
'timestamp': time.time(),
'summary': {
'total_metrics': total_metrics,
'total_data_points': total_data_points,
'bottleneck_count': len(bottlenecks),
'critical_bottlenecks': len([b for b in bottlenecks if b['severity'] == 'high'])
},
'analysis': analysis,
'bottlenecks': bottlenecks,
'recommendations': self._generate_recommendations(bottlenecks)
}
return report
def _generate_recommendations(self, bottlenecks: List[Dict[str, Any]]) -> List[str]:
"""
Generate recommendations based on bottlenecks.
Args:
bottlenecks (List[Dict[str, Any]]): Detected bottlenecks
Returns:
List[str]: List of recommendations
"""
recommendations = []
for bottleneck in bottlenecks:
if bottleneck['type'] == 'high_cpu_usage':
recommendations.append("Consider optimizing CPU-intensive operations or reducing update frequency")
elif bottleneck['type'] == 'high_memory_usage':
recommendations.append("Consider implementing memory cleanup or reducing data retention")
elif bottleneck['type'] == 'high_latency':
recommendations.append("Consider optimizing communication or reducing data transfer size")
return recommendations
class PerformanceMonitor:
"""
Main performance monitoring class.
This class provides comprehensive performance monitoring
functionality with real-time data collection and analysis.
"""
def __init__(self, config: PerformanceConfig = None):
"""
Initialize performance monitor.
Args:
config (PerformanceConfig): Performance monitoring configuration
"""
self.config = config or PerformanceConfig()
# Initialize components
self.collector = PerformanceCollector()
self.analyzer = PerformanceAnalyzer(self.config.history_length)
# Monitoring state
self.monitoring = False
self.monitor_thread = None
self.start_time = None
# Alert system
self.alerts: List[PerformanceAlert] = []
self.alert_callbacks: List[Callable] = []
# Performance logging
self.log_file = None
if self.config.enable_logging:
self.log_file = open(self.config.log_file, 'w')
logger.info("Performance monitor initialized")
def start_monitoring(self):
"""Start performance monitoring."""
if self.monitoring:
logger.warning("Performance monitoring is already running")
return
self.monitoring = True
self.start_time = time.time()
self.monitor_thread = threading.Thread(target=self._monitoring_loop, daemon=True)
self.monitor_thread.start()
logger.info("Performance monitoring started")
def stop_monitoring(self):
"""Stop performance monitoring."""
if not self.monitoring:
logger.warning("Performance monitoring is not running")
return
self.monitoring = False
if self.monitor_thread and self.monitor_thread.is_alive():
self.monitor_thread.join(timeout=5.0)
# Close log file
if self.log_file:
self.log_file.close()
self.log_file = None
logger.info("Performance monitoring stopped")
def _monitoring_loop(self):
"""Main monitoring loop."""
while self.monitoring:
try:
# Collect system metrics
self._collect_system_metrics()
# Check for alerts
self._check_alerts()
# Sleep for update interval
time.sleep(self.config.update_interval)
except Exception as e:
logger.error(f"Error in monitoring loop: {e}")
def _collect_system_metrics(self):
"""Collect all system metrics."""
timestamp = time.time()
# CPU metrics
if self.config.enable_cpu_monitoring:
cpu_metrics = self.collector.collect_cpu_metrics()
for name, value in cpu_metrics.items():
metric = PerformanceMetric(
name=f"cpu_{name}",
value=value,
unit="%" if "percent" in name else "count" if "count" in name else "MHz",
timestamp=timestamp,
metric_type=MetricType.CPU_USAGE
)
self.analyzer.add_metric(metric)
self._log_metric(metric)
# Memory metrics
if self.config.enable_memory_monitoring:
memory_metrics = self.collector.collect_memory_metrics()
for name, value in memory_metrics.items():
metric = PerformanceMetric(
name=f"memory_{name}",
value=value,
unit="%" if "percent" in name else "GB",
timestamp=timestamp,
metric_type=MetricType.MEMORY_USAGE
)
self.analyzer.add_metric(metric)
self._log_metric(metric)
# Network metrics
if self.config.enable_network_monitoring:
network_metrics = self.collector.collect_network_metrics()
for name, value in network_metrics.items():
metric = PerformanceMetric(
name=f"network_{name}",
value=value,
unit="KB/s" if "rate" in name else "GB" if "total" in name else "packets/s",
timestamp=timestamp,
metric_type=MetricType.NETWORK_IO
)
self.analyzer.add_metric(metric)
self._log_metric(metric)
# Disk metrics
if self.config.enable_disk_monitoring:
disk_metrics = self.collector.collect_disk_metrics()
for name, value in disk_metrics.items():
metric = PerformanceMetric(
name=f"disk_{name}",
value=value,
unit="KB/s" if "rate" in name else "GB" if "used" in name or "free" in name or "total" in name else "%",
timestamp=timestamp,
metric_type=MetricType.DISK_IO
)
self.analyzer.add_metric(metric)
self._log_metric(metric)
# Process metrics
process_metrics = self.collector.collect_process_metrics()
for name, value in process_metrics.items():
metric = PerformanceMetric(
name=f"process_{name}",
value=value,
unit="%" if "percent" in name else "MB" if "memory" in name else "count",
timestamp=timestamp,
metric_type=MetricType.CUSTOM
)
self.analyzer.add_metric(metric)
self._log_metric(metric)
# System metrics
system_metrics = self.collector.collect_system_metrics()
for name, value in system_metrics.items():
metric = PerformanceMetric(
name=f"system_{name}",
value=value,
unit="count" if "count" in name else "seconds",
timestamp=timestamp,
metric_type=MetricType.CUSTOM
)
self.analyzer.add_metric(metric)
self._log_metric(metric)
def _log_metric(self, metric: PerformanceMetric):
"""Log a performance metric."""
if self.log_file:
log_entry = {
'timestamp': datetime.fromtimestamp(metric.timestamp).isoformat(),
'name': metric.name,
'value': metric.value,
'unit': metric.unit,
'type': metric.metric_type.value
}
self.log_file.write(json.dumps(log_entry) + '\n')
self.log_file.flush()
def _check_alerts(self):
"""Check for performance alerts."""
if not self.config.enable_alerts:
return
# Get current metrics
for metric_name in self.analyzer.metric_history:
if metric_name in self.config.alert_thresholds:
threshold = self.config.alert_thresholds[metric_name]
current_metrics = list(self.analyzer.metric_history[metric_name])
if current_metrics:
current_value = current_metrics[-1].value
if current_value > threshold:
alert = PerformanceAlert(
metric_name=metric_name,
alert_level=AlertLevel.WARNING if current_value < threshold * 1.5 else AlertLevel.ERROR,
message=f"{metric_name} exceeded threshold: {current_value:.2f} > {threshold:.2f}",
timestamp=time.time(),
threshold=threshold,
current_value=current_value
)
self.alerts.append(alert)
self._notify_alert_callbacks(alert)
def add_alert_callback(self, callback: Callable):
"""
Add an alert callback function.
Args:
callback (Callable): Alert callback function
"""
self.alert_callbacks.append(callback)
logger.debug("Added alert callback")
def _notify_alert_callbacks(self, alert: PerformanceAlert):
"""Notify alert callbacks."""
for callback in self.alert_callbacks:
try:
callback(alert)
except Exception as e:
logger.error(f"Error in alert callback: {e}")
def get_current_metrics(self) -> Dict[str, float]:
"""
Get current metric values.
Returns:
Dict[str, float]: Current metric values
"""
current_metrics = {}
for metric_name, history in self.analyzer.metric_history.items():
if history:
current_metrics[metric_name] = history[-1].value
return current_metrics
def get_metric_history(self, metric_name: str) -> List[PerformanceMetric]:
"""
Get metric history.
Args:
metric_name (str): Name of the metric
Returns:
List[PerformanceMetric]: Metric history
"""
return list(self.analyzer.metric_history.get(metric_name, []))
def get_performance_report(self) -> Dict[str, Any]:
"""
Get a comprehensive performance report.
Returns:
Dict[str, Any]: Performance report
"""
return self.analyzer.generate_report()
def get_alerts(self, level: AlertLevel = None) -> List[PerformanceAlert]:
"""
Get performance alerts.
Args:
level (AlertLevel): Filter by alert level (optional)
Returns:
List[PerformanceAlert]: List of alerts
"""
if level is None:
return self.alerts.copy()
else:
return [alert for alert in self.alerts if alert.alert_level == level]
def clear_alerts(self):
"""Clear all alerts."""
self.alerts.clear()
logger.info("Cleared all performance alerts")
def export_data(self, file_path: str = None) -> bool:
"""
Export performance data to file.
Args:
file_path (str): Output file path (optional)
Returns:
bool: True if exported successfully
"""
if file_path is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
file_path = f"performance_data_{timestamp}.json"
try:
export_data = {
'metadata': {
'export_time': datetime.now().isoformat(),
'monitor_start_time': self.start_time,
'total_metrics': len(self.analyzer.metric_history)
},
'metrics': {},
'alerts': [asdict(alert) for alert in self.alerts],
'report': self.get_performance_report()
}
# Export metric history
for metric_name, history in self.analyzer.metric_history.items():
export_data['metrics'][metric_name] = [
{
'timestamp': metric.timestamp,
'value': metric.value,
'unit': metric.unit,
'type': metric.metric_type.value
}
for metric in history
]
with open(file_path, 'w') as f:
json.dump(export_data, f, indent=2)
logger.info(f"Exported performance data to {file_path}")
return True
except Exception as e:
logger.error(f"Failed to export performance data: {e}")
return False
def plot_metrics(self, metric_names: List[str] = None, save_path: str = None):
"""
Plot performance metrics.
Args:
metric_names (List[str]): Metrics to plot (if None, plot all)
save_path (str): Path to save the plot (optional)
"""
if not metric_names:
metric_names = list(self.analyzer.metric_history.keys())
fig, axes = plt.subplots(len(metric_names), 1, figsize=(12, 3 * len(metric_names)))
if len(metric_names) == 1:
axes = [axes]
for i, metric_name in enumerate(metric_names):
if metric_name in self.analyzer.metric_history:
history = self.analyzer.metric_history[metric_name]
timestamps = [metric.timestamp for metric in history]
values = [metric.value for metric in history]
axes[i].plot(timestamps, values, label=metric_name)
axes[i].set_title(f"{metric_name} Over Time")
axes[i].set_xlabel("Time")
axes[i].set_ylabel("Value")
axes[i].grid(True)
axes[i].legend()
plt.tight_layout()
if save_path:
plt.savefig(save_path)
logger.info(f"Saved performance plot to {save_path}")
else:
plt.show()
# Example usage
if __name__ == "__main__":
"""
Example usage of the performance monitor.
This demonstrates how to set up and use the performance
monitor for tracking system performance.
"""
# Create performance monitor configuration
config = PerformanceConfig(
update_interval=2.0,
history_length=500,
enable_cpu_monitoring=True,
enable_memory_monitoring=True,
enable_network_monitoring=True,
enable_disk_monitoring=True,
alert_thresholds={
'cpu_cpu_percent': 80.0,
'memory_memory_percent': 85.0
},
enable_alerts=True,
enable_logging=True
)
# Create performance monitor
monitor = PerformanceMonitor(config)
# Add alert callback
def alert_callback(alert):
print(f"ALERT: {alert.message}")
monitor.add_alert_callback(alert_callback)
# Start monitoring
monitor.start_monitoring()
try:
# Simulate some work
for i in range(30):
# Simulate CPU-intensive work
if i % 5 == 0:
# Simulate high CPU usage
for _ in range(1000000):
_ = 1 + 1
# Print current metrics every 10 seconds
if i % 5 == 0:
current_metrics = monitor.get_current_metrics()
print(f"Current metrics: {current_metrics}")
time.sleep(2)
# Generate performance report
report = monitor.get_performance_report()
print(f"Performance report: {report['summary']}")
# Export data
monitor.export_data("performance_export.json")
# Plot metrics
monitor.plot_metrics(save_path="performance_plot.png")
except KeyboardInterrupt:
print("\nStopping performance monitor...")
finally:
# Stop monitoring
monitor.stop_monitoring()
print("Performance monitoring completed!")
相关文章
real_time_controller.cpp
real_time_controller.cpp — cpp source code from the CrazyFly learning materials (CrazyFly/cpp/high_freq_control/real_time_controller.cpp).
阅读文章 →four_layer_pid.m
four_layer_pid.m — objectivec source code from the CrazyFly learning materials (CrazyFly/matlab/analysis/four_layer_pid.m).
阅读文章 →hybrid_controller.m
hybrid_controller.m — objectivec source code from the CrazyFly learning materials (CrazyFly/matlab/analysis/hybrid_controller.m).
阅读文章 →l1_adaptive_model.m
l1_adaptive_model.m — objectivec source code from the CrazyFly learning materials (CrazyFly/matlab/analysis/l1_adaptive_model.m).
阅读文章 →parameter_optimizer.m
parameter_optimizer.m — objectivec source code from the CrazyFly learning materials (CrazyFly/matlab/analysis/parameter_optimizer.m).
阅读文章 →performance_analyzer.m
performance_analyzer.m — objectivec source code from the CrazyFly learning materials (CrazyFly/matlab/analysis/performance_analyzer.m).
阅读文章 →