Skip to content

Commit

Permalink
out-of-band stats settings
Browse files Browse the repository at this point in the history
  • Loading branch information
teh-cmc committed Jan 15, 2024
1 parent a79d00d commit 53e051a
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 50 deletions.
42 changes: 9 additions & 33 deletions crates/re_query_cache/src/cache_stats.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::BTreeMap, sync::atomic::AtomicBool};
use std::collections::BTreeMap;

use re_log_types::{EntityPath, TimeRange, Timeline};
use re_types_core::ComponentName;
Expand All @@ -7,34 +7,6 @@ use crate::{Caches, LatestAtCache, RangeCache};

// ---

/// If `true`, enables the much-more-costly-to-compute per-component stats.
static ENABLE_DETAILED_STATS: AtomicBool = AtomicBool::new(false);

#[inline]
pub fn detailed_stats() -> bool {
ENABLE_DETAILED_STATS.load(std::sync::atomic::Ordering::Relaxed)
}

#[inline]
pub fn set_detailed_stats(b: bool) {
ENABLE_DETAILED_STATS.store(b, std::sync::atomic::Ordering::Relaxed);
}

/// If `true`, will show stats about empty caches too, which likely indicates a bug (dangling bucket).
static SHOW_EMPTY_CACHES: AtomicBool = AtomicBool::new(false);

#[inline]
pub fn show_empty_caches() -> bool {
SHOW_EMPTY_CACHES.load(std::sync::atomic::Ordering::Relaxed)
}

#[inline]
pub fn set_show_empty_caches(b: bool) {
SHOW_EMPTY_CACHES.store(b, std::sync::atomic::Ordering::Relaxed);
}

// ---

/// Stats for all primary caches.
///
/// Fetch them via [`Caches::stats`].
Expand Down Expand Up @@ -72,7 +44,7 @@ pub struct CachedEntityStats {
pub total_rows: u64,
pub total_size_bytes: u64,

/// Only if [`detailed_stats`] returns `true` (see [`set_detailed_stats`]).
/// Only if `detailed_stats` is `true` (see [`Caches::stats`]).
pub per_component: Option<BTreeMap<ComponentName, CachedComponentStats>>,
}

