-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Change bevy_math
to use inline
instead of inline(always)
#20887
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
base: main
Are you sure you want to change the base?
Conversation
That's older than that: https://discord.com/channels/691052431525675048/692572690833473578/796109019398930453 Cart guidelines were to |
I'm not sure if that discussion is saying "always use For what it's worth, I should have phrased my comment differently. I didn't mean to imply that there had been no discussion - just that I failed to find it. |
It would be helpful to show a benchmark run before and after, since this PR is changing code specifically related to performance, have you checked the git blames on those inline attributes to make sure there wasn't a good reason? Another way to think of For example, It's hard to think of a scenario where you want something as simple as field dereferencing to be behind a function call, and this PR includes changes to remove #[inline(always)]
fn center(&self) -> Self::Translation {
self.center
} Broadly I think your reasoning isn't unsound, and there's likely quite a few places the inline(always) could be relaxed to just inline or none at all. However this PR is changing hundreds of functions without showing due diligence, there is a lot of assumptions being made here with no numbers to show. It would be appreciated to show benchmark run before/after, at least for math heavy stuff. And potentially compiled binary sizes? |
I mentioned benchmarks and binary sizes only briefly as the TLDR was "no difference in optimised builds". Maybe I should have expanded a bit:
This is far from conclusive - they're microbenchmarks and On I've done a few more checks since filing the PR:
That's suggestive but still not conclusive. So I think there's another way to frame my argument - what if the situation was reversed? What if For this PR, there's one case I'm ambivalent about: the libm wrapper calls in |
Did some more testing around optimise for size in case it's useful:
|
Thanks for providing more info, appreciated!
It's a good point. |
Objective
Move
bevy_math
closer to recommended inlining practices, and avoid problems with debuggers and optimising for size.Background
Some
bevy_math
modules apply#[inline(always)]
to almost every function. This has downsides for some users - it can prevent optimising for size, and can stop the debugger from stepping into functions.I can't find any source that advises
inline(always)
by default - the most common advice is "use rarely and only after profiling" (example: std lib guide). I've poked around thebevy_math
history but couldn't find anything that explains whyinline(always)
was chosen.Solution
This PR changes all instances of
#[inline(always)]
to#[inline]
.The change is very unlikely to make any difference in optimised builds - almost all the functions are tiny so they're going to be inlined either way. Benchmarks showed no difference.
The change can sometimes decrease performance in
opt-level = 0
builds - one math heavy microbenchmark took a -10% hit. But this is arguably the right trade-off if it lets the user step into functions in the debugger.Overall, I think this is the safer default for most users.
inline(always)
has several concrete downsides, whileinline
has some trade-offs but no clear downsides.The change also adds a new
bevy_math
benchmark with a mix of small and large functions. Not sure if this is justified.Alternatives
The change could have been taken further.
#[inline]
from heftier functions likeBoundingSphere::from_point_cloud
.#[inline]
entirely.Testing
Also:
alien_cake_addict
with various optimisation levels to check there weren't major differences in size.More details in comment 1, comment 2.