Skip to content

Commit

Permalink
New data APIs 12: port all spatial views (#5993)
Browse files Browse the repository at this point in the history
Migrate all spatial views that were using the old cache APIs to the new
ones.
Instance keys are not queried at all anymore.

All views are now range-aware by default.
Also took the opportunity to somewhat streamline everything.

The 10min air-traffic example with full visible range is about 2-2.5x
faster than before.

I'm sure I broke a few things here and there, I'll run a full check
suite once everything's said and done.

---

Part of a PR series to completely revamp the data APIs in preparation
for the removal of instance keys and the introduction of promises:
- #5573
- #5574
- #5581
- #5605
- #5606
- #5633
- #5673
- #5679
- #5687
- #5755
- #5990
- #5992
- #5993 
- #5994
- #6035
- #6036
- #6037

Builds on top of the static data PR series:
- #5534
  • Loading branch information
teh-cmc authored Apr 26, 2024
1 parent d0e9af0 commit 6d9e23c
Show file tree
Hide file tree
Showing 22 changed files with 1,851 additions and 1,835 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/re_entity_db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub(crate) use self::entity_tree::{ClearCascade, CompactedStoreEvents};
use re_log_types::DataTableError;
pub use re_log_types::{EntityPath, EntityPathPart, TimeInt, Timeline};

pub use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary};
pub use re_query2::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary};

#[cfg(feature = "serde")]
pub use blueprint::components::EntityPropertiesComponent;
Expand Down
6 changes: 3 additions & 3 deletions crates/re_query_cache2/src/latest_at/results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ pub struct CachedLatestAtComponentResults {
pub(crate) promise: Option<Promise>,

/// The resolved, converted, deserialized dense data.
pub(crate) cached_dense: OnceLock<Box<dyn ErasedFlatVecDeque + Send + Sync>>,
pub(crate) cached_dense: OnceLock<Arc<dyn ErasedFlatVecDeque + Send + Sync>>,
}

impl CachedLatestAtComponentResults {
Expand Down Expand Up @@ -274,9 +274,9 @@ impl CachedLatestAtComponentResults {
.map_err(|err| DeserializationError::DataCellError(err.to_string()))?;

#[allow(clippy::borrowed_box)]
let cached: &Box<dyn ErasedFlatVecDeque + Send + Sync> = self
let cached: &Arc<dyn ErasedFlatVecDeque + Send + Sync> = self
.cached_dense
.get_or_init(move || Box::new(FlatVecDeque::from(data)));
.get_or_init(move || Arc::new(FlatVecDeque::from(data)));

downcast(&**cached)
}
Expand Down
103 changes: 87 additions & 16 deletions crates/re_query_cache2/src/range/results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use re_data_store::RangeQuery;
use re_log_types::{RowId, TimeInt, TimeRange};
use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes};

use crate::{ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, PromiseResult};
use crate::{
CachedLatestAtComponentResults, ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver,
PromiseResult,
};

// ---

Expand Down Expand Up @@ -98,6 +101,14 @@ impl CachedRangeResults {

// ---

thread_local! {
/// Keeps track of reentrancy counts for the current thread.
///
/// Used to detect and prevent potential deadlocks when using the cached APIs in work-stealing
/// environments such as Rayon.
static REENTERING: RefCell<u32> = const { RefCell::new(0) };
}

/// Lazily cached results for a particular component when using a cached range query.
#[derive(Debug)]
pub struct CachedRangeComponentResults {
Expand Down Expand Up @@ -156,16 +167,57 @@ impl std::ops::Deref for CachedRangeComponentResults {
}
}

/// Helper datastructure to make it possible to convert latest-at results into ranged results.
#[derive(Debug)]
enum Indices<'a> {
Owned(VecDeque<(TimeInt, RowId)>),
Cached(MappedRwLockReadGuard<'a, VecDeque<(TimeInt, RowId)>>),
}

impl<'a> std::ops::Deref for Indices<'a> {
type Target = VecDeque<(TimeInt, RowId)>;

#[inline]
fn deref(&self) -> &Self::Target {
match self {
Indices::Owned(data) => data,
Indices::Cached(data) => data,
}
}
}

/// Helper datastructure to make it possible to convert latest-at results into ranged results.
enum Data<'a, T> {
Owned(Arc<dyn ErasedFlatVecDeque + Send + Sync>),
Cached(MappedRwLockReadGuard<'a, FlatVecDeque<T>>),
}

impl<'a, T: 'static> std::ops::Deref for Data<'a, T> {
type Target = FlatVecDeque<T>;

#[inline]
fn deref(&self) -> &Self::Target {
match self {
Data::Owned(data) => {
// Unwrap: only way to instantiate a `Data` is via the `From` impl below which we
// fully control.
data.as_any().downcast_ref().unwrap()
}
Data::Cached(data) => data,
}
}
}

