Per-cache bytes: decoded thumbnail/preview/full sources, rendered previews, GPU device buffers (allocated/pooled/retired), loupe stage caches (CPU and GPU) and textures. lightcraft-cli --features dhat-heap adds live/peak heap and writes dhat-heap.json. Baseline (14 raws, loupe, 12 steps): peak RSS 1.9-2.3 GB, footprint 2.5-2.6 GB; heap peak 634 MB after import (probes decode every raw), 930 MB during grid thumbnails (parallel decodes); GPU free pool grows to 2 GB (exact-size reuse). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
103 lines
3.4 KiB
Rust
103 lines
3.4 KiB
Rust
//! Memory accounting: what each cache holds (`library.memory`, and `ui.inspect` → `memory` with the
|
|
//! frontend's own caches added).
|
|
//!
|
|
//! The numbers are the caches' own bookkeeping (pixels held), not the process's resident size: the
|
|
//! allocator keeps freed pages for reuse and the GPU driver maps device buffers, so `ps`/`time -l`
|
|
//! report more. A binary built with a heap profiler installs [`set_heap_stats`] (e.g.
|
|
//! `lightcraft-cli` with `--features dhat-heap`) to add live/peak heap bytes.
|
|
|
|
use std::sync::OnceLock;
|
|
|
|
use serde::Serialize;
|
|
|
|
/// Entries and bytes held by one cache.
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize)]
|
|
pub struct Usage {
|
|
pub count: usize,
|
|
pub bytes: usize,
|
|
}
|
|
|
|
impl Usage {
|
|
pub fn new(count: usize, bytes: usize) -> Usage {
|
|
Usage { count, bytes }
|
|
}
|
|
}
|
|
|
|
/// Heap bytes as counted by an instrumented allocator.
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct HeapUsage {
|
|
/// Live heap bytes now.
|
|
pub current: u64,
|
|
/// Highest live heap bytes so far.
|
|
pub peak: u64,
|
|
}
|
|
|
|
/// Device buffers of the GPU renderer.
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct GpuUsage {
|
|
/// Every device buffer that exists.
|
|
pub allocated: u64,
|
|
/// Of which recycled buffers waiting in the free pool.
|
|
pub pooled: u64,
|
|
/// Of which buffers released since their thread's last submit.
|
|
pub retired: u64,
|
|
}
|
|
|
|
/// What the engine's caches hold.
|
|
#[derive(Clone, Debug, Default, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct MemoryReport {
|
|
/// Decoded thumbnail-level sources (≤ 512 px, linear float).
|
|
pub thumb_sources: Usage,
|
|
/// Decoded preview-level sources (≤ 2560 px, linear float) of the current and prefetched photos.
|
|
pub preview_sources: Usage,
|
|
/// The last full-resolution original (exports, 1:1).
|
|
pub full_source: Usage,
|
|
/// Rendered thumbnails and view renders (8-bit) in memory.
|
|
pub rendered: Usage,
|
|
/// Sum of the above.
|
|
pub engine_bytes: usize,
|
|
pub gpu: GpuUsage,
|
|
/// Live/peak heap when the binary counts allocations.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub heap: Option<HeapUsage>,
|
|
}
|
|
|
|
static HEAP: OnceLock<fn() -> HeapUsage> = OnceLock::new();
|
|
|
|
/// Install the heap counter of an instrumented binary (first call wins).
|
|
pub fn set_heap_stats(f: fn() -> HeapUsage) {
|
|
let _ = HEAP.set(f);
|
|
}
|
|
|
|
/// Live/peak heap bytes, when the binary installed a counter.
|
|
pub fn heap_stats() -> Option<HeapUsage> {
|
|
HEAP.get().map(|f| f())
|
|
}
|
|
|
|
/// The GPU renderer's device buffers.
|
|
pub fn gpu_usage() -> GpuUsage {
|
|
let g = lightcraft_gpu::memory();
|
|
GpuUsage { allocated: g.allocated, pooled: g.pooled, retired: g.retired }
|
|
}
|
|
|
|
impl crate::Session {
|
|
/// What the engine's caches hold now.
|
|
pub fn memory_report(&self) -> MemoryReport {
|
|
let (thumb_sources, preview_sources, full_source) = self.media.usage();
|
|
let (n, b) = self.media.rendered.mem_usage();
|
|
let rendered = Usage::new(n, b);
|
|
MemoryReport {
|
|
thumb_sources,
|
|
preview_sources,
|
|
full_source,
|
|
rendered,
|
|
engine_bytes: thumb_sources.bytes + preview_sources.bytes + full_source.bytes + rendered.bytes,
|
|
gpu: gpu_usage(),
|
|
heap: heap_stats(),
|
|
}
|
|
}
|
|
}
|