You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As an example, you may optimize a chunk of code by caching intermediate values.
34
31
However, if that code was slow due to memory constraints, caching the values and
35
32
reading them later may be even slower than calculating them from scratch!
@@ -96,6 +93,89 @@ Once you have your baseline profile/benchmark, make your changes and rebuild the
96
93
engine with the exact same build settings you used before. Then profile again
97
94
and compare the results.
98
95
96
+
High level vs low level optimization
97
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98
+
99
+
Optimizing code is different between "high level" and "low level" code.
100
+
101
+
"High level" code refers to code that heavily relies on frameworks and functions to
102
+
perform its task. This is most of Godot's code. In high level code, it is often most
103
+
important to avoid doing expensive work entirely. For example, by caching values
104
+
rather than making duplicate calls, by avoiding copying data unnecessarily, or by
105
+
replacing calls to expensive functions with calls to cheap functions.
106
+
107
+
In contrast, "low level" code refers to code that is working mostly with C++ language
108
+
features, such as primitive types and ``for``-loops. Optimizing low level code, often
109
+
referred to as "micro-optimization", can be more difficult, because it requires intimate
110
+
knowledge about C++ compiler intrinsics, as well as the inner workings of the CPU and RAM.
111
+
Furthermore, improving low level code is often unintuitive, and can reduce its readability
112
+
or robustness. We recommend against attempting to optimize low level code, unless you are
113
+
a very experienced low level C++ programmer.
114
+
115
+
.. note:::
116
+
117
+
For micro-optimizations, C++ compilers will often be aware of basic tricks and
118
+
will already perform them in optimized builds. Therefore, not all changes that
119
+
look like they should optimize the code will actually make the code faster.
120
+
121
+
Tools for optimization
122
+
~~~~~~~~~~~~~~~~~~~~~~
123
+
124
+
Profilers
125
+
^^^^^^^^^
126
+
127
+
Profilers are the most important tool for everyone optimizing code.
128
+
They show you which parts of the code are responsible for slow execution or heavy CPU load,
129
+
and are therefore excellent for identifying what needs to be optimized. Profilers can
130
+
also be used to identify whether the problem has been resolved, by profiling again after
131
+
making the changes. Godot has a built-in profiler, but it does not provide very detailed
132
+
information. Instead, use dedicated C++ profilers, which are
133
+
`explained in the Godot documentation <https://docs.godotengine.org/en/stable/engine_details/development/debugging/using_cpp_profilers.html>`__.
134
+
135
+
Benchmarks
136
+
^^^^^^^^^^
137
+
138
+
Benchmarks can be a great and simple tool to test the impact of your changes
139
+
of an isolated piece of code. However, benchmarks can be deceptive: It's easy to
140
+
accidentally write a benchmark that highlights a way in which performance was
141
+
improved, while ignoring other ways in which it was made worse.
142
+
143
+
To give one example: The most expensive operation of modern CPU programming is fetching RAM
144
+
that is not in the cache. Benchmarks often test code with values that are already in the cache
145
+
("hot" execution), but often, it is more important to optimize for the case where values are not
146
+
in the cache yet ("cold" execution).
147
+
148
+
Another common source of confusion is compiler optimization: One might write a benchmark that
149
+
looks like it should test the code faithfully, but the benchmarks show no improvement. This might
150
+
be indicative of a poorly written benchmark, which the compiler is able to "optimize away" by using
151
+
`constant folding <https://en.wikipedia.org/wiki/Constant_folding>`__ and other tricks.
152
+
For these, and other reasons, it is difficult to write good benchmarks. When using benchmarks to
153
+
test the performance of your code, always be aware of its potential caveats, and try to familiarize
154
+
yourself with good benchmark practices.
155
+
156
+
To start writing benchmarks in Godot, use the following GDScript code template:
157
+
158
+
.. code-block:: gdscript
159
+
160
+
var start = Time.get_ticks_msec()
161
+
var s := "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
162
+
for i in range(10000):
163
+
s.replace("e", "b") # Benchmarks the 'replace' function.
164
+
print(Time.get_ticks_msec() - start, "ms")
165
+
166
+
Alternatively, you can benchmark right from C++:
167
+
168
+
.. code-block:: cpp
169
+
170
+
String s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
171
+
172
+
auto t0 = std::chrono::high_resolution_clock::now();
173
+
for (int i = 0; i < 100000; i ++) {
174
+
String s1 = s.replace("e", "b"); // Benchmarks the 'replace' function.
175
+
}
176
+
auto t1 = std::chrono::high_resolution_clock::now();
0 commit comments