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

Primary caching 12: bare-bone range support #4784

Merged
merged 11 commits into from
Jan 15, 2024

Conversation

teh-cmc
Copy link
Member

@teh-cmc teh-cmc commented Jan 11, 2024

Prefer on a per-commit basis, stuff has moved around

Range queries are back!... in the most primitive form possible.

No invalidation, no bucketing, no optimization, no nothing. Just putting everything in place.

24-01-11_12.37.56.patched.mp4

Part of the primary caching series of PR (index search, joins, deserialization):


Checklist

  • I have read and agree to Contributor Guide and the Code of Conduct
  • I've included a screenshot or gif (if applicable)
  • I have tested the web demo (if applicable):
  • The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG

@teh-cmc teh-cmc added 🔍 re_query affects re_query itself 🚀 performance Optimization, memory use, etc do-not-merge Do not merge this PR include in changelog labels Jan 11, 2024
Copy link
Member Author

Choose a reason for hiding this comment

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

All of this stuff was only moved around, no modifications whatsoever.

Copy link
Member Author

Choose a reason for hiding this comment

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

Barely any changes: the latest-at stuff has been moved to latest_at.rs and this file now simply redirects the caller to either latest_at.rs or range.rs appropriately.

Comment on lines 557 to 595

// ---

// NOTE: Because we're working with deserialized data, everything has to be done with metaprogramming,
// which is notoriously painful in Rust (i.e., macros).
// For this reason we move as much of the code as possible into the already existing macros in `query.rs`.

/// Caches the results of `LatestAt` queries.
#[derive(Default)]
pub struct LatestAtCache {
/// Organized by _query_ time.
///
/// If the data you're looking for isn't in here, try partially running the query and check
/// if there is any data available for the resulting _data_ time in [`Self::per_data_time`].
pub per_query_time: BTreeMap<TimeInt, Arc<RwLock<CacheBucket>>>,

/// Organized by _data_ time.
///
/// Due to how our latest-at semantics work, any number of queries at time `T+n` where `n >= 0`
/// can result in a data time of `T`.
pub per_data_time: BTreeMap<TimeInt, Arc<RwLock<CacheBucket>>>,

/// Dedicated bucket for timeless data, if any.
///
/// Query time and data time are one and the same in the timeless case, therefore we only need
/// this one bucket.
//
// NOTE: Lives separately so we don't pay the extra `Option` cost in the much more common
// timeful case.
pub timeless: Option<CacheBucket>,

/// Total size of the data stored in this cache in bytes.
pub total_size_bytes: u64,
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Moved to latest_at.rs

crates/re_query_cache/src/cache.rs Outdated Show resolved Hide resolved
crates/re_query_cache/src/cache.rs Outdated Show resolved Hide resolved
crates/re_query_cache/src/cache.rs Outdated Show resolved Hide resolved
crates/re_query_cache/src/cache.rs Outdated Show resolved Hide resolved
Copy link
Member Author

Choose a reason for hiding this comment

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

Nothing interesting here, just made it so it doesn't depend on production components.

Copy link
Member Author

Choose a reason for hiding this comment

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

1:1 port of the tests in crates/re_query/tests/archetype_range_tests.rs, with caching enabled.

Of course they don't pass yet. We'll get there in the upcoming PRs.

@teh-cmc
Copy link
Member Author

teh-cmc commented Jan 11, 2024

Update: ported the original range test suite over.

@teh-cmc
Copy link
Member Author

teh-cmc commented Jan 11, 2024

Updated so that the app options now toggle latest-at and range queries as a whole:
image

latest-at defaults to enabled, while range stays disabled for now.

Copy link
Member

@Wumpf Wumpf left a comment

Choose a reason for hiding this comment

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

thanks for the notes on what has moved, made reviewing it a lot easier.
Lgtm as well, but struggled a little bit to follow in a few spots, but not concerned :)

@@ -0,0 +1,388 @@
//! Contains:
//! - A 1:1 port of the tests in `crates/re_query/tests/archetype_range_tests.rs`, with caching enabled.
Copy link
Member

Choose a reason for hiding this comment

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

it would be nice to share some of store setup code from there

Copy link
Member Author

Choose a reason for hiding this comment

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

Eh, I do expect them to grow apart as time goes on; they don't worry about the same things exactly.

teh-cmc added a commit that referenced this pull request Jan 15, 2024
)

_99% grunt work, the only somewhat interesting thing happens in
`query_archetype`_

Our query model always operates with two distinct timestamps: the
timestamp you're querying for (`query_time`) vs. the timestamp of the
data you get back (`data_time`).

This is the result of our latest-at semantics: a query for a point at
time `10` can return a point at time `2`.
This is important to know when caching the data: a query at time `4` and
a query at time `8` that both return the data at time `2` must share the
same single entry or the memory budget would explode.

