Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
プロファイラー
Godotからゲームを実行してプレイしてみましょう。楽しくて、機能が完成しつつあり、リリースが近づいていると感じます。
しかしその後、スキルツリーを開くとコードに何かが引っかかり、スキルツリーが停止してしまいます。スキルツリーがスライドショーのようにスクロールするのは受け入れられません。何が悪かったのでしょう? スキルツリー要素の位置? UI? それともレンダリング?
すべてを最適化してゲームを繰り返し実行することもできますが、重い箇所の可能性を絞り込んでいくほうが賢いです。 そのためにGodotのプロファイラーを使用します。
プロファイラーの概要
プロファイラーを開くには、デバッガー パネルを開いて、プロファイラー タブをクリックします。
プロファイリングはパフォーマンスを重視するため、Godotのプロファイラは自動的には実行されません。ゲーム内で起こっているすべての事象を継続的に測定し、デバッガーに報告する必要があるため、デフォルトではオフになっています。
To begin profiling, run your game then focus back on the editor. Click on the Start button in the top-left corner of the Profiler tab. You can also check Autostart, which will make the profiler automatically start when the project is run the next time. Note that the Autostart checkbox's state is not preserved across editor sessions.
注釈
プロファイラーは現在、C#スクリプトをサポートしていません。 C#スクリプトはGodotサポートプラグインを備えた JetBrains Rider および JetBrains dotTrace を使用してプロファイリングできます。
クリア ボタンをクリックすると、いつでもデータをクリアできます。 測定 ドロップダウンメニューを使用して、測定するデータの種類を変更します。それに応じて測定パネルとグラフが更新されます。
測定データ
プロファイラーのインターフェースは2つに分かれています。左側に機能のリスト、右側にパフォーマンスのグラフがあります。
主な測定値は、フレーム時間、物理フレーム、待機時間、物理時間です。
Frame Time は物理からレンダリングまで、画像全体のすべてのロジックをGodotが実行するのにかかる時間です。
Physics Frame Time はGodotが物理更新の間に割り当てた時間です。理想的なシナリオではフレーム時間は選択したものになります。デフォルトでは 16.66 ミリ秒で、これは 60FPS に相当します。これは周囲のあらゆるものに使用できる参照フレームです。
Idle time is the time Godot took to update logic other than physics, such as code that lives in _process() or timers and cameras set to update on Idle.
Physics time is the time Godot took to update physics tasks, like _physics_process() and built-in nodes set to update on Physics.
注釈
**Frame Time**にはレンダリング時間が含まれます。ゲーム内で謎のラグの急増を見つけたものの、物理演算とスクリプトはすべて高速に実行されているとするとき、遅延はパーティクルの出現または視覚効果が原因である可能性があります!
デフォルトではGodotはフレーム時間と物理時間をチェックします。これにより設定された物理FPSと比較して各フレームにかかる時間の概要が得られます。左側のチェックボックスをクリックすると、機能のオンとオフを切り替えることができます。リストの下に進むとコードが表示されるスクリプト関数に到達する前に、Physics 2D、Physics 3D、Audioなどの他の機能も表示されます。
グラフをクリックすると、左側に表示されるフレームの情報が変わります。右上には表示しているフレームをより細かく手動で調整できるフレームカウンターもあります。
測定範囲と測定ウィンドウ
測定 のドロップダウンメニューを開くと、表示する測定値の種類を変更できます。デフォルトではフレームを通過するのにかかる時間をミリ秒単位でリストします。平均時間は特定の関数が複数回呼び出されたときにかかった平均時間です。たとえば、5回の実行に 0.05 ミリ秒かかった関数の平均時間は 0.01 ミリ秒になります。
正確なミリ秒数が重要ではなく、フレームの残りの部分に対する時間の割合を確認したい場合は、パーセンテージ測定を使用します。 フレーム%はフレーム時間に相対し、物理フレーム%は物理時間に相対します。
最後のオプションは時間の範囲です。 **包括**はネストされた関数呼び出しを含む関数にかかった時間を測定します。例えば:
get_neighbors, find_nearest_neighbor, and move_subject all took a lot of
time. You could be fooled into thinking that this is because all three of them
are slow.
ただし 自己 に変更すると、Godotは関数呼び出しの関係を考慮せずに、その関数本体で費やした時間を測定します。
You can see that get_neighbors and move_subject have lost a lot of their
importance. In effect, that means that get_neighbors and move_subject have
spent more time waiting for some other function call to finish than not, and
find_nearest_neighbor is actually slow.
プロファイラーを使用した遅いコードのデバッグ
プロファイラーを使用して遅いコードを見つけるには、結局のところゲームを実行し、描画されるパフォーマンス グラフを観察することになります。フレーム時間内に許容できないスパイクが発生した場合は、グラフをクリックしてゲームを一時停止し、 "フレーム #" をスパイクの開始位置まで絞り込むことができます。根本原因を見つけるにはフレームと関数の間を行ったり来たりする必要がある場合があります。
時間がかかる関数を見つけるためには、 Script Functionsの下のいくつかの関数のチェックボックスをオンにします。これを使用してレビュー、最適化する必要がある関数を見つけます。
手動で測定する (マイクロ秒単位)
If your function is complex, it could be challenging to figure out which part
needs optimization. Is it your math or the way you access other pieces of data
to do the math with? Is it the for loop? The if statements?
You can narrow down the measurement by manually counting ticks as the code runs
with some temporary functions. The two functions are part of the Time class
object. They are get_ticks_msec() and
get_ticks_usec(). The first measures in
milliseconds (1,000 per second), and the second measures in microseconds
(1,000,000 per second).
どちらもそれぞれの時間枠でゲーム エンジンが開始されてからの時間を返します。
マイクロ秒の開始カウントと終了カウントを使用してコード部分を囲む場合、2つの違いはそのコード部分の実行にかかった時間になります。
# Measuring the time it takes for worker_function() to run
var start = Time.get_ticks_usec()
worker_function()
var end = Time.get_ticks_usec()
var worker_time = (end-start)/1000000.0
# Measuring the time spent running a calculation over each element of an array
start = Time.get_ticks_usec()
for calc in calculations:
result = pow(2, calc.power) * calc.product
end = Time.get_ticks_usec()
var loop_time = (end-start)/1000000.0
print("Worker time: %s\nLoop time: %s" % [worker_time, loop_time])
経験豊富なプログラマになると、このテクニックは必要なくなります。実行中のプログラムのどの部分が遅いのかがわかり始めます。ループや分岐が遅くなる可能性があることは経験から得られるものであり、測定や調査を行うことで経験を積みます。
ただしプロファイラーとティック関数の間には、コードのどの部分を最適化する必要があるかを見つけるのに十分な情報が必要です。