## Coverage Report

#### Created: 2026-01-25 15:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/noah/src/trueno/src/brick/profiler/tile_stats.rs

    Line
    Count
    Source
    1
    //! Tile-level profiling statistics.
    2
    3
    use std::time::Instant;
    4
    5
    /// Tile-level profiling statistics.
    6
    ///
    7
    /// Tracks per-tile performance metrics for hierarchical cache-blocked operations.
    8
    /// Used in conjunction with `TcbGeometry` and `TilingConfig` from the tiling module.
    9
    ///
    10
    /// # Example
    11
    ///
    12
    /// ```ignore
    13
    /// let mut profiler = BrickProfiler::new();
    14
    /// profiler.enable();
    15
    ///
    16
    /// let tile_timer = profiler.start_tile(TileLevel::Macro, 0, 0);
    17
    /// // ... execute tile ...
    18
    /// profiler.stop_tile(tile_timer, 1024 * 1024);
    19
    /// ```
    20
    #[derive(Debug, Clone, Default)]
    21
    pub struct TileStats {
    22
        /// Tile level (Macro/Midi/Micro)
    23
        pub level: TileLevel,
    24
        /// Total samples collected
    25
        pub count: u64,
    26
        /// Total elapsed time (nanoseconds)
    27
        pub total_ns: u64,
    28
        /// Min elapsed time (nanoseconds)
    29
        pub min_ns: u64,
    30
        /// Max elapsed time (nanoseconds)
    31
        pub max_ns: u64,
    32
        /// Total elements processed
    33
        pub total_elements: u64,
    34
        /// Total cache misses (estimated)
    35
        pub cache_misses: u64,
    36
        /// Total arithmetic operations
    37
        pub total_flops: u64,
    38
    }
    39
    40
    /// Tile hierarchy level for profiling.
    41
    #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
    42
    pub enum TileLevel {
    43
        /// Macro-tile: L3 cache / GPU global memory
    44
        #[default]
    45
        Macro,
    46
        /// Midi-tile: L2 cache / GPU shared memory
    47
        Midi,
    48
        /// Micro-tile: Registers / SIMD lanes
    49
        Micro,
    50
    }
    51
    52
    impl TileLevel {
    53
        /// Get the name of this tile level.
    54
        #[must_use]
    55
    0
        pub const fn name(&self) -> &'static str {
    56
    0
            match self {
    57
    0
                TileLevel::Macro => "macro",
    58
    0
                TileLevel::Midi => "midi",
    59
    0
                TileLevel::Micro => "micro",
    60
            }
    61
    0
        }
    62
    }
    63
    64
    impl TileStats {
    65
        /// Create new tile stats for a given level.
    66
    0
        pub fn new(level: TileLevel) -> Self {
    67
    0
            Self {
    68
    0
                level,
    69
    0
                count: 0,
    70
    0
                total_ns: 0,
    71
    0
                min_ns: u64::MAX,
    72
    0
                max_ns: 0,
    73
    0
                total_elements: 0,
    74
    0
                cache_misses: 0,
    75
    0
                total_flops: 0,
    76
    0
            }
    77
    0
        }
    78
    79
        /// Add a sample to statistics.
    80
    0
        pub fn add_sample(&mut self, elapsed_ns: u64, elements: u64, flops: u64) {
    81
    0
            self.count += 1;
    82
    0
            self.total_ns += elapsed_ns;
    83
    0
            self.min_ns = self.min_ns.min(elapsed_ns);
    84
    0
            self.max_ns = self.max_ns.max(elapsed_ns);
    85
    0
            self.total_elements += elements;
    86
    0
            self.total_flops += flops;
    87
    0
        }
    88
    89
        /// Average time in microseconds.
    90
        #[must_use]
    91
    0
        pub fn avg_us(&self) -> f64 {
    92
    0
            if self.count == 0 {
    93
    0
                0.0
    94
            } else {
    95
    0
                self.total_ns as f64 / self.count as f64 / 1000.0
    96
            }
    97
    0
        }
    98
    99
        /// Throughput in elements/second.
    100
        #[must_use]
    101
    0
        pub fn throughput(&self) -> f64 {
    102
    0
            if self.total_ns == 0 {
    103
    0
                0.0
    104
            } else {
    105
    0
                self.total_elements as f64 / (self.total_ns as f64 / 1_000_000_000.0)
    106
            }
    107
    0
        }
    108
    109
        /// Compute throughput in GFLOP/s.
    110
        #[must_use]
    111
    0
        pub fn gflops(&self) -> f64 {
    112
    0
            if self.total_ns == 0 {
    113
    0
                0.0
    114
            } else {
    115
    0
                self.total_flops as f64 / (self.total_ns as f64 / 1_000_000_000.0) / 1e9
    116
            }
    117
    0
        }
    118
    119
        /// Arithmetic intensity (FLOP/byte) estimate.
    120
        ///
    121
        /// Assumes 4 bytes per element (f32).
    122
        #[must_use]
    123
    0
        pub fn arithmetic_intensity(&self) -> f64 {
    124
    0
            if self.total_elements == 0 {
    125
    0
                0.0
    126
            } else {
    127
    0
                self.total_flops as f64 / (self.total_elements as f64 * 4.0)
    128
            }
    129
    0
        }
    130
    131
        /// Estimated cache efficiency (0.0-1.0).
    132
        ///
    133
        /// Based on ratio of actual throughput vs theoretical peak.
    134
        #[must_use]
    135
    0
        pub fn cache_efficiency(&self, peak_gflops: f64) -> f64 {
    136
    0
            if peak_gflops <= 0.0 {
    137
    0
                0.0
    138
            } else {
    139
    0
                (self.gflops() / peak_gflops).min(1.0)
    140
            }
    141
    0
        }
    142
    }
    143
    144
    /// Timer handle for tile-level profiling.
    145
    #[derive(Debug)]
    146
    pub struct TileTimer {
    147
        /// Tile level
    148
        pub(crate) level: TileLevel,
    149
        /// Row index within parent tile (reserved for spatial analysis)
    150
        pub(crate) _row: u32,
    151
        /// Column index within parent tile (reserved for spatial analysis)
    152
        pub(crate) _col: u32,
    153
        /// Start time
    154
        pub(crate) start: Instant,
    155
    }