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

Clean up code to find the current keyframe #11306

Merged
merged 16 commits into from Jan 13, 2024

Conversation

alice-i-cecile
Copy link
Member

@alice-i-cecile alice-i-cecile commented Jan 11, 2024

Objective

While working on #10832, I found this code very dense and hard to understand.

I was not confident in my fix (or the correctness of the existing code).

Solution

Clean up, test and document the code used in the apply_animation system.

I also added a pair of length-related utility methods to Keyframes for easier testing. They seemed generically useful, so I made them pub.

Changelog

  • Added VariableCurve::find_current_keyframe method.
  • Added Keyframes::len and is_empty methods.

@alice-i-cecile alice-i-cecile added C-Code-Quality A section of code that is hard to understand or change A-Animation Make things move and change over time labels Jan 11, 2024
@mockersf
Copy link
Member

mockersf commented Jan 11, 2024

refactoring this is a very good opportunity to add tests 🙂

@alice-i-cecile
Copy link
Member Author

alice-i-cecile commented Jan 12, 2024

I've added a solid battery of tests now. Both the original code and the refactor versions pass all 6 of them: I am now confident that there is no change in behavior and that the behavior is correct.

See c9f4f9f for the port of the original algorithm: I deliberately committed and then reverted this to make it easier for reviewers to verify.

@alice-i-cecile alice-i-cecile added the C-Usability A simple quality-of-life change that makes Bevy easier to use label Jan 12, 2024
@alice-i-cecile
Copy link
Member Author

alice-i-cecile commented Jan 12, 2024

Basic perf testing reveals no major regressions: I'm getting 2.2 ms frame times on the many_foxes stress test both before and after this PR.

I don't think we can get a better answer than that without some actual benchmarks (and better methods in general).

image

From @mockersf: yellow is this PR, red is main.

pub fn len(&self) -> usize {
match self {
Keyframes::Weights(vec) => vec.len(),
Keyframes::Translation(vec) | Keyframes::Scale(vec) => vec.len(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are these two on the same line while the others are split up?

Suggested change
Keyframes::Translation(vec) | Keyframes::Scale(vec) => vec.len(),
Keyframes::Translation(vec) => vec.len(),
Keyframes::Scale(vec) => vec.len(),

Copy link
Member

@mockersf mockersf Jan 13, 2024

Choose a reason for hiding this comment

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

because vec is the same type for translation and scale, but not for weights and rotation

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep I would do all 4 on one line but it didn't compile.

// PERF: finding the current keyframe can be optimised
let search_result = self
.keyframe_timestamps
.binary_search_by(|probe| probe.partial_cmp(&seek_time).unwrap());
Copy link
Contributor

Choose a reason for hiding this comment

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

im willing to bet 2 cents and a teaspoon of maple syrup that the extremely minor perf regression is thanks to the unwrap check, and something as smoothbrained and inelegant as
|probe| if probe < &seek_time { Ordering::Less } else if probe == &seek_time { Ordering::Equal } else { Ordering::Greater }
would fix it

Copy link
Member

@mockersf mockersf Jan 13, 2024

Choose a reason for hiding this comment

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

I tried comparing with tracy, the manual compare is a tiny bit worse than the unwrap.

I would love that teaspoon of maple syrup!

Copy link
Contributor

Choose a reason for hiding this comment

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

alright come over, im in berkeley. i'll even make you a pancake to put it on

);
}
if animation.path_cache.len() != animation_clip.paths.len() {
animation.path_cache = vec![Vec::new(); animation_clip.paths.len()];
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need to make a whole new vec or can we just add/remove elements until the len is the same?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's possible to do a clear() followed by an extend(…). The Vec::new here doesn't cause an allocation until something is pushed to it.

@mockersf mockersf added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Jan 13, 2024
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Jan 13, 2024
Merged via the queue into bevyengine:main with commit 98b62e8 Jan 13, 2024
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Animation Make things move and change over time C-Code-Quality A section of code that is hard to understand or change C-Usability A simple quality-of-life change that makes Bevy easier to use S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants