QMLアプリケーションのプロファイリング
QML Profiler を使用すると、動作の遅延や応答の遅れ、ユーザーインターフェースのカクつきなど、アプリケーションで発生する典型的なパフォーマンス問題の原因を特定できます。典型的な原因としては、フレーム数が少なすぎる中で過剰なJavaScriptが実行されていることが挙げられます。GUIスレッドが処理を続行するには、すべてのJavaScriptが実行完了する必要があります。GUIスレッドの準備が整っていない場合、フレームの表示が遅れたり、スキップされたりします。
同様のパフォーマンス問題のもう一つの典型的な原因は、非表示のアイテムの作成や更新であり、これにはGUIスレッドで時間がかかります。
ペイントメソッドやシグナルハンドラなど、実行に時間がかかるC++関数を呼び出すことも、GUIスレッドで時間を消費しますが、QML Profiler ではC++コードのプロファイリングが行われないため、この問題を発見するのはより困難です。
JavaScriptの過剰な使用を確認するには、アニメーションやシーングラフイベントのフレームレートを確認し、ギャップがないか調べ、アプリケーションが期待どおりに動作しているかを確認してください。「JavaScript」カテゴリには関数の実行時間が表示されますが、これを1フレームあたり16ミリ秒未満に抑えるよう努めてください。
非表示のアイテムの処理に起因する問題を見つけるには、フレームのドロップがないか確認し、フレームごとに更新される短いバインディングやシグナルハンドラを過剰に使用していないか確認してください。また、シーングラフのオーバードローを可視化してシーンのレイアウトを確認し、画面外にある、あるいは他の表示されている要素の下に隠れてユーザーには決して表示されないアイテムを見つけることもできます。
JavaScriptが実行されていないにもかかわらずフレームがドロップされ、タイムラインに原因不明の大きな空白がある場合は、カスタムQQuickItem の実装を確認してください。Valgrind Callgrindやその他の汎用プロファイラを使用して、C++コードを分析できます。
フルスタックトレースを使用すると、最上位の QML や JavaScript から C++ を経て、カーネル空間に至るまでを追跡できます。収集したデータは、Chrome Trace Format Viewer で確認できます。
収集したデータの分析
Timeline ビューには、QMLおよびJavaScriptの実行状況のグラフィカルな表現と、記録されたすべてのイベントの要約表示が表示されます。

