-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Plot borrowed data #3849
Plot borrowed data #3849
Conversation
Did you benchmark to see what kind of performance gains this can give? |
This type is used to avoid lifetime issues with buil_fn in lib.rs
This avoids requiring move and set
PlotGeometry::GenericPoints has same behaviour as PlotGeometry::Rects
Legend used to take a slice but this does not work if you have an iterator but slices can be iterators. It is thus best to take a simple iterator of the desired type.
- Remove old show that was just wrapper of show_dyn - Rename show_dyn to show - Change type of show to match old show and new types
- buil_fn now takes PlotUiBuilder and returns PlotUi and R
- Return a ref mut self on return which allows chaining of multiple functions in a nicer way then before. - Add function to add Generic plot points to items
I have done profiling to see what was hurting performance. The recreation of all Points was the first obvious problem. In my case I store roughly 350k PlotPoints to draw, cloning or recalculating them every repaint gets in the way. In the case of a dynamic element (e.g. a filter) data needs to be recomputed every time. There is still some improvement here as now you can use a lazy evaluated filter over your static PlotPoints. Additionally, there is added ergonomics in using an Iterator as you can easily apply |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, this is looking much better!
It would be great if one of the examples in crates/egui_demo_lib/src/demo/plot_demo.rs
used the new borrowing mechanism
Added Scatter plot example with decently cool step_by to show off the iterator part. It plots 50k dots, not sure how much web could handle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First of all, I appreciate all the effort you've put into this!
However, this is a lot of new complexity, so I want to make sure this is justified. I'm likely the one who is going to be maintaining it for the foreseeable future.
Whenever I've ran into plot performance issues, it's been on the tessellator side, not here. And the solution is usually to aggregate the data, i.e. downsample it before handing it to egui_plot
(see for instance rerun-io/rerun#4865).
So I'd be very interested in seeing some before/after flamegraph profiler screenshots, or an added benchmark to justify all this.
@@ -368,7 +375,7 @@ impl MarkerDemo { | |||
markers_plot | |||
.show(ui, |plot_ui| { | |||
for marker in self.markers() { | |||
plot_ui.points(marker); | |||
plot_ui.owned_points(marker); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a slightly annoying name change, but maybe fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can replace it with a single function but would need to expose PlotItem as it would go into a public interface.
pub fn points<T: 'a>(&mut self, mut points: Points<T>) -> &mut Self
where
Points<T>: PlotItem,
{
// Give the points an automatic color if no color has been assigned.
if points.color == Color32::TRANSPARENT {
points.color = self.auto_color();
}
self.items.push(Box::new(points));
self
}
This is something I am not sure about. If it is exposed maybe it should be sealed?
where | ||
T: GenericPlotPoints, | ||
{ | ||
pub fn new_generic(t: T) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be called something like from_iter
, and have a docstring
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might not be the best name:
method
from_iter
can be confused for the standard trait methodstd::iter::FromIterator::from_iter
consider implementing the traitstd::iter::FromIterator
or choosing a less ambiguous method name
for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
-W clippy::should-implement-trait
implied by-W clippy::all
Also implementing FromIterator trait is not an option.
} | ||
|
||
/// Add data points. | ||
pub fn borrowed_points<'b, T: 'a>(&mut self, mut points: Points<T>) -> &mut Self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if we could combine owned_points
and borrowed_points
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that it would be nicer.
We need to require that everything impls PlotItem and this is either done through a generic type constraint or well defined types that impl PlotItem.
In my profiling there were some three things in performance
There is as I see it no easy way to benchmark anything in egui as I have a flamegraph where egui spends significant time in the shape vec reallocating which should be preventable: In my optimizeShapeVec branch I made a simple function to count the shapes. Which should already help a bit. Tesselation vec (the reserves are nice but it would be nicer if it could be done at once) These are two examples of likely relatively straightforward performance improvements. I will say I think there is indeed more 'real' gain to be had with shapes and tessellation then plot points but it is not insignificant. Additionally, iterators makes down sampling simpler to reconstructing the data every frame. This PR is a start to performance improvements. However, right now I feel like there is a requirement to invest a significant amount of additional time to make this or other PRs to increase performance land. |
Sorry this is a big change for through egui_plot. I can not make it smaller.
./scripts/check.sh
.The script does not work on 1.72.0
Partially closes emilk/egui_plot#18.
After much trial and error this PR enables the user to plot borrowed data.
It allows the user to plot
Iterator
s,slice
s,PlotPoints
. While there is still optimization possible per my message in emilk/egui_plot#18. This is a good first step and allows for easy performance improvement on the users side.E.g. the user can now easily create a slice
&[PlotPoint]
that represents their point data or go a step further and represent their data using aniter().filter(...)
approach.Will this break current builds: Yes