-
-
Notifications
You must be signed in to change notification settings - Fork 10
Engine optimization PR guidelines #7
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,140 @@ | ||||||||||||||||||||||||||
.. _doc_optimization: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Optimization Guidelines | ||||||||||||||||||||||||||
======================= | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Introduction | ||||||||||||||||||||||||||
------------ | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
In general, the project prefers clear, simple code over highly optimized code, | ||||||||||||||||||||||||||
except in bottlenecks. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
However, optimization PRs are welcome provided they follow the guidelines below. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
.. note:: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
The project doesn't automatically accept all optimization PRs, even if they | ||||||||||||||||||||||||||
improve performance. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Choosing what to optimize | ||||||||||||||||||||||||||
------------------------- | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Choosing what to optimize can be extremely hard. Oftentimes code that looks like | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "It can be difficult to predict which code would benefit from optimization without using performance tools." ? I wouldn't say it is hard, just non-intuitive? |
||||||||||||||||||||||||||
it will run slow has no impact on overall performance and code that looks like | ||||||||||||||||||||||||||
it should be fast has a huge impact on performance. Further, reasoning about why | ||||||||||||||||||||||||||
a certain chunk of code is slow is impossible to do without detailed metrics | ||||||||||||||||||||||||||
(e.g. from a profiler or other performance analysis tool). | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Instructions on using some common profilers with Godot can be found `here | ||||||||||||||||||||||||||
<https://docs.godotengine.org/en/stable/engine_details/development/debugging/using_cpp_profilers.html>`_. | ||||||||||||||||||||||||||
Comment on lines
+28
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would put this, along with a broad overview of strengths / weaknesses, in a new section called "Tools for optimization". This would include:
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
As an example, you may optimize a chunk of code by caching intermediate values. | ||||||||||||||||||||||||||
However, if that code was slow due to memory constraints, caching the values and | ||||||||||||||||||||||||||
reading them later may be even slower than calculating them from scratch! | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Similarly, if the code is relatively slow but is only called rarely (for | ||||||||||||||||||||||||||
instance once on level load), then there is less potential benefit to speeding | ||||||||||||||||||||||||||
it up (unless you are specifically optimizing load times). | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Most optimizations involve making a tradeoff, so instead of randomly picking a | ||||||||||||||||||||||||||
part of the engine to optimize, we recommend that you use a profiler to identify | ||||||||||||||||||||||||||
bottlenecks **before** making any changes to ensure that your optimization will | ||||||||||||||||||||||||||
make a difference. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
If an area of the engine is not appearing in a profile, no matter how | ||||||||||||||||||||||||||
inefficient the code, then a PR is unlikely to be approved and merged. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
*(There are some exceptions, but this is generally the pattern.)* | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
When in doubt look for Github issues tagged with the `performance | ||||||||||||||||||||||||||
<https://github.com/godotengine/godot/issues?q=is%3Aissue%20state%3Aopen%20label%3Aperformance>`_ | ||||||||||||||||||||||||||
label to guide your optimization efforts. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
When assessing optimization opportunities we need to take into account: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Benefits | ||||||||||||||||||||||||||
~~~~~~~~ | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Is the optimization worth doing in this case? | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
- How often is this code called? | ||||||||||||||||||||||||||
- How much of a bottleneck is it to overall performance? | ||||||||||||||||||||||||||
- Does profiling show it to be a bottleneck? | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Costs | ||||||||||||||||||||||||||
~~~~~ | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
What are the downsides? | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
- Code complexity | ||||||||||||||||||||||||||
- Code readability | ||||||||||||||||||||||||||
- Maintenance burden | ||||||||||||||||||||||||||
- Constraining future changes | ||||||||||||||||||||||||||
- Risk of regressions | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Optimization process | ||||||||||||||||||||||||||
-------------------- | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Once you have decided what you should optimize. You should start by capturing a | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
baseline profile in your profiler of choice. Ensure you are running Godot's | ||||||||||||||||||||||||||
latest master branch and that you use an optimized build of Godot, since many | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
things that appear to run slow end up disappearing with optimizations enabled. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
By default Godot builds with optimizations enabled. See `the Godot build docs | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
<https://docs.godotengine.org/en/stable/engine_details/development/compiling/introduction_to_the_buildsystem.html#optimization-level>`_ | ||||||||||||||||||||||||||
for more information about build optimization settings. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
In some cases using a synthetic benchmark is also acceptable, but remember that | ||||||||||||||||||||||||||
Godot is a game engine. The golden standard is to test the performance of real | ||||||||||||||||||||||||||
games. Benchmarks can be helpful, but they can also be misleading as the | ||||||||||||||||||||||||||
performance of an algorithm given synthetic data may be different than the same | ||||||||||||||||||||||||||
algorithm running on real world data. | ||||||||||||||||||||||||||
Comment on lines
+89
to
+91
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Rather |
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Once you have your baseline profile/benchmark, make your changes and rebuild the | ||||||||||||||||||||||||||
engine with the exact same build settings you used before. Then profile again | ||||||||||||||||||||||||||
and compare the results. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
PR Requirements | ||||||||||||||||||||||||||
--------------- | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
When making an optimization PR you should: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
- Explain why you chose to optimize this code (e.g. include the profiling result, link the issue report, etc.). | ||||||||||||||||||||||||||
- Show that you improved the code either by profiling again, or running systematic benchmarks. | ||||||||||||||||||||||||||
- Test on multiple platforms where appropriate, especially mobile. | ||||||||||||||||||||||||||
- When micro-optimizing, show assembly before / after to confirm how the optimization is working. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather put this in the "tools" section mentioned above. Assembly is difficult to wrap your head around, and I wouldn't consider it a requirement if the code is provably way faster than before.
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
In particular you should be aware that for micro-optimizations, c++ compilers will often | ||||||||||||||||||||||||||
be aware of basic tricks and will already perform them in optimized builds. This is why | ||||||||||||||||||||||||||
showing before / after assembly can be important in these cases. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
The most important point to get across in your PR is to highlight the source of | ||||||||||||||||||||||||||
the performance issues, and have a clear explanation for how your PR fixes that | ||||||||||||||||||||||||||
performance issue. Your profiling/benchmarking results are proof that your | ||||||||||||||||||||||||||
optimization was successful. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Optimizing for best / worst cases | ||||||||||||||||||||||||||
--------------------------------- | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Often in optimization there can be situations where optimizing for a rare case slows a | ||||||||||||||||||||||||||
common case, or vice versa. Be aware that surprisingly often in games, optimizing for | ||||||||||||||||||||||||||
the worst case can be more important than optimizing for the best case, as worst cases | ||||||||||||||||||||||||||
can cause dropped frames. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
In situations where a PR is trading off speed for different paths, reviewers may have to | ||||||||||||||||||||||||||
decide whether a change is worth making. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
GPU Optimization | ||||||||||||||||||||||||||
---------------- | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
GPU optimization can be even more fraught with difficulty than CPU optimization, | ||||||||||||||||||||||||||
primarily because of the vast range of hardware the engine must run on, | ||||||||||||||||||||||||||
differences in drivers and behavior, and aggressive power saving modes that | ||||||||||||||||||||||||||
downclock the GPU when not under stress. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Even more so than for CPU work, it is essential to test GPU changes on mobile as well as | ||||||||||||||||||||||||||
desktop, and the more platforms, the better. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
In particular you should be aware that changes which increase performance on one platform | ||||||||||||||||||||||||||
can often reduce performance on another. | ||||||||||||||||||||||||||
|
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.