タイムライン(6)の各行は、記録された QML イベントの種類を表しています。行上のイベントにカーソルを合わせると、そのイベントの所要時間や、ソース内のどの箇所で呼び出されているかを確認できます。イベントが選択されているときのみ情報を表示するには、「View Event Information on Mouseover 」(4)をオフにしてください。
アウトライン (10) には、データが収集された期間の概要が表示されます。ズーム範囲 (8) をドラッグするか、アウトラインをクリックしてアウトライン上を移動できます。また、「Jump to Previous Event 」と「Jump to Next Event 」 (1) を選択することで、イベント間を移動することもできます。
「Show Zoom Slider 」(2)を選択すると、ズームレベルを設定するスライダーが表示されます。ズームハンドル(9)をドラッグしても調整できます。デフォルトのズームレベルにリセットするには、タイムラインを右クリックしてコンテキストメニューを開き、「Reset Zoom 」を選択します。
タイムラインに垂直方向の目盛り線 (5) を追加するには、タイムラインの目盛りを選択します。
イベント範囲の選択
イベント範囲 (7) を選択すると、イベントのフレームレートを表示し、類似したイベントのフレームレートと比較できます。 「Select Range 」(3)を選択して、選択ツールを有効にします。次に、タイムラインをクリックしてイベント範囲の開始点を指定します。選択ハンドルをドラッグして範囲の終了点を定義します。範囲の長さが、そのイベントのフレームレートを示します。
2つの連続するイベント間の遅延を測定するには、最初のイベントの終了位置と2番目のイベントの開始位置の間にイベント範囲を設定します。「Duration 」フィールドには、イベント間の遅延がミリ秒単位で表示されます。
イベント範囲を拡大表示するには、その範囲をダブルクリックします。
「Timeline 」、「Statistics 」、および「Flame Graph 」ビューで現在の範囲を絞り込むには、範囲を右クリックして「Analyze Current Range 」を選択します。全範囲に戻すには、コンテキストメニューから「Analyze Full Range 」を選択します。
イベント範囲を削除するには、「Selection 」ダイアログを閉じます。
データの理解
通常、タイムラインビューのイベントは、QML または JavaScript の実行にかかった時間を示しています。イベントの上にマウスを合わせると、詳細が表示されます。ほとんどのイベントには、ソースコード内の位置、実行時間、およびソースコード自体の関連部分が含まれています。
イベントを選択すると、コードエディタ内のカーソルが、そのイベントに関連付けられているコードの部分に移動します。
以下の種類のイベントが、タイムラインビューの 1 行または複数行に表示されます。
| イベントカテゴリ | 説明 |
|---|---|
| Pixmap Cache | キャッシュされたピクマップデータの総量をピクセル単位で表示します。さらに、読み込まれている各画像について、ファイル名やサイズなどの詳細情報を含む個別のイベントが表示されます。 |
| Scene Graph | シーングラフフレームがレンダリングされた時刻と、その実行に要した各段階に関する追加のタイミング情報を表示します。 |
| Memory Usage | JavaScript メモリマネージャーによるブロックの割り当てを表示します。通常、メモリマネージャーは大きなメモリブロックを 1 つの塊として確保し、後でそれを小さな単位に分割してアプリケーションに割り当てます。アプリケーションが特定のサイズを超える単一のメモリブロックを要求した場合、メモリマネージャーはそれらを個別に割り当てます。これら 2 つの動作モードは、異なる色のイベントとして表示されます。 2行目には、割り当てられたメモリの実際の使用状況が表示されます。これは、アプリケーションが実際に要求したJavaScriptヒープの量です。 |
| Input Events | マウスおよびキーボードのイベントを表示します。 |
| Painting | 未使用。 |
| Animations | アクティブなアニメーションの数と、それらが実行されているフレームレートを表示します。レンダリングスレッドのアニメーションは別の行に表示されます。 |
| Compiling | QML ファイルのコンパイルに要した時間を表示します。 |
| Creating | シーン内の要素の作成に費やされた時間を表示します。要素の作成は 2 段階で行われます。第 1 段階は、子要素を含むデータ構造の作成です。第 2 段階は、完了コールバックを表します。ただし、すべての要素が完了コールバックをトリガーするわけではありません。これらの段階は、タイムライン上で個別のイベントとして表示されます。 |
| Binding | バインディングが評価された時刻と、その評価に要した時間を表示します。 |
| Handling Signal | シグナルが処理された時刻と、その処理に要した時間を表示します。 |
| JavaScript | バインディングやシグナルハンドラの背後にある実際のJavaScriptの実行に要した時間を表示します。バインディングの評価やシグナルの処理に使用されている可能性のあるすべてのJavaScript関数が一覧表示されます。 |
| Quick3D | Qt Quick の3Dフレームのレンダリングに費やされた時間、フレームの準備および同期に関するタイミング情報、パーティクルシステムの更新時間とパーティクル更新回数、ならびにテクスチャおよびメッシュのメモリ割り当てとメモリ消費量を表示します。 このイベントタイプは、Qt 6.3 以降で利用可能です。 |
シーングラフイベントの分析
シーングラフカテゴリを理解するには、『Qt Quick 』の「シーングラフ」および『Qt Quick 』の「シーングラフのデフォルトレンダラー」で、Qt Quick のシーングラフの仕組みについて詳しく読んでください。以下のイベントは、Scene Graph カテゴリで報告されます。すべてのイベントがすべてのレンダリングループで生成されるわけではありません。WindowsおよびBasicのレンダリングループでは、すべてが同じスレッドで実行されるため、GUIスレッドとレンダリングスレッドの区別は意味をなしません。
環境変数 QSG_RENDER_TIMING を設定すると、プロファイル対象のアプリケーションから得られるタイミングと類似しているが、若干異なるタイミングのテキスト出力を取得できます。その違いは以下の通りです。
| イベントの種類 | スレッド | レンダリングループの種類 | QSG_RENDER_TIMING の出力におけるラベル | 説明 |
|---|---|---|---|---|
| Polish | GUI | スレッド型、基本、Windows | polish | QQuickItem::updatePolish() を使用してアイテムがレンダリングされる前の最終的な調整を行います。 |
| GUI Thread Wait | GUI | スレッド対応 | lock | QQuickWindow::afterAnimating() シグナルに接続されたスロットを実行し、GUI Thread Sync で同じミューテックスを待機する前に、レンダリングスレッドのミューテックスをロックします。これがRender Thread Sync のかなり前に開始される場合、GUI スレッドに余剰時間が生じ、その時間を追加の QML や JavaScript の実行に利用できます。 |
| GUI Thread Sync | GUI | スレッド化 | blockedForSync | GUIスレッドがレンダリングスレッドを待機してブロックされている時間。 |
| Animations | GUI | スレッド化、Windows | animations | GUIスレッドでのアニメーションの進行。基本レンダリングループでは、アニメーションはレンダリングと同期して駆動されません。これが、基本レンダリングループを使用している際にアニメーションイベントが表示されない理由です。この場合のアニメーションのタイミングを確認するには、「Animations 」カテゴリをご覧ください。 |
| Render Thread Sync | レンダリング | スレッド化、基本、Windows | Frame rendered ... sync | QQuickItem::updatePaintNode() を使用して、QML 状態をシーングラフに同期させます。 |
| Render | レンダリング | スレッド化、基本、Windows | Frame rendered ... render | フレームのレンダリングに要した合計時間。これには、必要なすべてのデータの準備およびGPUへのアップロードが含まれます。これは総レンダリング時間です。以下の「Render Render の正味時間」と混同しないでください。 |
| Swap | レンダリング | スレッド化、基本、Windows | Frame rendered ... swap | レンダリング後のフレームのスワップ。 |
| Render Preprocess | レンダリング | スレッド化、基本、Windows | time in renderer ... preprocess | プリプロセスが必要なすべてのノードに対して、QSGNode::preprocess() を呼び出します。これは、Render ステップの一部です。 |
| Render Update | レンダリング | スレッド化、基本、Windows | time in renderer ... updates | シーングラフ内のすべてのノードを反復処理し、ジオメトリ、変形、不透明度、およびその他の状態を更新します。「Render Thread Sync 」ステージでは、各ノードはGUIスレッドからの状態情報に基づいて個別に更新されます。「Render Update 」では、すべてのノードが組み合わされて最終的なシーンが生成されます。これは、「Render 」ステップの一部です。 |
| Render Bind | レンダリング | スレッド化、基本、Windows | time in renderer ... binding | OpenGLレンダリング用に正しいフレームバッファをバインドします。これは、大まかなRender ステップの一部です。 |
| Render Render | レンダリング | スレッド化、基本、Windows | time in renderer ... rendering | OpenGLを介してすべてのデータをGPUに送信する実際の処理。これは、Render ステップの一部です。 |
| Material Compile | レンダリング | スレッド化、基本、Windows | shader compiled | GLSL シェーダープログラムのコンパイル。 |
| Glyph Render | レンダリング | スレッド化、基本、Windows | glyphs ... rendering | フォントグリフをテクスチャにレンダリングします。 |
| Glyph Upload | レンダリングスレッド化、基本、Windows | スレッド化、基本、Windows | glyphs ... upload | GPUへのグリフテクスチャのアップロード。 |
| Texture Bind | レンダリング | スレッド化、基本、Windows | plain texture ... bind | glBindTextures を使用して、OpenGL コンテキストにテクスチャをバインドします。 |
| Texture Convert | レンダリングスレッド化、基本、Windows | スレッド化、基本、Windows | plain texture ... convert | フォーマットの変換と画像の縮小を行い、テクスチャとして使用できるようにする。 |
| Texture Swizzle | レンダリングスレッド対応、基本、Windows | スレッド対応、基本、Windows | plain texture ... swizzle | 必要に応じて、CPU上でテクスチャデータのスウィズリングを行います。 |
| Texture Upload | レンダリング | スレッド化、基本、Windows | plain texture ... upload / atlastexture uploaded | テクスチャデータを GPU にアップロードします。 |
| Texture Mipmap | レンダリングスレッド化、基本、Windows | スレッド化、基本、Windows | plain texture ... mipmap | GPU上でテクスチャのミップマッピングを行います。 |
| Texture Delete | レンダリング | スレッド化、基本、Windows | plain texture deleted | 不要になったテクスチャをGPUから削除します。 |
Qt Quick 3D イベントの分析
以下は、Qt Quick 3D のイベントの一覧です。レンダリングされる各フレームは、synchronize、prepare、render の各フェーズで構成されており、これらはこの順序で実行されます。synchronize はシーングラフの同期フェーズで発生し、prepare および render はシーングラフのレンダリングフェーズで発生します。
環境変数 `QSG_RENDERER_DEBUG=render ` を設定すると、さまざまなレンダリングパスごとのレンダリング呼び出し回数の追加テキスト出力が得られます。これらの呼び出し回数は、`Render Frame` イベント内で合計されます。
| イベントタイプ | スレッド | 説明 |
|---|---|---|
| Render Frame | Render | フレームのレンダリング時間。また、ドローコールの数も表示されます。 |
| Prepare Frame | レンダリング | フレームの準備に要した時間。リソースは準備フェーズで割り当てられ、読み込まれます。シーンの読み込み後の最初のフレームは、その時点でほとんどのリソースが読み込まれるため、通常、他のフレームよりも時間がかかります。 |
| Synchronize Frame | レンダリング | フレームの同期時間。同期処理では、フロントエンドからバックエンドの値を更新します。また、Qt Quick のシーングラフとQt Quick 3D間で共有されるリソースの管理も行います。 |
| Mesh Load | レンダリング | メッシュの読み込み時間。すべてのメッシュの合計メモリ使用量を表示します。アンロードも表示します。 |
| Custom Mesh Load | レンダリング | カスタムメッシュの読み込み時間。すべてのメッシュの合計メモリ使用量を表示します。アンロードも表示します。 |
| Texture Load | レンダリング | テクスチャの読み込み時間。すべてのテクスチャの合計メモリ使用量を表示します。アンロードも表示します。 |
| Generate Shader | レンダリング | マテリアル用のシェーダーを生成する時間。 |
| Load Shader | レンダリング | 組み込みシェーダーの読み込みにかかる時間。 |
| Particle Update | GUI | パーティクルシステムの更新時間。更新されたパーティクルの数が表示されます。 |
| Mesh Memory Consumption | レンダリング | メッシュの総メモリ使用量をバーグラフで表示します。 |
| Texture Memory Consumption | レンダリング | テクスチャの総メモリ使用量を棒グラフで表示します。 |
| Render Call | レンダリング | 1回の描画または演算呼び出しにかかる時間。負荷の高いGPU操作を特定するのに役立ちます。 |
| Render Pass | レンダリング | レンダリングパス全体にかかる時間。フレームバッファに対するレンダリング操作をグループ化して表示します。 |
統計情報の表示
「Statistics 」ビューには、各バインディング、作成、コンパイル、JavaScript、またはシグナルイベントがトリガーされた回数と、その平均所要時間が表示されます。統計情報を確認して、どのイベントを最適化すべきかを把握してください。発生回数が多い場合は、そのイベントが不必要にトリガーされている可能性があります。 発生回数の中央値、最長時間、最短時間を表示するには、コンテキストメニューから「Extended Event Statistics 」を選択します。
イベントを選択すると、コードエディタ内のソースコードのその箇所に移動します。