Expand All @@ -96,7 +68,7 @@ impl Caches {
/// Computes the stats for all primary caches.
///
/// `per_component` toggles per-component stats.
pub fn stats() -> CachesStats {
pub fn stats(detailed_stats: bool) -> CachesStats {
re_tracing::profile_function!();

Self::with(|caches| {
Expand All @@ -108,7 +80,7 @@ impl Caches {
(key.entity_path.clone(), {
let mut total_size_bytes = 0u64;
let mut total_rows = 0u64;
let mut per_component = detailed_stats().then(BTreeMap::default);
let mut per_component = detailed_stats.then(BTreeMap::default);

for latest_at_cache in
caches_per_arch.latest_at_per_archetype.read().values()
Expand All @@ -124,6 +96,8 @@ impl Caches {
total_rows = per_data_time.len() as u64 + timeless.is_some() as u64;

if let Some(per_component) = per_component.as_mut() {
re_tracing::profile_scope!("detailed");

for bucket in per_data_time.values() {
for (component_name, data) in &bucket.read().components {
let stats: &mut CachedComponentStats =
Expand Down Expand Up @@ -172,8 +146,10 @@ impl Caches {

let total_rows = bucket.data_times.len() as u64;

let mut per_component = detailed_stats().then(BTreeMap::default);
let mut per_component = detailed_stats.then(BTreeMap::default);
if let Some(per_component) = per_component.as_mut() {
re_tracing::profile_scope!("detailed");

for (component_name, data) in &bucket.components {
let stats: &mut CachedComponentStats =
per_component.entry(*component_name).or_default();
Expand Down
5 changes: 1 addition & 4 deletions crates/re_query_cache/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ mod query;
mod range;

pub use self::cache::{AnyQuery, Caches};
pub use self::cache_stats::{
detailed_stats, set_detailed_stats, set_show_empty_caches, show_empty_caches,
CachedComponentStats, CachedEntityStats, CachesStats,
};
pub use self::cache_stats::{CachedComponentStats, CachedEntityStats, CachesStats};
pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque};
pub use self::query::{
query_archetype_pov1, query_archetype_with_history_pov1, MaybeCachedComponentData,
Expand Down
3 changes: 2 additions & 1 deletion crates/re_viewer/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,8 @@ impl eframe::App for App {
};

let store_stats = store_hub.stats();
let caches_stats = re_query_cache::Caches::stats();
let caches_stats =
re_query_cache::Caches::stats(self.memory_panel.primary_cache_detailed_stats_enabled());

// do early, before doing too many allocations
self.memory_panel
Expand Down
44 changes: 32 additions & 12 deletions crates/re_viewer/src/ui/memory_panel.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::sync::atomic::AtomicBool;

use re_data_store::{DataStoreConfig, DataStoreRowStats, DataStoreStats};
use re_format::{format_bytes, format_number};
use re_memory::{util::sec_since_start, MemoryHistory, MemoryLimit, MemoryUse};
Expand All @@ -12,6 +14,13 @@ use crate::{env_vars::RERUN_TRACK_ALLOCATIONS, store_hub::StoreHubStats};
pub struct MemoryPanel {
history: MemoryHistory,
memory_purge_times: Vec<f64>,

/// If `true`, enables the much-more-costly-to-compute per-component stats for the primary
/// cache.
prim_cache_detailed_stats: AtomicBool,

/// If `true`, will show stats about empty primary caches too, which likely indicates a bug (dangling bucket).
prim_cache_show_empty: AtomicBool,
}

impl MemoryPanel {
Expand All @@ -35,10 +44,17 @@ impl MemoryPanel {
}

/// Note that we purged memory at this time, to show in stats.
#[inline]
pub fn note_memory_purge(&mut self) {
self.memory_purge_times.push(sec_since_start());
}

#[inline]
pub fn primary_cache_detailed_stats_enabled(&self) -> bool {
self.prim_cache_detailed_stats
.load(std::sync::atomic::Ordering::Relaxed)
}

#[allow(clippy::too_many_arguments)]
pub fn ui(
&self,
Expand All @@ -59,7 +75,7 @@ impl MemoryPanel {
.min_width(250.0)
.default_width(300.0)
.show_inside(ui, |ui| {
Self::left_side(
self.left_side(
ui,
re_ui,
limit,
Expand All @@ -76,6 +92,7 @@ impl MemoryPanel {
}

fn left_side(
&self,
ui: &mut egui::Ui,
re_ui: &re_ui::ReUi,
limit: &MemoryLimit,
Expand Down Expand Up @@ -106,7 +123,7 @@ impl MemoryPanel {

ui.separator();
ui.collapsing("Primary Cache Resources", |ui| {
Self::caches_stats(ui, re_ui, caches_stats);
self.caches_stats(ui, re_ui, caches_stats);
});

ui.separator();
Expand Down Expand Up @@ -309,24 +326,27 @@ impl MemoryPanel {
});
}

fn caches_stats(ui: &mut egui::Ui, re_ui: &re_ui::ReUi, caches_stats: &CachesStats) {
let mut detailed_stats = re_query_cache::detailed_stats();
fn caches_stats(&self, ui: &mut egui::Ui, re_ui: &re_ui::ReUi, caches_stats: &CachesStats) {
use std::sync::atomic::Ordering::Relaxed;

let mut detailed_stats = self.prim_cache_detailed_stats.load(Relaxed);
re_ui
.checkbox(ui, &mut detailed_stats, "Detailed stats")
.on_hover_text("Show detailed statistics when hovering entity paths below.\nThis will slow down the program.");
re_query_cache::set_detailed_stats(detailed_stats);
self.prim_cache_detailed_stats
.store(detailed_stats, Relaxed);

let mut show_empty_caches = re_query_cache::show_empty_caches();
let mut show_empty = self.prim_cache_show_empty.load(Relaxed);
re_ui
.checkbox(ui, &mut show_empty_caches, "Show empty caches")
.checkbox(ui, &mut show_empty, "Show empty caches")
.on_hover_text(
"Show empty caches too.\nDangling buckets are generally the result of a bug.",
);
re_query_cache::set_show_empty_caches(show_empty_caches);
self.prim_cache_show_empty.store(show_empty, Relaxed);

let CachesStats { latest_at, range } = caches_stats;

if show_empty_caches || !latest_at.is_empty() {
if show_empty || !latest_at.is_empty() {
ui.separator();
ui.strong("LatestAt");
egui::ScrollArea::vertical()
Expand All @@ -345,7 +365,7 @@ impl MemoryPanel {
ui.end_row();

for (entity_path, stats) in latest_at {
if !show_empty_caches && stats.is_empty() {
if !show_empty && stats.is_empty() {
continue;
}

Expand All @@ -357,7 +377,7 @@ impl MemoryPanel {
});
}

if show_empty_caches || !latest_at.is_empty() {
if show_empty || !latest_at.is_empty() {
ui.separator();
ui.strong("Range");
egui::ScrollArea::vertical()
Expand All @@ -378,7 +398,7 @@ impl MemoryPanel {

for (entity_path, stats_per_range) in range {
for (timeline, time_range, stats) in stats_per_range {
if !show_empty_caches && stats.is_empty() {
if !show_empty && stats.is_empty() {
continue;
}

Expand Down

0 comments on commit 53e051a

Please sign in to comment.