lgui_core/memory/
stats.rs1use 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}