This PR just updates all existing latest-at APIs so they return the data
time in their response.
This was already the case for range APIs.

Note that in the case of `query_archetype`, which is a compound API that
emits multiple queries, the data time of the final result is the most
recent data time among all of its components.

A follow-up PR will use the data time to deduplicate entries in the
latest-at cache.

---

Part of the primary caching series of PR (index search, joins,
deserialization):
- #4592
- #4593
- #4659
- #4680 
- #4681
- #4698
- #4711
- #4712
- #4721 
- #4726 
- #4773
- #4784
- #4785
- #4793
- #4800
teh-cmc added a commit that referenced this pull request Jan 15, 2024
…ation (#4712)

Introduces the notion of cache deduplication: given a query at time `4`
and a query at time `8` that both returns data at time `2`, they must
share a single cache entry.

I.e. starting with this PR, scrubbing through the OPF example will not
result if more cache memory being used.

---

Part of the primary caching series of PR (index search, joins,
deserialization):
- #4592
- #4593
- #4659
- #4680 
- #4681
- #4698
- #4711
- #4712
- #4721 
- #4726 
- #4773
- #4784
- #4785
- #4793
- #4800
teh-cmc added a commit that referenced this pull request Jan 15, 2024
Introduces a dedicated cache bucket for timeless data and properly
forwards the information through all APIs downstream.

---

Part of the primary caching series of PR (index search, joins,
deserialization):
- #4592
- #4593
- #4659
- #4680 
- #4681
- #4698
- #4711
- #4712
- #4721 
- #4726 
- #4773
- #4784
- #4785
- #4793
- #4800
@teh-cmc teh-cmc force-pushed the cmc/primcache_12_barebone_range branch from 17b548b to 5fb6abd Compare January 15, 2024 12:26
@teh-cmc teh-cmc force-pushed the cmc/primcache_12_barebone_range branch from 5480cc3 to a64f1c3 Compare January 15, 2024 14:38
@teh-cmc teh-cmc removed the do-not-merge Do not merge this PR label Jan 15, 2024
@teh-cmc teh-cmc merged commit 886014a into main Jan 15, 2024
13 of 25 checks passed
@teh-cmc teh-cmc deleted the cmc/primcache_12_barebone_range branch January 15, 2024 14:49
teh-cmc added a commit that referenced this pull request Jan 15, 2024
teh-cmc added a commit that referenced this pull request Jan 15, 2024
… range queries (#4793)

Our low-level range APIs used to bake the latest-at results at
`range.min - 1` into the range results, which is a big problem in a
multi tenant setting because `range(1, 10)` vs. `latestat(1) + range(2,
10)` are two completely different things.

Side-effect: a plot with a window of len 1 now behaves as expected:



https://github.com/rerun-io/rerun/assets/2910679/957ac367-35a6-4bea-9f40-59d51c556639

---

Part of the primary caching series of PR (index search, joins,
deserialization):
- #4592
- #4593
- #4659
- #4680 
- #4681
- #4698
- #4711
- #4712
- #4721 
- #4726 
- #4773
- #4784
- #4785
- #4793
- #4800
teh-cmc added a commit that referenced this pull request Jan 15, 2024
The most obvious and most important performance optimization when doing
cached range queries: only upsert data at the edges of the bucket /
ring-buffer.

This works because our buckets (well, singular, at the moment) are
always dense.

- #4793  

![image](https://github.com/rerun-io/rerun/assets/2910679/7246827c-4977-4b3f-9ef9-f8e96b8a9bea)
- #4800:

![image](https://github.com/rerun-io/rerun/assets/2910679/ab78643b-a98b-4568-b510-2b8827467095)

---

Part of the primary caching series of PR (index search, joins,
deserialization):
- #4592
- #4593
- #4659
- #4680 
- #4681
- #4698
- #4711
- #4712
- #4721 
- #4726 
- #4773
- #4784
- #4785
- #4793
- #4800
teh-cmc added a commit that referenced this pull request Jan 23, 2024
Range queries used to A) return the frame a T-1, B) accumulate state
starting at T-1 and then C) yield frames starting at T.

A) was a huge issue for many reasons, which #4793 took care of by
eliminating both A) and B).

But we need B) for range queries to be context-free, i.e. to be
guaranteed that `Range(5, 10)` and `Range(4, 10)` will return the exact
same data for frame `5`.
This is crucial for multi-tenant settings where those 2 example queries
would share the same cache.

It also is the nicer-nicer version of the range semantics that we wanted
anyway, I just didn't realize back then that it would require so little
changes, or I would've gone straight for that.

---

Part of the primary caching series of PR (index search, joins,
deserialization):
- #4592
- #4593
- #4659
- #4680 
- #4681
- #4698
- #4711
- #4712
- #4721 
- #4726 
- #4773
- #4784
- #4785
- #4793
- #4800
- #4851
- #4852
- #4853
- #4856
teh-cmc added a commit that referenced this pull request Jan 23, 2024
Simply add a timeless path for the range cache, and actually only
iterate over the range the user asked for (we were still blindly
iterating over everything until now).

