Skip to main content

lgui_core/memory/
stats.rs

1use super::{CacheDomain, DomainInstanceId, MemoryOptions, TrimReason};
2use std::sync::{Arc, Mutex};
3
4#[cfg_attr(feature = "diagnostics-serde", derive(serde::Serialize))]
5#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
6pub struct CacheUsage {
7    pub live_bytes: usize,
8    pub rebuildable_bytes: usize,
9    pub cache_bytes: usize,
10    pub cpu_bytes: usize,
11    pub gpu_estimated_bytes: usize,
12    pub pinned_bytes: usize,
13    pub entries: usize,
14    pub hits: u64,
15    pub misses: u64,
16    pub evictions: u64,
17    pub rebuilds: u64,
18    pub largest_entry_bytes: usize,
19    pub in_flight: usize,
20}
21
22impl CacheUsage {
23    pub const fn resident_bytes(self) -> usize {
24        self.live_bytes
25            .saturating_add(self.rebuildable_bytes)
26            .saturating_add(self.cache_bytes)
27    }
28
29    pub const fn managed_bytes(self) -> usize {
30        self.rebuildable_bytes.saturating_add(self.cache_bytes)
31    }
32
33    #[doc(hidden)]
34    pub fn add_assign(&mut self, other: Self) {
35        self.live_bytes = self.live_bytes.saturating_add(other.live_bytes);
36        self.rebuildable_bytes = self
37            .rebuildable_bytes
38            .saturating_add(other.rebuildable_bytes);
39        self.cache_bytes = self.cache_bytes.saturating_add(other.cache_bytes);
40        self.cpu_bytes = self.cpu_bytes.saturating_add(other.cpu_bytes);
41        self.gpu_estimated_bytes = self
42            .gpu_estimated_bytes
43            .saturating_add(other.gpu_estimated_bytes);
44        self.pinned_bytes = self.pinned_bytes.saturating_add(other.pinned_bytes);
45        self.entries = self.entries.saturating_add(other.entries);
46        self.hits = self.hits.saturating_add(other.hits);
47        self.misses = self.misses.saturating_add(other.misses);
48        self.evictions = self.evictions.saturating_add(other.evictions);
49        self.rebuilds = self.rebuilds.saturating_add(other.rebuilds);
50        self.largest_entry_bytes = self.largest_entry_bytes.max(other.largest_entry_bytes);
51        self.in_flight = self.in_flight.saturating_add(other.in_flight);
52    }
53}
54
55#[cfg_attr(feature = "diagnostics-serde", derive(serde::Serialize))]
56#[derive(Clone, Debug, PartialEq, Eq)]
57pub struct DomainSnapshot {
58    pub registration_id: u64,
59    pub domain: CacheDomain,
60    pub instance: DomainInstanceId,
61    pub owner: String,
62    pub usage: CacheUsage,
63}
64
65#[cfg_attr(feature = "diagnostics-serde", derive(serde::Serialize))]
66#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
67pub struct TrimSnapshot {
68    pub reason: TrimReason,
69    pub requested_at_epoch: u64,
70    pub released_bytes: usize,
71    pub duration_micros: u64,
72}
73
74#[cfg_attr(feature = "diagnostics-serde", derive(serde::Serialize))]
75#[derive(Clone, Debug, PartialEq, Eq)]
76pub struct MemorySnapshot {
77    pub epoch: u64,
78    pub options: MemoryOptions,
79    pub usage: CacheUsage,
80    pub transient_reserved_bytes: usize,
81    pub large_tasks_in_flight: usize,
82    pub pinned_overflow_bytes: usize,
83    pub domains: Vec<DomainSnapshot>,
84    pub last_trim: Option<TrimSnapshot>,
85}
86
87#[derive(Clone, Default)]
88#[doc(hidden)]
89pub struct CacheTelemetry {
90    usage: Arc<Mutex<CacheUsage>>,
91}
92
93impl CacheTelemetry {
94    pub fn publish(&self, usage: CacheUsage) {
95        *self.usage.lock().expect("cache telemetry poisoned") = usage;
96    }
97
98    pub fn snapshot(&self) -> CacheUsage {
99        *self.usage.lock().expect("cache telemetry poisoned")
100    }
101}