Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drive blueprints off of a DataStore #2010

Merged
merged 107 commits into from
May 19, 2023
Merged
Show file tree
Hide file tree
Changes from 105 commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
b7971bf
Confirm no recording info is sent without logging
jleibs May 9, 2023
dd7a3f8
Update flush hierarchy test to match new behavior
jleibs May 9, 2023
10b6cde
Introduce RecordingType enum
jleibs Apr 27, 2023
3fb1f63
Add a global blueprint recording context
jleibs Apr 27, 2023
df0c7cc
Silly shim to send a component on a different recording
jleibs Apr 27, 2023
1eb5024
Detect incoming blueprints separately
jleibs Apr 27, 2023
8d0bbdf
Python API to init blueprint
jleibs Apr 27, 2023
468e0ca
Blueprint needs its own recording id
jleibs Apr 27, 2023
63775a8
Blueprint selection UI
jleibs Apr 27, 2023
633c923
New blueprint components
jleibs Apr 27, 2023
9d8abf5
New component for SpaceView
jleibs Apr 29, 2023
36d19ff
Implement PartialEq for spaceviews so we can determine if an update i…
jleibs Apr 29, 2023
f42b2e7
Make everything work with a blueprint we materialize at the beginning…
jleibs Apr 29, 2023
4bb548f
Add code to check/reconcile updates
jleibs Apr 29, 2023
2599c65
Cleanup some warnings
jleibs Apr 29, 2023
8bb6e80
Move sync to its own file and sync the panel state
jleibs Apr 29, 2023
9b9aba6
Also split out blueprint loading
jleibs Apr 29, 2023
06e1505
Save/Restore spaceview from store
jleibs Apr 29, 2023
68fe9fd
Prevent re-saving state on every frame
jleibs Apr 29, 2023
6874eeb
Add memory tracking to the blueprint store
jleibs Apr 29, 2023
d54fadf
Handle add/remove spaceviews
jleibs Apr 29, 2023
ba564c9
Store some viewport state as well
jleibs Apr 29, 2023
6fedb47
Clean up some logging
jleibs Apr 29, 2023
68dc65e
Functioning space views from python
jleibs Apr 30, 2023
5e7307b
Plumbing of blueprint + rrd for notebooks
jleibs Apr 30, 2023
97f089f
Make either recording or blueprint streams optional
jleibs May 3, 2023
38f5e4f
Work around lurking race conditions on disabling heuristics
jleibs May 3, 2023
b7f6345
Hacking around a special 'append' blueprint id
jleibs May 3, 2023
4618529
Handle streams being optional in memory recording
jleibs May 3, 2023
6a3b169
Add some sample apps to help exhibit blueprint behavior options
jleibs May 3, 2023
73abfa9
Manual API to enable heuristics
jleibs May 3, 2023
06be29a
Update blueprint examples
jleibs May 3, 2023
4a988b6
Add missing compute memory
jleibs May 5, 2023
2f1717e
Split out ViewportState
jleibs May 5, 2023
9407501
More tracking / filtering of state
jleibs May 8, 2023
feac631
Small cleanup
jleibs May 8, 2023
15257cd
Fix tracking of user-edited
jleibs May 8, 2023
c13a46a
Detect/track changes to dock structure
jleibs May 8, 2023
d6c779a
Simplify logic now that we have lazy recording-initialization
jleibs May 9, 2023
f09ce3c
Simple API to reset data/blueprint on the memory recording
jleibs May 9, 2023
22a0280
Fix panel logging timeline
jleibs May 9, 2023
2f4c1e0
Split up components and refactor the querying
jleibs May 10, 2023
77a5fb9
Don't commit the truck image
jleibs May 10, 2023
2c36827
Revert "Simplify logic now that we have lazy recording-initialization"
jleibs May 10, 2023
5ee8be2
Turn RecordingId into a string
jleibs May 10, 2023
f4b65c3
Use the default blueprint when receiving a recording
jleibs May 10, 2023
7077765
Allow deterministic ids for spaceviews
jleibs May 10, 2023
3ce99ad
Py formatting
jleibs May 10, 2023
1d04b65
Simplify python examples and fix more race conditions
jleibs May 11, 2023
96d0876
Align examples with current structure
jleibs May 11, 2023
48bfa80
Py-lint
jleibs May 11, 2023
6f17cbb
Rust lints
jleibs May 11, 2023
e7983cc
Taplo
jleibs May 11, 2023
ae3f9b3
Fix pan and zoom
jleibs May 11, 2023
5320ffb
Swap order of memory storage construction
jleibs May 11, 2023
2c13f38
More py-litns
jleibs May 11, 2023
76c20b5
Type annotations
jleibs May 11, 2023
1355907
Readability lint
jleibs May 11, 2023
9d9d483
more annotations
jleibs May 11, 2023
b9732f1
Make RecordingId a string
jleibs May 10, 2023
ead1c71
Remove gratuitous constant
jleibs May 11, 2023
5976c3a
Add a few more convenience traits
jleibs May 11, 2023
06031f0
Merge branch 'jleibs/recording_id_string' into jleibs/blueprint_mvp
jleibs May 11, 2023
4dc8d6e
Revert "Confirm no recording info is sent without logging"
jleibs May 11, 2023
d6fc7d0
Revert "Update flush hierarchy test to match new behavior"
jleibs May 11, 2023
6e61cc9
PR cleanup
jleibs May 11, 2023
7edc687
Merge branch 'main' into jleibs/blueprint_mvp
jleibs May 11, 2023
dd52e7f
Fix merge for using egui-tiles
jleibs May 11, 2023
ca083a5
Add missing requirements.txt
jleibs May 11, 2023
a36f7a3
Cleanup panels API
jleibs May 11, 2023
87844dd
Consolidate helpers in re_data_store::util
jleibs May 11, 2023
0c608d7
Cleanup timeless queries
jleibs May 11, 2023
0b88614
More entropy on the spaceviewid hash
jleibs May 11, 2023
992d7de
Cleanup space-view partitioning
jleibs May 11, 2023
52e03e7
Cleanup comment
jleibs May 11, 2023
92075fe
Cleanup PartialEq
jleibs May 11, 2023
19c0ae7
Links to https://github.com/rerun-io/rerun/issues/2089
jleibs May 11, 2023
bae874a
Rename blueprint process_updates
jleibs May 11, 2023
914a12e
Extract blueprint-loading as it's own helper
jleibs May 11, 2023
06b3a40
Add blueprint requirements to recursive requirements
jleibs May 11, 2023
bb0fa6d
Can't use Time::now() on web
jleibs May 11, 2023
6a87fd7
Merge branch 'main' into jleibs/blueprint_mvp
jleibs May 11, 2023
007189f
Ue time::now() again
jleibs May 11, 2023
7594345
Trees now support partialeq
jleibs May 11, 2023
0d3bfe7
EntityPath only needed for serde-gated features in entity_properties
jleibs May 11, 2023
58a8a47
Make re_viewer dep explicit
jleibs May 12, 2023
4608d46
Merge branch 'main' into jleibs/blueprint_mvp
jleibs May 15, 2023
746b85c
Fix memory recordings
jleibs May 16, 2023
9a3afaa
Store blueprint per-app
jleibs May 16, 2023
d242fdb
py-lint
jleibs May 16, 2023
2c0de29
Merge branch 'main' into jleibs/blueprint_mvp
jleibs May 16, 2023
803d2ba
Cleanup
jleibs May 16, 2023
60c5f82
Fix excessive blueprint-syncing
jleibs May 16, 2023
d01b6c0
doctests 🙄
jleibs May 16, 2023
46fa1dd
Another doctest and add _PATH suffixes
jleibs May 16, 2023
20e8715
Add a comment
jleibs May 16, 2023
6a03325
Add test for maximized, fix tests
jleibs May 16, 2023
63dedb3
Move blueprint APIs to experimental
jleibs May 16, 2023
78a5157
Add docstrings
jleibs May 16, 2023
d1efba7
Lint
jleibs May 16, 2023
7424638
Name selected_blueprint_by_app appropriately
jleibs May 16, 2023
6aa84cd
Fix accidental patch to build_build_ino
jleibs May 17, 2023
f441e18
Clean up some comments
jleibs May 17, 2023
9b3097c
Merge branch 'main' into jleibs/blueprint_mvp
jleibs May 17, 2023
3f629e8
Handle unknown app id
jleibs May 17, 2023
6764bb1
Merge branch 'main' into jleibs/blueprint_mvp
jleibs May 19, 2023
71829fb
Require all kwargs and rename space_path to origin
jleibs May 19, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.lock

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

