Skip to content

Commit 56207f3

Browse files
committedJul 1, 2024
support per-component row-id ranges and fix static writes accordingly
1 parent 1e24a6b commit 56207f3

File tree

2 files changed

+71
-7
lines changed

2 files changed

+71
-7
lines changed
 

‎crates/re_chunk/src/chunk.rs

+58
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,64 @@ impl Chunk {
217217
})
218218
.collect()
219219
}
220+
221+
/// Computes the `RowId` range covered by each individual component column on each timeline.
222+
///
223+
/// This is different from the `RowId` range covered by the [`Chunk`] as a whole because component
224+
/// columns are potentially sparse.
225+
///
226+
/// This is crucial for indexing and queries to work properly.
227+
//
228+
// TODO(cmc): This needs to be stored in chunk metadata and transported across IPC.
229+
pub fn row_id_range_per_component(&self) -> BTreeMap<ComponentName, (RowId, RowId)> {
230+
re_tracing::profile_function!();
231+
232+
let row_ids = self.row_ids().collect_vec();
233+
234+
if self.is_sorted() {
235+
self.components
236+
.iter()
237+
.filter_map(|(component_name, list_array)| {
238+
let mut row_id_min = None;
239+
let mut row_id_max = None;
240+
241+
for (i, &row_id) in row_ids.iter().enumerate() {
242+
if list_array.is_valid(i) {
243+
row_id_min = Some(row_id);
244+
}
245+
}
246+
for (i, &row_id) in row_ids.iter().enumerate().rev() {
247+
if list_array.is_valid(i) {
248+
row_id_max = Some(row_id);
249+
}
250+
}
251+
252+
Some((*component_name, (row_id_min?, row_id_max?)))
253+
})
254+
.collect()
255+
} else {
256+
self.components
257+
.iter()
258+
.filter_map(|(component_name, list_array)| {
259+
let mut row_id_min = Some(RowId::MAX);
260+
let mut row_id_max = Some(RowId::ZERO);
261+
262+
for (i, &row_id) in row_ids.iter().enumerate() {
263+
if list_array.is_valid(i) && Some(row_id) > row_id_min {
264+
row_id_min = Some(row_id);
265+
}
266+
}
267+
for (i, &row_id) in row_ids.iter().enumerate().rev() {
268+
if list_array.is_valid(i) && Some(row_id) < row_id_max {
269+
row_id_max = Some(row_id);
270+
}
271+
}
272+
273+
Some((*component_name, (row_id_min?, row_id_max?)))
274+
})
275+
.collect()
276+
}
277+
}
220278
}
221279

222280
// ---

‎crates/re_chunk_store/src/writes.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,17 @@ impl ChunkStore {
4949

5050
self.insert_id += 1;
5151

52-
let row_id_min = row_id_range.0;
53-
let row_id_max = row_id_range.1;
54-
5552
self.chunks_per_chunk_id.insert(chunk.id(), chunk.clone());
5653
self.chunk_ids_per_min_row_id
57-
.entry(row_id_min)
54+
.entry(row_id_range.0)
5855
.or_default()
5956
.push(chunk.id());
6057

6158
if chunk.is_static() {
6259
// Static data: make sure to keep the most recent chunk available for each component column.
6360

61+
let row_id_range_per_component = chunk.row_id_range_per_component();
62+
6463
for (&component_name, list_array) in chunk.components() {
6564
let is_empty = list_array
6665
.validity()
@@ -69,6 +68,12 @@ impl ChunkStore {
6968
continue;
7069
}
7170

71+
let Some((_row_id_min, row_id_max)) =
72+
row_id_range_per_component.get(&component_name)
73+
else {
74+
continue;
75+
};
76+
7277
self.static_chunk_ids_per_entity
7378
.entry(chunk.entity_path().clone())
7479
.or_default()
@@ -81,11 +86,12 @@ impl ChunkStore {
8186
RowId::ZERO,
8287
|chunk| {
8388
chunk
84-
.row_id_range()
85-
.map_or(RowId::ZERO, |(_, row_id_max)| row_id_max)
89+
.row_id_range_per_component()
90+
.get(&component_name)
91+
.map_or(RowId::ZERO, |(_, row_id_max)| *row_id_max)
8692
},
8793
);
88-
if row_id_max > cur_row_id_max {
94+
if *row_id_max > cur_row_id_max {
8995
*cur_chunk_id = chunk.id();
9096
}
9197
})

0 commit comments

Comments
 (0)