Callers また、「Callees 」は、イベント間の依存関係を表示します。これらを使用することで、アプリケーションの内部機能を調査できます。「Callers 」は、バインディングをトリガーするQMLイベントをまとめます。これにより、バインディングの変更の原因がわかります。「Callees 」は、バインディングがトリガーするQMLイベントをまとめます。これにより、バインディングを変更した場合にどのQMLイベントが影響を受けるかがわかります。
イベントを選択すると、コードエディタ内のソースコードのその位置に移動します。
「Timeline 」ビューでイベントを選択すると、そのイベントに関する情報が「Statistics 」および「Flame Graph 」ビューに表示されます。
あるビューまたは行の内容をクリップボードにコピーするには、コンテキストメニューから [Copy Table ] または [Copy Row ] を選択します。
統計情報をフレームグラフとして可視化
「Flame Graph 」ビューでは、QML および JavaScript の実行に関する統計情報をより簡潔に概要表示します。「Total Time 」ビューでは、水平バーが、特定の関数のすべての呼び出しに要した合計時間を、すべての JavaScript および QML イベントの総実行時間に対する割合として示しています。ネスト構造は、どの関数がどの関数によって呼び出されたかを示しています。

関数によって割り当てられたメモリの合計量を確認するには、ドロップダウンメニューから「Memory 」を選択します。
関数によって実行されたメモリ割り当ての回数を表示するには、[Allocations] を選択します。
ビュー内の項目をダブルクリックすると、その項目にズームインします。ビュー内の何もない領域をダブルクリックすると、再びズームアウトします。
「Timeline 」ビューとは異なり、「Flame Graph 」ビューには、QML や JavaScript がまったく実行されていない時間範囲は表示されません。したがって、フレームごとの実行時間を分析するには適していません。しかし、さまざまな QML および JavaScript イベントが全体に与える影響を把握するには非常に便利です。
「手順:分析」、「アナライザ」、「コードの分析」、「QMLアプリケーションのプロファイリング」も参照してください 。
Copyright © The Qt Company Ltd. and other contributors. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.