42 changes: 3 additions & 39 deletions crates/re_data_store/src/entity_properties.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use re_arrow_store::LatestAtQuery;
use re_log_types::{DeserializableComponent, EntityPath};
#[cfg(feature = "serde")]
use re_log_types::EntityPath;

#[cfg(feature = "serde")]
use crate::EditableAutoValue;
Expand All @@ -8,7 +8,7 @@ use crate::EditableAutoValue;

/// Properties for a collection of entities.
#[cfg(feature = "serde")]
#[derive(Clone, Default)]
#[derive(Clone, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct EntityPropertyMap {
props: nohash_hasher::IntMap<EntityPath, EntityProperties>,
Expand Down Expand Up @@ -186,39 +186,3 @@ impl Default for ColorMapper {
Self::Colormap(Colormap::default())
}
}

// ----------------------------------------------------------------------------

/// Get the latest value for a given [`re_log_types::Component`].
///
/// This assumes that the row we get from the store only contains a single instance for this
/// component; it will log a warning otherwise.
///
/// This should only be used for "mono-components" such as `Transform` and `Tensor`.
pub fn query_latest_single<C: DeserializableComponent>(
data_store: &re_arrow_store::DataStore,
entity_path: &EntityPath,
query: &LatestAtQuery,
) -> Option<C>
where
for<'b> &'b C::ArrayType: IntoIterator,
{
crate::profile_function!();

// Although it would be nice to use the `re_query` helpers for this, we would need to move
// this out of re_data_store to avoid a circular dep. Since we don't need to do a join for
// single components this is easy enough.

let (_, cells) = data_store.latest_at(query, entity_path, C::name(), &[C::name()])?;
let cell = cells.get(0)?.as_ref()?;

let mut iter = cell.try_to_native::<C>().ok()?;

let component = iter.next();

if iter.next().is_some() {
re_log::warn_once!("Unexpected batch for {} at: {}", C::name(), entity_path);
}

component
}
2 changes: 2 additions & 0 deletions crates/re_data_store/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ pub mod entity_properties;
pub mod entity_tree;
mod instance_path;
pub mod log_db;
mod util;

