use mecha10::prelude::*;
use serde::{Deserialize, Serialize};
use std::time::Duration;
use tokio::time::sleep;
#[derive(Debug, Clone, Serialize, Deserialize)]
struct SensorData {
timestamp: u64,
value: f64,
}
impl Message for SensorData {}
async fn basic_latency_example() -> Result<()> {
info!("Example 1: Basic latency measurement");
let metrics = PerformanceMetrics::new();
for i in 0..100 {
let publish_time = now_micros();
sleep(Duration::from_millis(1)).await;
let latency = measure_latency(publish_time);
metrics.record_latency("/sensor/data", latency).await;
if i % 20 == 0 {
info!("Published message {} with {}µs latency", i, latency);
}
}
let stats = metrics.get_latency_stats("/sensor/data").await.unwrap();
info!("\nLatency Statistics for /sensor/data:");
info!(" Count: {}", stats.count);
info!(" Min: {}µs ({:.2}ms)", stats.min_us, stats.min_us as f64 / 1000.0);
info!(" Max: {}µs ({:.2}ms)", stats.max_us, stats.max_us as f64 / 1000.0);
info!(" Mean: {:.0}µs ({:.2}ms)", stats.mean_us, stats.mean_us / 1000.0);
info!(" P50: {}µs ({:.2}ms)", stats.p50_us, stats.p50_us as f64 / 1000.0);
info!(" P95: {}µs ({:.2}ms)", stats.p95_us, stats.p95_us as f64 / 1000.0);
info!(" P99: {}µs ({:.2}ms)", stats.p99_us, stats.p99_us as f64 / 1000.0);
Ok(())
}
async fn throughput_measurement_example() -> Result<()> {
info!("Example 2: Throughput measurement");
let metrics = PerformanceMetrics::new();
info!("Publishing 1000 messages...");
for _ in 0..1000 {
let message_size = 1024;
metrics.record_message("/camera/rgb", message_size).await;
sleep(Duration::from_micros(100)).await;
}
let stats = metrics.get_throughput_stats("/camera/rgb").await.unwrap();
info!("\nThroughput Statistics for /camera/rgb:");
info!(" Messages: {}", stats.message_count);
info!(" Total data: {:.2} MB", stats.byte_count as f64 / 1_000_000.0);
info!(" Duration: {:.2}s", stats.duration_sec);
info!(" Messages/sec: {:.2}", stats.messages_per_sec);
info!(" Throughput: {:.2} MB/s", stats.megabytes_per_sec);
info!(" Bandwidth: {:.2} Mbps", stats.megabytes_per_sec * 8.0);
Ok(())
}
async fn execution_timing_example() -> Result<()> {
info!("Example 3: Execution time measurement");
let metrics = PerformanceMetrics::new();
for _ in 0..100 {
let _timer = metrics.start_timer("fast_function").await;
sleep(Duration::from_micros(100)).await;
}
for _ in 0..10 {
let _timer = metrics.start_timer("slow_function").await;
sleep(Duration::from_millis(10)).await;
}
sleep(Duration::from_millis(100)).await;
let fast_stats = metrics.get_execution_stats("fast_function").await.unwrap();
info!("\nExecution Stats for fast_function:");
info!(" Executions: {}", fast_stats.count);
info!(" Mean: {:.0}µs", fast_stats.mean_us);
info!(" P95: {}µs", fast_stats.p95_us);
let slow_stats = metrics.get_execution_stats("slow_function").await.unwrap();
info!("\nExecution Stats for slow_function:");
info!(" Executions: {}", slow_stats.count);
info!(" Mean: {:.2}ms", slow_stats.mean_us / 1000.0);
info!(" P95: {:.2}ms", slow_stats.p95_us as f64 / 1000.0);
Ok(())
}
async fn memory_tracking_example() -> Result<()> {
info!("Example 4: Memory usage tracking");
let metrics = PerformanceMetrics::new();
metrics.record_memory(1_000_000, 0).await;
metrics.record_memory(5_000_000, 0).await;
metrics.record_memory(2_000_000, 0).await;
let stats = metrics.get_memory_stats().await;
info!("\nMemory Stats after allocations:");
info!(" Current usage: {:.2} MB", stats.current_usage_mb);
info!(" Peak usage: {:.2} MB", stats.peak_usage_mb);
metrics.record_memory(0, 3_000_000).await;
let stats = metrics.get_memory_stats().await;
info!("\nMemory Stats after freeing:");
info!(" Current usage: {:.2} MB", stats.current_usage_mb);
info!(" Peak usage: {:.2} MB", stats.peak_usage_mb);
info!(
" Total allocated: {:.2} MB",
stats.total_allocated_bytes as f64 / 1_000_000.0
);
info!(" Total freed: {:.2} MB", stats.total_freed_bytes as f64 / 1_000_000.0);
Ok(())
}
async fn multi_topic_monitoring() -> Result<()> {
info!("Example 5: Multiple topics monitoring");
let metrics = PerformanceMetrics::new();
for _ in 0..100 {
metrics.record_latency("/sensor/camera", 5000).await;
metrics.record_message("/sensor/camera", 921600).await;
metrics.record_latency("/sensor/lidar", 50000).await;
metrics.record_message("/sensor/lidar", 256000).await;
metrics.record_latency("/control/cmd_vel", 1000).await;
metrics.record_message("/control/cmd_vel", 24).await;
sleep(Duration::from_millis(10)).await;
}
info!("\nComparative Topic Performance:");
info!("────────────────────────────────────────────────────");
for topic in &["/sensor/camera", "/sensor/lidar", "/control/cmd_vel"] {
if let Some(lat_stats) = metrics.get_latency_stats(topic).await {
if let Some(tp_stats) = metrics.get_throughput_stats(topic).await {
info!("\n{}", topic);
info!(
" Latency: {:.2}ms (p95: {:.2}ms)",
lat_stats.mean_us / 1000.0,
lat_stats.p95_us as f64 / 1000.0
);
info!(
" Throughput: {:.2} msg/s, {:.2} MB/s",
tp_stats.messages_per_sec, tp_stats.megabytes_per_sec
);
}
}
}
Ok(())
}
async fn performance_report_example() -> Result<()> {
info!("Example 6: Complete performance report");
let metrics = PerformanceMetrics::new();
for i in 0..50 {
let _timer = metrics.start_timer("process_frame").await;
metrics.record_latency("/camera/image", 2000 + (i % 5) * 100).await;
metrics.record_message("/camera/image", 640 * 480 * 3).await;
sleep(Duration::from_millis(10)).await;
}
sleep(Duration::from_millis(100)).await;
let report = metrics.get_report().await;
info!("\n╔════════════════════════════════════════╗");
info!("║ Performance Report ║");
info!("╚════════════════════════════════════════╝");
info!("\n📊 Latency Metrics:");
for stats in &report.latency {
info!(" {}", stats.topic);
info!(
" Count: {}, Mean: {:.2}ms, P95: {:.2}ms",
stats.count,
stats.mean_us / 1000.0,
stats.p95_us as f64 / 1000.0
);
}
info!("\n📈 Throughput Metrics:");
for stats in &report.throughput {
info!(" {}", stats.topic);
info!(
" {} msg/s, {:.2} MB/s",
stats.messages_per_sec as u64, stats.megabytes_per_sec
);
}
info!("\n⏱️ Execution Metrics:");
for stats in &report.execution {
info!(" {}", stats.name);
info!(
" Calls: {}, Mean: {:.2}ms, P99: {:.2}ms",
stats.count,
stats.mean_us / 1000.0,
stats.p99_us as f64 / 1000.0
);
}
info!("\n💾 Memory Metrics:");
info!(" Current: {:.2} MB", report.memory.current_usage_mb);
info!(" Peak: {:.2} MB", report.memory.peak_usage_mb);
Ok(())
}
async fn realtime_monitoring_example() -> Result<()> {
info!("Example 7: Real-time monitoring (5 seconds)");
let metrics = PerformanceMetrics::new();
let metrics_clone = metrics.clone();
tokio::spawn(async move {
for _ in 0..500 {
metrics_clone.record_latency("/sensor/imu", 500).await;
metrics_clone.record_message("/sensor/imu", 64).await;
sleep(Duration::from_millis(10)).await;
}
});
for i in 1..=5 {
sleep(Duration::from_secs(1)).await;
if let Some(stats) = metrics.get_throughput_stats("/sensor/imu").await {
info!(
"[{}s] IMU: {:.0} msg/s, {:.2} KB/s",
i,
stats.messages_per_sec,
stats.bytes_per_sec / 1000.0
);
}
}
Ok(())
}
async fn bottleneck_profiling_example() -> Result<()> {
info!("Example 8: Profiling bottlenecks");
let metrics = PerformanceMetrics::new();
for _ in 0..20 {
{
let _timer = metrics.start_timer("acquire_image").await;
sleep(Duration::from_millis(5)).await;
}
{
let _timer = metrics.start_timer("preprocess").await;
sleep(Duration::from_millis(10)).await;
}
{
let _timer = metrics.start_timer("inference").await;
sleep(Duration::from_millis(50)).await;
}
{
let _timer = metrics.start_timer("postprocess").await;
sleep(Duration::from_millis(5)).await;
}
}
sleep(Duration::from_millis(200)).await;
info!("\nPipeline Profiling (20 iterations):");
info!("────────────────────────────────────────");
let mut total_time = 0.0;
let pipeline_steps = vec!["acquire_image", "preprocess", "inference", "postprocess"];
for step in &pipeline_steps {
if let Some(stats) = metrics.get_execution_stats(step).await {
let mean_ms = stats.mean_us / 1000.0;
total_time += mean_ms;
info!("{:15} {:.2}ms", step, mean_ms);
}
}
info!("────────────────────────────────────────");
info!("{:15} {:.2}ms", "Total", total_time);
info!(
"\n🔴 Bottleneck: 'inference' takes {:.0}% of total time",
(50.0 / total_time) * 100.0
);
Ok(())
}
fn main() -> Result<()> {
tracing_subscriber::fmt().with_max_level(tracing::Level::INFO).init();
println!("Performance Profiling Usage Examples");
println!("====================================\n");
let runtime = tokio::runtime::Runtime::new().unwrap();
runtime.block_on(async {
basic_latency_example().await?;
println!();
throughput_measurement_example().await?;
println!();
execution_timing_example().await?;
println!();
memory_tracking_example().await?;
println!();
multi_topic_monitoring().await?;
println!();
performance_report_example().await?;
println!();
realtime_monitoring_example().await?;
println!();
bottleneck_profiling_example().await?;
println!();
Ok::<(), Mecha10Error>(())
})?;
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("All profiling examples completed!");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
println!("Key Takeaways:");
println!(" ✓ Track latency with percentile statistics");
println!(" ✓ Measure throughput (messages/sec, MB/sec)");
println!(" ✓ Time function execution automatically");
println!(" ✓ Monitor memory allocations");
println!(" ✓ Identify performance bottlenecks");
println!(" ✓ Generate comprehensive reports");
println!();
println!("Use cases:");
println!(" • Optimize message processing pipelines");
println!(" • Debug latency issues in distributed systems");
println!(" • Monitor system health in production");
println!(" • Capacity planning and scaling decisions");
Ok(())
}