pub struct CachedRangeData<'a, T> {
// NOTE: Options so we can represent an empty result without having to somehow conjure a mutex
// guard out of thin air.
//
// TODO(Amanieu/parking_lot#289): we need two distinct mapped guards because it's
// impossible to return an owned type in a `parking_lot` guard.
// See <https://github.com/Amanieu/parking_lot/issues/289#issuecomment-1827545967>.
indices: Option<MappedRwLockReadGuard<'a, VecDeque<(TimeInt, RowId)>>>,
data: Option<MappedRwLockReadGuard<'a, FlatVecDeque<T>>>,
// indices: Option<MappedRwLockReadGuard<'a, VecDeque<(TimeInt, RowId)>>>,
indices: Option<Indices<'a>>,
data: Option<Data<'a, T>>,

time_range: TimeRange,
front_status: PromiseResult<()>,
Expand All @@ -178,6 +230,32 @@ pub struct CachedRangeData<'a, T> {
reentering: &'static std::thread::LocalKey<RefCell<u32>>,
}

impl<'a, C: Component> CachedRangeData<'a, C> {
/// Useful to abstract over latest-at and ranged results.
#[inline]
pub fn from_latest_at(
resolver: &PromiseResolver,
results: &'a CachedLatestAtComponentResults,
) -> Self {
let CachedLatestAtComponentResults {
index,
promise: _,
cached_dense,
} = results;

let status = results.to_dense::<C>(resolver).map(|_| ());

Self {
indices: Some(Indices::Owned(vec![*index].into())),
data: cached_dense.get().map(|data| Data::Owned(Arc::clone(data))),
time_range: TimeRange::new(index.0, index.0),
front_status: status.clone(),
back_status: status,
reentering: &REENTERING,
}
}
}

impl<'a, T> Drop for CachedRangeData<'a, T> {
#[inline]
fn drop(&mut self) {
Expand All @@ -186,7 +264,7 @@ impl<'a, T> Drop for CachedRangeData<'a, T> {
}
}

impl<'a, T> CachedRangeData<'a, T> {
impl<'a, T: 'static> CachedRangeData<'a, T> {
/// Returns the current status on both ends of the range.
///
/// E.g. it is possible that the front-side of the range is still waiting for pending data while
Expand All @@ -201,10 +279,11 @@ impl<'a, T> CachedRangeData<'a, T> {
&self,
entry_range: Range<usize>,
) -> impl Iterator<Item = &(TimeInt, RowId)> {
match self.indices.as_ref() {
let indices = match self.indices.as_ref() {
Some(indices) => itertools::Either::Left(indices.range(entry_range)),
None => itertools::Either::Right(std::iter::empty()),
}
};
indices
}

#[inline]
Expand Down Expand Up @@ -278,14 +357,6 @@ impl CachedRangeComponentResults {

// --- Step 1: try and upsert pending data (write lock) ---

thread_local! {
/// Keeps track of reentrancy counts for the current thread.
///
/// Used to detect and prevent potential deadlocks when using the cached APIs in work-stealing
/// environments such as Rayon.
static REENTERING: RefCell<u32> = const { RefCell::new(0) };
}

REENTERING.with_borrow_mut(|reentering| *reentering = reentering.saturating_add(1));

// Manufactured empty result.
Expand Down Expand Up @@ -514,8 +585,8 @@ impl CachedRangeComponentResults {
});

CachedRangeData {
indices: Some(indices),
data: Some(data),
indices: Some(Indices::Cached(indices)),
data: Some(Data::Cached(data)),
time_range: self.time_range,
front_status,
back_status,
Expand Down
1 change: 1 addition & 0 deletions crates/re_space_view/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ re_log_types.workspace = true
re_data_store.workspace = true
re_entity_db.workspace = true
re_query.workspace = true
re_query2.workspace = true
re_tracing.workspace = true
re_types_core.workspace = true
re_types.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/re_space_view/src/visual_time_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//! to reduce the amount of changes in code that is likely to be refactored soon anyways.
use re_log_types::TimeRange;
use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary};
use re_query2::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary};
use re_types::blueprint::{
components::VisibleTimeRange,
datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind},
Expand Down
5 changes: 1 addition & 4 deletions crates/re_space_view_spatial/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ re_log_types.workspace = true
re_log.workspace = true
re_query.workspace = true
re_query_cache.workspace = true
re_query_cache2.workspace = true
re_renderer = { workspace = true, features = [
"import-gltf",
"import-obj",
Expand Down Expand Up @@ -61,7 +62,3 @@ mimalloc.workspace = true

[lib]
bench = false

[[bench]]
name = "bench_points"
harness = false
Loading

0 comments on commit 6d9e23c

Please sign in to comment.