pub use entity_properties::*;
pub use entity_tree::*;
pub use instance_path::*;
pub use log_db::LogDb;
pub use util::*;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no more wildcards please.. 😞

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For stuff like this I'm always going to default to matching the existing patterns established in the files.


#[cfg(feature = "serde")]
pub use editable_auto_value::EditableAutoValue;
Expand Down
11 changes: 8 additions & 3 deletions crates/re_data_store/src/log_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use re_arrow_store::{DataStoreConfig, TimeInt};
use re_log_types::{
component_types::InstanceKey, ArrowMsg, Component as _, ComponentPath, DataCell, DataRow,
DataTable, EntityPath, EntityPathHash, EntityPathOpMsg, LogMsg, PathOp, RecordingId,
RecordingInfo, RowId, SetRecordingInfo, TimePoint, Timeline,
RecordingInfo, RecordingType, RowId, SetRecordingInfo, TimePoint, Timeline,
};

use crate::{Error, TimesPerTimeline};
Expand Down Expand Up @@ -69,7 +69,8 @@ impl EntityDb {
Ok(())
}

fn try_add_data_row(&mut self, row: &DataRow) -> Result<(), Error> {
// TODO(jleibs): If this shouldn't be public, chain together other setters
pub fn try_add_data_row(&mut self, row: &DataRow) -> Result<(), Error> {
Comment on lines +72 to +73
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wanted to chat with @teh-cmc about whether this should be public... if it's not there's probably some other way of adding a data-row but it requires using other less direct APIs.

for (&timeline, &time_int) in row.timepoint().iter() {
self.times_per_timeline.insert(timeline, time_int);
}
Expand Down Expand Up @@ -195,6 +196,10 @@ impl LogDb {
self.recording_msg().map(|msg| &msg.info)
}

pub fn recording_type(&self) -> RecordingType {
self.recording_id.variant
}

pub fn recording_id(&self) -> &RecordingId {
&self.recording_id
}
Expand Down Expand Up @@ -241,7 +246,7 @@ impl LogDb {
Ok(())
}

fn add_begin_recording_msg(&mut self, msg: &SetRecordingInfo) {
pub fn add_begin_recording_msg(&mut self, msg: &SetRecordingInfo) {
self.recording_msg = Some(msg.clone());
}

Expand Down
88 changes: 88 additions & 0 deletions crates/re_data_store/src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use re_arrow_store::LatestAtQuery;
use re_log_types::{
DataRow, DeserializableComponent, EntityPath, RowId, SerializableComponent, TimeInt, TimePoint,
Timeline,
};

use crate::LogDb;

// ----------------------------------------------------------------------------

/// Get the latest value for a given [`re_log_types::Component`].
///
/// This assumes that the row we get from the store only contains a single instance for this
/// component; it will log a warning otherwise.
///
/// This should only be used for "mono-components" such as `Transform` and `Tensor`.
pub fn query_latest_single<C: DeserializableComponent>(
data_store: &re_arrow_store::DataStore,
entity_path: &EntityPath,
query: &LatestAtQuery,
) -> Option<C>
where
for<'b> &'b C::ArrayType: IntoIterator,
{
crate::profile_function!();

// Although it would be nice to use the `re_query` helpers for this, we would need to move
// this out of re_data_store to avoid a circular dep. Since we don't need to do a join for
// single components this is easy enough.

let (_, cells) = data_store.latest_at(query, entity_path, C::name(), &[C::name()])?;
let cell = cells.get(0)?.as_ref()?;

let mut iter = cell.try_to_native::<C>().ok()?;

let component = iter.next();

if iter.next().is_some() {
re_log::warn_once!("Unexpected batch for {} at: {}", C::name(), entity_path);
}

component
}

/// Get the latest value for a given [`re_log_types::Component`] assuming it is timeless.
///
/// This assumes that the row we get from the store only contains a single instance for this
/// component; it will log a warning otherwise.
pub fn query_timeless_single<C: DeserializableComponent>(
data_store: &re_arrow_store::DataStore,
entity_path: &EntityPath,
) -> Option<C>
where
for<'b> &'b C::ArrayType: IntoIterator,
{
let query = re_arrow_store::LatestAtQuery::new(Timeline::default(), TimeInt::MAX);
query_latest_single(data_store, entity_path, &query)
}

// ----------------------------------------------------------------------------

/// Store a single value for a given [`re_log_types::Component`].
pub fn store_one_component<C: SerializableComponent>(
log_db: &mut LogDb,
entity_path: &EntityPath,
timepoint: &TimePoint,
component: C,
) {
let mut row = DataRow::from_cells1(
RowId::random(),
entity_path.clone(),
timepoint.clone(),
1,
[component].as_slice(),
);
row.compute_all_size_bytes();

match log_db.entity_db.try_add_data_row(&row) {
Ok(()) => {}
Err(err) => {
re_log::warn_once!(
"Failed to store component {}.{}: {err}",
entity_path,
C::name(),
);
}
}
}
5 changes: 5 additions & 0 deletions crates/re_data_ui/src/log_msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ impl DataUi for SetRecordingInfo {
started,
recording_source,
is_official_example,
recording_type,
} = info;

egui::Grid::new("fields").num_columns(2).show(ui, |ui| {
Expand All @@ -61,6 +62,10 @@ impl DataUi for SetRecordingInfo {
ui.monospace("is_official_example:");
ui.label(format!("{is_official_example}"));
ui.end_row();

ui.monospace("recording_type:");
ui.label(format!("{recording_type}"));
ui.end_row();
});
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/re_log_encoding/src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ fn test_encode_decode() {
rustc_version: String::new(),
llvm_version: String::new(),
},
recording_type: re_log_types::RecordingType::Data,
},
})];