Also some very minimal clean up related to #4832, but we have a long way
to go...
- #4832

---

- Fixes #4821 

---

Part of the primary caching series of PR (index search, joins,
deserialization):
- #4592
- #4593
- #4659
- #4680 
- #4681
- #4698
- #4711
- #4712
- #4721 
- #4726 
- #4773
- #4784
- #4785
- #4793
- #4800
- #4851
- #4852
- #4853
- #4856
teh-cmc added a commit that referenced this pull request Jan 23, 2024
Implement range invalidation and do a quality pass over all the size
tracking stuff in the cache.

**Range caching is now enabled by default!**

- Fixes #4809 
- Fixes #374

---

Part of the primary caching series of PR (index search, joins,
deserialization):
- #4592
- #4593
- #4659
- #4680 
- #4681
- #4698
- #4711
- #4712
- #4721 
- #4726 
- #4773
- #4784
- #4785
- #4793
- #4800
- #4851
- #4852
- #4853
- #4856
teh-cmc added a commit that referenced this pull request Jan 23, 2024
- Quick sanity pass over all the intermediary locks and refcounts to
make sure we don't hold anything for longer than we need.
- Get rid of all static globals and let the caches live with their
associated stores in `EntityDb`.
- `CacheKey` no longer requires a `StoreId`.

---

- Fixes #4815 

---

Part of the primary caching series of PR (index search, joins,
deserialization):
- #4592
- #4593
- #4659
- #4680 
- #4681
- #4698
- #4711
- #4712
- #4721 
- #4726 
- #4773
- #4784
- #4785
- #4793
- #4800
- #4851
- #4852
- #4853
- #4856
@abey79 abey79 changed the title Primary caching 12: barebone range support Primary caching 12: bare-bone range support Feb 7, 2024
emilk added a commit that referenced this pull request Jul 5, 2024
## What
* Closes #5315

## egui changelog

### ⭐ Added
* Add `Image::uri()` [#4720](emilk/egui#4720) by
[@rustbasic](https://github.com/rustbasic)

### 🔧 Changed
* Better documentation for `Event::Zoom`
[#4778](emilk/egui#4778) by
[@emilk](https://github.com/emilk)
* Hide tooltips when scrolling
[#4784](emilk/egui#4784) by
[@emilk](https://github.com/emilk)
* Smoother animations [#4787](emilk/egui#4787)
by [@emilk](https://github.com/emilk)
* Hide tooltip on click [#4789](emilk/egui#4789)
by [@emilk](https://github.com/emilk)

### 🐛 Fixed
* Fix default height of top/bottom panels
[#4779](emilk/egui#4779) by
[@emilk](https://github.com/emilk)
* Show the innermost debug rectangle when pressing all modifier keys
[#4782](emilk/egui#4782) by
[@emilk](https://github.com/emilk)
* Fix occasional flickering of pointer-tooltips
[#4788](emilk/egui#4788) by
[@emilk](https://github.com/emilk)

## eframe changelog
* Web: only capture clicks/touches when actually over canvas
[#4775](emilk/egui#4775) by
[@lucasmerlin](https://github.com/lucasmerlin)

## Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6785?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6785?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6785)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
emilk added a commit that referenced this pull request Jul 5, 2024
## What
* Closes #5315

## egui changelog

### ⭐ Added
* Add `Image::uri()` [#4720](emilk/egui#4720) by
[@rustbasic](https://github.com/rustbasic)

### 🔧 Changed
* Better documentation for `Event::Zoom`
[#4778](emilk/egui#4778) by
[@emilk](https://github.com/emilk)
* Hide tooltips when scrolling
[#4784](emilk/egui#4784) by
[@emilk](https://github.com/emilk)
* Smoother animations [#4787](emilk/egui#4787)
by [@emilk](https://github.com/emilk)
* Hide tooltip on click [#4789](emilk/egui#4789)
by [@emilk](https://github.com/emilk)

### 🐛 Fixed
* Fix default height of top/bottom panels
[#4779](emilk/egui#4779) by
[@emilk](https://github.com/emilk)
* Show the innermost debug rectangle when pressing all modifier keys
[#4782](emilk/egui#4782) by
[@emilk](https://github.com/emilk)
* Fix occasional flickering of pointer-tooltips
[#4788](emilk/egui#4788) by
[@emilk](https://github.com/emilk)

## eframe changelog
* Web: only capture clicks/touches when actually over canvas
[#4775](emilk/egui#4775) by
[@lucasmerlin](https://github.com/lucasmerlin)

## Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6785?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6785?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6785)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
include in changelog 🚀 performance Optimization, memory use, etc 🔍 re_query affects re_query itself
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants