-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Reduce compile time of bevy_ptr::OwnedPtr::make function #15644
base: main
Are you sure you want to change the base?
Conversation
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 can be quite hard to measure these smaller changes, but I agree with the technique, and it's trivial for the compiler to inline the new function if that produces better results.
// SAFETY: The value behind the pointer will not get dropped or observed later, | ||
// so it's safe to promote it to an owning pointer. |
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 can probably be removed now, right? Since the unsafe code was moved into make_internal
?
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.
Yes. I tried multiple ways to rearrange the code and forgot to remove the comment on the latest one.
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.
make_internal should be an unsafe method. The safety is still unheld in this method.
crates/bevy_ptr/src/lib.rs
Outdated
@@ -397,13 +397,20 @@ impl<'a, T: ?Sized> From<&'a mut T> for PtrMut<'a> { | |||
} | |||
|
|||
impl<'a> OwningPtr<'a> { | |||
/// This exists mostly to reduce compile times; | |||
/// code is only duplicated per type, rather than per function called. | |||
fn make_internal<T>(temp: &mut ManuallyDrop<T>) -> OwningPtr<'_> { |
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 an unsafe method and have the same safety requirements as the promote method.
crates/bevy_ptr/src/lib.rs
Outdated
/// This exists mostly to reduce compile times; | ||
/// code is only duplicated per type, rather than per function called. | ||
fn make_internal<T>(temp: &mut ManuallyDrop<T>) -> OwningPtr<'_> { | ||
// SAFETY: The value behind the pointer will not get dropped or observed later, |
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.
// SAFETY: The value behind the pointer will not get dropped or observed later, | |
// SAFETY: Safety is unheld by the caller. |
The following line should be deleted.
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 get making the function itself unsafe, but what value does this safety comment add? If safety is unheld, shouldn't we not be using unsafe code?
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.
Oops typo. It should be upheld
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.
Oh okay that makes sense haha
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.
The caller lets go of all safety constraints and becomes free.
// SAFETY: The value behind the pointer will not get dropped or observed later, | ||
// so it's safe to promote it to an owning pointer. |
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.
make_internal should be an unsafe method. The safety is still unheld in this method.
I fixed |
Methodology
A good metric that correlates with compile time is the amount of code generated by the compiler itself; even if the end binary is exactly the same size, having more copies of the same code can really slow down compile time, since it has to figure out whether it needs to include them or not.
The measurement for this used was the
cargo-llvm-lines
crate which can measure which functions are generating the most lines of LLVM IR, which generally means more code compiled. The example compiled was thebreakout
game, to choose something that touches a decent portion of the engine.Solution
Based upon the measurements,
bevy_ptr::OwnedPtr::make
was taking up 4061 lines of LLVM IR in the example code. So, I separated part of this function into a less-monomorphised version to reduce the amount of generated code. This was by far the most lines emitted by any single function.Results
After this change, only 2560 lines are emitted, accounting for a 36% decrease. I tried timing the results and it seemed like it did decrease compile times a bit, but honestly, the data is really noisy and I can't be bothered to compile bevy for hours on end to get enough data points.
The tweak feels like an improvement, so, I'll offer it, however small.