Expand Down
23 changes: 21 additions & 2 deletions crates/re_log_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ impl std::fmt::Display for RecordingType {
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct RecordingId {
variant: RecordingType,
id: Arc<String>,
pub variant: RecordingType,
pub id: Arc<String>,
}

impl RecordingId {
Expand All @@ -148,6 +148,11 @@ impl RecordingId {
id: Arc::new(str),
}
}

#[inline]
pub fn as_str(&self) -> &str {
self.id.as_str()
}
}

impl std::fmt::Display for RecordingId {
Expand Down Expand Up @@ -187,6 +192,10 @@ impl ApplicationId {
pub fn unknown() -> Self {
Self("unknown_app_id".to_owned())
}

pub fn as_str(&self) -> &str {
self.0.as_str()
}
}

impl std::fmt::Display for ApplicationId {
Expand Down Expand Up @@ -261,6 +270,16 @@ pub struct RecordingInfo {
pub started: Time,

pub recording_source: RecordingSource,

pub recording_type: RecordingType,
}

impl RecordingInfo {
/// Whether this `RecordingInfo` is the default used when a user is not explicitly
/// creating their own blueprint.
pub fn is_app_default_blueprint(&self) -> bool {
self.application_id.as_str() == self.recording_id.as_str()
jleibs marked this conversation as resolved.
Show resolved Hide resolved
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down
16 changes: 15 additions & 1 deletion crates/re_memory/src/memory_history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub struct MemoryHistory {

/// Bytes used by the datastore according to its own accounting.
pub counted_store: History<i64>,

/// Bytes used by the blueprint store according to its own accounting.
pub counted_blueprint: History<i64>,
}

impl Default for MemoryHistory {
Expand All @@ -35,6 +38,7 @@ impl Default for MemoryHistory {
counted: History::new(0..max_elems, max_seconds),
counted_gpu: History::new(0..max_elems, max_seconds),
counted_store: History::new(0..max_elems, max_seconds),
counted_blueprint: History::new(0..max_elems, max_seconds),
}
}
}
Expand All @@ -46,15 +50,22 @@ impl MemoryHistory {
counted,
counted_gpu,
counted_store,
counted_blueprint,
} = self;
resident.is_empty()
&& counted.is_empty()
&& counted_gpu.is_empty()
&& counted_store.is_empty()
&& counted_blueprint.is_empty()
}

/// Add data to history
pub fn capture(&mut self, counted_gpu: Option<i64>, counted_store: Option<i64>) {
pub fn capture(
&mut self,
counted_gpu: Option<i64>,
counted_store: Option<i64>,
counted_blueprint: Option<i64>,
) {
let mem_use = crate::MemoryUse::capture();
let now = crate::util::sec_since_start();

Expand All @@ -70,5 +81,8 @@ impl MemoryHistory {
if let Some(counted_store) = counted_store {
self.counted_store.add(now, counted_store);
}
if let Some(counted_blueprint) = counted_blueprint {
self.counted_blueprint.add(now, counted_blueprint);
}
}
}
2 changes: 1 addition & 1 deletion crates/re_renderer/src/view_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ pub enum Projection {
}

/// How [`Size::AUTO`] is interpreted.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct AutoSizeConfig {
/// Determines the point radius when [`crate::Size::AUTO`].
Expand Down
1 change: 1 addition & 0 deletions crates/re_sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ pub fn new_recording_info(
rustc_version: env!("RE_BUILD_RUSTC_VERSION").into(),
llvm_version: env!("RE_BUILD_LLVM_VERSION").into(),
},
recording_type: re_log_types::RecordingType::Data,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be passed as a parameter to this function? or renaming the function to new_data_recording_info

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to force a rust-API change on this one until we know we have the naming right. I'm still not really a fan of "data recording" vs "blueprint recording". My preference on user-facing terminology is still "Recording" vs "Blueprint".

}
}

Expand Down
Loading