mecha10-core 0.6.5

Mecha10 core runtime and foundational types
Documentation
//! Performance Profiling Usage Example
//!
//! This example demonstrates how to use the performance profiling helpers
//! to measure and optimize system performance.

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 {}

/// Example 1: Basic latency measurement
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(())
}

/// Example 2: Throughput measurement
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(())
}

/// Example 3: Execution time measurement with TimerGuard
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(())
}

/// Example 4: Memory usage tracking
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(())
}

/// Example 5: Multiple topics monitoring
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(())
}

/// Example 6: Complete performance report
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(())
}

/// Example 7: Real-time monitoring loop
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(())
}

/// Example 8: Profiling bottlenecks
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(())
}