diff --git a/crates/re_query/src/archetype_view.rs b/crates/re_query/src/archetype_view.rs index aff4178e0b1e..389f8f31334e 100644 --- a/crates/re_query/src/archetype_view.rs +++ b/crates/re_query/src/archetype_view.rs @@ -68,13 +68,13 @@ impl ComponentWithInstances { } let arr = self .lookup_arrow(instance_key) - .map_or_else(|| Err(QueryError::ComponentNotFound(C::name())), Ok)?; + .map_or_else(|| Err(crate::ComponentNotFoundError(C::name())), Ok)?; let mut iter = C::from_arrow(arr.as_ref())?.into_iter(); let val = iter .next() - .map_or_else(|| Err(QueryError::ComponentNotFound(C::name())), Ok)?; + .map_or_else(|| Err(crate::ComponentNotFoundError(C::name())), Ok)?; Ok(val) } diff --git a/crates/re_query/src/lib.rs b/crates/re_query/src/lib.rs index ec081335b63f..ccd1c0f6d2eb 100644 --- a/crates/re_query/src/lib.rs +++ b/crates/re_query/src/lib.rs @@ -23,6 +23,17 @@ pub use self::util::query_archetype_with_history; #[cfg(feature = "testing")] pub use self::query::__populate_example_store; +#[derive(Debug, Clone, Copy)] +pub struct ComponentNotFoundError(pub re_types_core::ComponentName); + +impl std::fmt::Display for ComponentNotFoundError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("Could not find component: {}", self.0)) + } +} + +impl std::error::Error for ComponentNotFoundError {} + #[derive(thiserror::Error, Debug)] pub enum QueryError { #[error("Tried to access a column that doesn't exist")] @@ -31,11 +42,8 @@ pub enum QueryError { #[error("Could not find primary component: {0}")] PrimaryNotFound(re_types_core::ComponentName), - #[error("Could not find required component: {0}")] - RequiredComponentNotFound(re_types_core::ComponentName), - - #[error("Could not find component: {0}")] - ComponentNotFound(re_types_core::ComponentName), + #[error(transparent)] + ComponentNotFound(#[from] ComponentNotFoundError), #[error("Tried to access component of type '{actual:?}' using component '{requested:?}'")] TypeMismatch { diff --git a/crates/re_query_cache/benches/latest_at.rs b/crates/re_query_cache/benches/latest_at.rs index 7cc4439428bb..7eccfae8f821 100644 --- a/crates/re_query_cache/benches/latest_at.rs +++ b/crates/re_query_cache/benches/latest_at.rs @@ -54,7 +54,7 @@ criterion_main!(benches); fn mono_points(c: &mut Criterion) { // Each mono point gets logged at a different path let paths = (0..NUM_POINTS) - .map(move |point_idx| entity_path!("points", point_idx.to_string())) + .map(move |point_idx| entity_path!("points", point_idx)) .collect_vec(); let msgs = build_points_rows(&paths, 1); @@ -83,7 +83,7 @@ fn mono_points(c: &mut Criterion) { fn mono_strings(c: &mut Criterion) { // Each mono string gets logged at a different path let paths = (0..NUM_STRINGS) - .map(move |string_idx| entity_path!("strings", string_idx.to_string())) + .map(move |string_idx| entity_path!("strings", string_idx)) .collect_vec(); let msgs = build_strings_rows(&paths, 1); diff --git a/crates/re_query_cache/src/cache.rs b/crates/re_query_cache/src/cache.rs index 1ad320ad0407..6d09b51ce1c4 100644 --- a/crates/re_query_cache/src/cache.rs +++ b/crates/re_query_cache/src/cache.rs @@ -4,7 +4,6 @@ use std::{ }; use ahash::HashMap; -use itertools::Either; use once_cell::sync::Lazy; use parking_lot::RwLock; use paste::paste; @@ -175,36 +174,24 @@ impl CacheBucket { #[inline] pub fn iter_component( &self, - ) -> re_query::Result> { + ) -> Option> { let data = self .components .get(&C::name()) - .map(|data| data.as_any().downcast_ref::>()) - .ok_or_else(|| re_query::QueryError::RequiredComponentNotFound(C::name()))?; - - let Some(data) = data else { - return Ok(Either::Left(std::iter::empty())); - }; - - Ok(Either::Right(data.iter())) + .and_then(|data| data.as_any().downcast_ref::>())?; + Some(data.iter()) } /// Iterate over the batches of the specified optional component. #[inline] pub fn iter_component_opt( &self, - ) -> re_query::Result]>> { + ) -> Option]>> { let data = self .components .get(&C::name()) - .map(|data| data.as_any().downcast_ref::>>()) - .ok_or_else(|| re_query::QueryError::ComponentNotFound(C::name()))?; - - let Some(data) = data else { - return Ok(Either::Left(std::iter::empty())); - }; - - Ok(Either::Right(data.iter())) + .and_then(|data| data.as_any().downcast_ref::>>())?; + Some(data.iter()) } /// How many timestamps' worth of data is stored in this bucket? diff --git a/crates/re_query_cache/src/query.rs b/crates/re_query_cache/src/query.rs index a0ce621aa705..819ceae6157a 100644 --- a/crates/re_query_cache/src/query.rs +++ b/crates/re_query_cache/src/query.rs @@ -23,7 +23,16 @@ pub enum MaybeCachedComponentData<'a, C> { Raw(Vec), } -impl<'a, C: Clone> MaybeCachedComponentData<'a, C> { +impl<'a, C> std::ops::Deref for MaybeCachedComponentData<'a, C> { + type Target = [C]; + + #[inline] + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +impl<'a, C> MaybeCachedComponentData<'a, C> { #[inline] pub fn iter(&self) -> impl ExactSizeIterator + '_ { self.as_slice().iter() @@ -102,12 +111,13 @@ macro_rules! impl_query_archetype { // NOTE: Implicitly dropping the write guard here: the LatestAtCache is free once again! if bucket.is_empty() { + re_tracing::profile_scope!("fill"); + let now = web_time::Instant::now(); let arch_view = query_archetype::(store, &query, entity_path)?; bucket.[]::(query.at, &arch_view)?; - // TODO(cmc): I'd love a way of putting this information into the `puffin` span directly. let elapsed = now.elapsed(); ::re_log::trace!( store_id=%store.id(), @@ -118,11 +128,15 @@ macro_rules! impl_query_archetype { ); } + re_tracing::profile_scope!("iter"); + let it = itertools::izip!( bucket.iter_pov_times(), bucket.iter_pov_instance_keys(), - $(bucket.iter_component::<$pov>()?,)+ - $(bucket.iter_component_opt::<$comp>()?,)* + $(bucket.iter_component::<$pov>() + .ok_or_else(|| re_query::ComponentNotFoundError(<$pov>::name()))?,)+ + $(bucket.iter_component_opt::<$comp>() + .ok_or_else(|| re_query::ComponentNotFoundError(<$comp>::name()))?,)* ).map(|(time, instance_keys, $($pov,)+ $($comp,)*)| { ( *time,