66
66
R1 : Component + Send + Sync + ' static ,
67
67
F : FnMut (
68
68
(
69
- ( TimeInt , RowId ) ,
69
+ ( Option < TimeInt > , RowId ) ,
70
70
MaybeCachedComponentData < ' _ , InstanceKey > ,
71
71
MaybeCachedComponentData < ' _ , R1 > ,
72
72
) ,
@@ -93,7 +93,7 @@ macro_rules! impl_query_archetype {
93
93
$( $comp: Component + Send + Sync + ' static , ) *
94
94
F : FnMut (
95
95
(
96
- ( TimeInt , RowId ) ,
96
+ ( Option < TimeInt > , RowId ) ,
97
97
MaybeCachedComponentData <' _, InstanceKey >,
98
98
$( MaybeCachedComponentData <' _, $pov>, ) +
99
99
$( MaybeCachedComponentData <' _, Option <$comp>>, ) *
@@ -107,7 +107,7 @@ macro_rules! impl_query_archetype {
107
107
) ;
108
108
109
109
110
- let mut iter_results = |bucket: & crate :: CacheBucket | -> crate :: Result <( ) > {
110
+ let mut iter_results = |timeless : bool , bucket: & crate :: CacheBucket | -> crate :: Result <( ) > {
111
111
re_tracing:: profile_scope!( "iter" ) ;
112
112
113
113
let it = itertools:: izip!(
@@ -117,9 +117,9 @@ macro_rules! impl_query_archetype {
117
117
. ok_or_else( || re_query:: ComponentNotFoundError ( <$pov>:: name( ) ) ) ?, ) +
118
118
$( bucket. iter_component_opt:: <$comp>( )
119
119
. ok_or_else( || re_query:: ComponentNotFoundError ( <$comp>:: name( ) ) ) ?, ) *
120
- ) . map( |( time, instance_keys, $( $pov, ) + $( $comp, ) * ) | {
120
+ ) . map( |( ( time, row_id ) , instance_keys, $( $pov, ) + $( $comp, ) * ) | {
121
121
(
122
- * time,
122
+ ( ( !timeless ) . then_some ( * time) , * row_id ) ,
123
123
MaybeCachedComponentData :: Cached ( instance_keys) ,
124
124
$( MaybeCachedComponentData :: Cached ( $pov) , ) +
125
125
$( MaybeCachedComponentData :: Cached ( $comp) , ) *
@@ -133,68 +133,102 @@ macro_rules! impl_query_archetype {
133
133
Ok ( ( ) )
134
134
} ;
135
135
136
+
137
+ let upsert_results = |
138
+ data_time: TimeInt ,
139
+ arch_view: & :: re_query:: ArchetypeView <A >,
140
+ bucket: & mut crate :: CacheBucket ,
141
+ | -> crate :: Result <( ) > {
142
+ re_log:: trace!( data_time=?data_time, ?data_time, "fill" ) ;
143
+
144
+ // Grabbing the current time is quite costly on web.
145
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
146
+ let now = web_time:: Instant :: now( ) ;
147
+
148
+ bucket. [ <insert_pov$N _comp$M>] :: <A , $( $pov, ) + $( $comp, ) * >( data_time, & arch_view) ?;
149
+
150
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
151
+ {
152
+ let elapsed = now. elapsed( ) ;
153
+ :: re_log:: trace!(
154
+ store_id=%store. id( ) ,
155
+ %entity_path,
156
+ archetype=%A :: name( ) ,
157
+ "cached new entry in {elapsed:?} ({:0.3} entries/s)" ,
158
+ 1f64 / elapsed. as_secs_f64( )
159
+ ) ;
160
+ }
161
+
162
+ Ok ( ( ) )
163
+ } ;
164
+
136
165
let mut latest_at_callback = |query: & LatestAtQuery , latest_at_cache: & mut crate :: LatestAtCache | {
137
166
re_tracing:: profile_scope!( "latest_at" , format!( "{query:?}" ) ) ;
138
167
139
- let crate :: LatestAtCache { per_query_time, per_data_time } = latest_at_cache;
168
+ let crate :: LatestAtCache { per_query_time, per_data_time, timeless } = latest_at_cache;
140
169
141
170
let query_time_bucket_at_query_time = match per_query_time. entry( query. at) {
142
171
std:: collections:: btree_map:: Entry :: Occupied ( query_time_bucket_at_query_time) => {
143
172
// Fastest path: we have an entry for this exact query time, no need to look any
144
173
// further.
145
- return iter_results( & query_time_bucket_at_query_time. get( ) . read( ) ) ;
174
+ re_log:: trace!( query_time=?query. at, "cache hit (query time)" ) ;
175
+ return iter_results( false , & query_time_bucket_at_query_time. get( ) . read( ) ) ;
146
176
}
147
177
entry @ std:: collections:: btree_map:: Entry :: Vacant ( _) => entry,
148
178
} ;
149
179
150
180
let arch_view = query_archetype:: <A >( store, & query, entity_path) ?;
151
- // TODO(cmc): actual timeless caching support.
152
- let data_time = arch_view. data_time( ) . unwrap_or( TimeInt :: MIN ) ;
181
+ let data_time = arch_view. data_time( ) ;
153
182
154
183
// Fast path: we've run the query and realized that we already have the data for the resulting
155
184
// _data_ time, so let's use that to avoid join & deserialization costs.
156
- if let Some ( data_time_bucket_at_data_time) = per_data_time. get( & data_time) {
157
- * query_time_bucket_at_query_time. or_default( ) = std:: sync:: Arc :: clone( & data_time_bucket_at_data_time) ;
185
+ if let Some ( data_time) = data_time { // Reminder: `None` means timeless.
186
+ if let Some ( data_time_bucket_at_data_time) = per_data_time. get( & data_time) {
187
+ re_log:: trace!( query_time=?query. at, ?data_time, "cache hit (data time)" ) ;
188
+
189
+ * query_time_bucket_at_query_time. or_default( ) = std:: sync:: Arc :: clone( & data_time_bucket_at_data_time) ;
158
190
159
- // We now know for a fact that a query at that data time would yield the same
160
- // results: copy the bucket accordingly so that the next cache hit for that query
161
- // time ends up taking the fastest path.
162
- let query_time_bucket_at_data_time = per_query_time. entry( data_time) ;
163
- * query_time_bucket_at_data_time. or_default( ) = std:: sync:: Arc :: clone( & data_time_bucket_at_data_time) ;
191
+ // We now know for a fact that a query at that data time would yield the same
192
+ // results: copy the bucket accordingly so that the next cache hit for that query
193
+ // time ends up taking the fastest path.
194
+ let query_time_bucket_at_data_time = per_query_time. entry( data_time) ;
195
+ * query_time_bucket_at_data_time. or_default( ) = std:: sync:: Arc :: clone( & data_time_bucket_at_data_time) ;
164
196
165
- return iter_results( & data_time_bucket_at_data_time. read( ) ) ;
197
+ return iter_results( false , & data_time_bucket_at_data_time. read( ) ) ;
198
+ }
199
+ } else {
200
+ if let Some ( timeless_bucket) = timeless. as_ref( ) {
201
+ re_log:: trace!( query_time=?query. at, "cache hit (data time, timeless)" ) ;
202
+ return iter_results( true , timeless_bucket) ;
203
+ }
166
204
}
167
205
168
206
let query_time_bucket_at_query_time = query_time_bucket_at_query_time. or_default( ) ;
169
207
170
208
// Slowest path: this is a complete cache miss.
171
- {
172
- re_tracing :: profile_scope! ( "fill ") ;
209
+ if let Some ( data_time ) = data_time { // Reminder: `None` means timeless.
210
+ re_log :: trace! ( query_time=?query . at , ?data_time , "cache miss ") ;
173
211
174
- // Grabbing the current time is quite costly on web.
175
- #[ cfg( not( target_arch = "wasm32" ) ) ]
176
- let now = web_time:: Instant :: now( ) ;
177
-
178
- let mut query_time_bucket_at_query_time = query_time_bucket_at_query_time. write( ) ;
179
- query_time_bucket_at_query_time. [ <insert_pov$N _comp$M>] :: <A , $( $pov, ) + $( $comp, ) * >( query. at, & arch_view) ?;
180
-
181
- #[ cfg( not( target_arch = "wasm32" ) ) ]
182
212
{
183
- let elapsed = now. elapsed( ) ;
184
- :: re_log:: trace!(
185
- store_id=%store. id( ) ,
186
- %entity_path,
187
- archetype=%A :: name( ) ,
188
- "cached new entry in {elapsed:?} ({:0.3} entries/s)" ,
189
- 1f64 / elapsed. as_secs_f64( )
190
- ) ;
213
+ let mut query_time_bucket_at_query_time = query_time_bucket_at_query_time. write( ) ;
214
+ upsert_results( data_time, & arch_view, & mut query_time_bucket_at_query_time) ?;
191
215
}
192
- }
193
216
194
- let data_time_bucket_at_data_time = per_data_time. entry( data_time) ;
195
- * data_time_bucket_at_data_time. or_default( ) = std:: sync:: Arc :: clone( & query_time_bucket_at_query_time) ;
217
+ let data_time_bucket_at_data_time = per_data_time. entry( data_time) ;
218
+ * data_time_bucket_at_data_time. or_default( ) = std:: sync:: Arc :: clone( & query_time_bucket_at_query_time) ;
219
+
220
+ iter_results( false , & query_time_bucket_at_query_time. read( ) )
221
+ } else {
222
+ re_log:: trace!( query_time=?query. at, "cache miss (timeless)" ) ;
223
+
224
+ let mut timeless_bucket = crate :: CacheBucket :: default ( ) ;
196
225
197
- iter_results( & query_time_bucket_at_query_time. read( ) )
226
+ upsert_results( TimeInt :: MIN , & arch_view, & mut timeless_bucket) ?;
227
+ iter_results( true , & timeless_bucket) ?;
228
+
229
+ * timeless = Some ( timeless_bucket) ;
230
+ Ok ( ( ) )
231
+ }
198
232
} ;
199
233
200
234
@@ -209,8 +243,7 @@ macro_rules! impl_query_archetype {
209
243
210
244
for arch_view in arch_views {
211
245
let data = (
212
- // TODO(cmc): actual timeless caching support.
213
- ( arch_view. data_time( ) . unwrap_or( TimeInt :: MIN ) , arch_view. primary_row_id( ) ) ,
246
+ ( arch_view. data_time( ) , arch_view. primary_row_id( ) ) ,
214
247
MaybeCachedComponentData :: Raw ( arch_view. iter_instance_keys( ) . collect( ) ) ,
215
248
$( MaybeCachedComponentData :: Raw ( arch_view. iter_required_component:: <$pov>( ) ?. collect( ) ) , ) +
216
249
$( MaybeCachedComponentData :: Raw ( arch_view. iter_optional_component:: <$comp>( ) ?. collect( ) ) , ) *
@@ -228,8 +261,7 @@ macro_rules! impl_query_archetype {
228
261
let arch_view = :: re_query:: query_archetype:: <A >( store, query, entity_path) ?;
229
262
230
263
let data = (
231
- // TODO(cmc): actual timeless caching support.
232
- ( arch_view. data_time( ) . unwrap_or( TimeInt :: MIN ) , arch_view. primary_row_id( ) ) ,
264
+ ( arch_view. data_time( ) , arch_view. primary_row_id( ) ) ,
233
265
MaybeCachedComponentData :: Raw ( arch_view. iter_instance_keys( ) . collect( ) ) ,
234
266
$( MaybeCachedComponentData :: Raw ( arch_view. iter_required_component:: <$pov>( ) ?. collect( ) ) , ) +
235
267
$( MaybeCachedComponentData :: Raw ( arch_view. iter_optional_component:: <$comp>( ) ?. collect( ) ) , ) *
@@ -286,7 +318,7 @@ where
286
318
R1 : Component + Send + Sync + ' static ,
287
319
F : FnMut (
288
320
(
289
- ( TimeInt , RowId ) ,
321
+ ( Option < TimeInt > , RowId ) ,
290
322
MaybeCachedComponentData < ' _ , InstanceKey > ,
291
323
MaybeCachedComponentData < ' _ , R1 > ,
292
324
) ,
@@ -318,7 +350,7 @@ macro_rules! impl_query_archetype_with_history {
318
350
$( $comp: Component + Send + Sync + ' static , ) *
319
351
F : FnMut (
320
352
(
321
- ( TimeInt , RowId ) ,
353
+ ( Option < TimeInt > , RowId ) ,
322
354
MaybeCachedComponentData <' _, InstanceKey >,
323
355
$( MaybeCachedComponentData <' _, $pov>, ) +
324
356
$( MaybeCachedComponentData <' _, Option <$comp>>, ) *
0 commit comments