QMLアプリケーションのプロファイリング
QML Profiler を使えば、アプリケーションの典型的なパフォーマンス問題、例えば、遅い、反応が鈍い、ユーザーインターフェイスがもたつく、などの原因を見つけることができます。典型的な原因としては、JavaScriptの実行フレーム数が少なすぎることが挙げられます。すべてのJavaScriptはGUIスレッドが続行できるようになる前に戻らなければならず、GUIスレッドの準備ができていない場合、フレームは遅延するかドロップされます。
同様のパフォーマンス問題のもう一つの典型的な原因は、不可視アイテムの作成や更新で、GUIスレッドで時間がかかります。
ペイント・メソッドやシグナル・ハンドラなど、長時間実行されるC++関数のトリガーにもGUIスレッドで時間がかかりますが、QML Profiler 、C++コードのプロファイリングが行われないため、よりわかりにくくなっています。JavaScriptの過剰な使用を見つけるには、アニメーションやScene Graphイベントのフレームレートをチェックし、ギャップを探し、アプリケーションが期待通りに動作するかをチェックします。JavaScriptカテゴリには関数の実行時間が表示されますが、1フレームあたり16ミリ秒以下に抑えるようにしましょう。
不可視アイテムの処理に起因する問題を見つけるには、ドロップされたフレームを探し、フレームごとに更新される短いバインディングやシグナルハンドラを使いすぎていないかチェックします。また、Scene Graph のオーバードローを視覚化して、シーンのレイアウトをチェックし、画面の外にあったり、他の見える要素の下に隠れていたりして、ユーザーに決して見えないアイテムを見つけることができます。
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メモリマネージャのブロック割り当てを表示します。一般的に、メモリマネージャーは大きなメモリブロックを一括して予約し、後でアプリケーションに小分けして渡します。アプリケーションがあるサイズを超える単一のメモリブロックを要求した場合、メモリマネージャーはそれらを個別に割り当てます。これら2つの動作モードは、異なる色のイベントとして表示されている。2行目は、割り当てられたメモリの実際の使用量を表示します。これはアプリケーションが実際に要求したJavaScriptヒープの量です。 |
| Input Events | マウスとキーボードのイベントを表示します。 |
| Painting | 使用されていません。 |
| Animations | アクティブなアニメーションの量と、それらが実行されているフレームレートを表示します。レンダースレッドアニメーションは別の行に表示されます。 |
| Compiling | QMLファイルのコンパイルにかかった時間を表示します。 |
| Creating | シーン内のエレメントの作成に費やされた時間を表示します。エレメントの作成は2段階で行われます。第一段階は、子要素を含むデータ構造の作成です。第2段階は、完了コールバックを表します。しかし、すべての要素が完了コールバックをトリガーするわけではありません。ステージは、タイムラインでは別々のイベントとして表示されます。 |
| Binding | バインディングが評価される時間と、評価にかかる時間が表示されます。 |
| Handling Signal | シグナルが処理される時間と、処理にかかる時間が表示されます。 |
| JavaScript | バインディングとシグナルハンドラの背後にある実際のJavaScriptの実行に費やされた時間を表示します。バインディングの評価やシグナルの処理に使用しているすべてのJavaScript関数が一覧表示されます。 |
| Quick3D | Qt Quick 3Dフレームのレンダリングにかかった時間、フレームの準備と同期のタイミング情報、パーティクルシステムの更新時間とパーティクル更新回数、テクスチャとメッシュのメモリ割り当てとメモリ消費量が表示されます。 このイベントタイプは Qt 6.3 から利用可能です。 |
シーングラフイベントの分析
シーングラフカテゴリを理解するには、Qt Quick Scene GraphとQt Quick Scene Graph Default Renderer で、Qt Quick シーングラフがどのように動作するかについて詳しく説明しています。Scene Graph カテゴリーでは、以下のイベントが報告されます。すべてのイベントが、すべてのレンダー ループで生成されるわけではありません。Windows と Basic のレンダー ループでは、すべてが同じスレッドで実行され、GUI スレッドとレンダー スレッドの区別は無意味です。
環境変数QSG_RENDER_TIMINGを設定すると、プロファイリング対象のアプリケーションと似ているがわずかに異なるタイミングをテキストで出力します。以下にその違いを示します。
| イベントの種類 | スレッド | レンダー・ループの種類 | QSG_RENDER_TIMING 出力のラベル | 説明 |
|---|---|---|---|---|
| Polish | GUI | スレッド、ベーシック、ウィンドウズ | 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 | glyphs ... upload | グリフテクスチャのGPUへのアップロード。 |
| Texture Bind | レンダリング | スレッド、基本、Windows | plain texture ... bind | glBindTexturesを使用してOpenGLコンテキストでテクスチャをバインドする。 |
| Texture Convert | レンダリング | スレッド化、基本、Windows | plain texture ... convert | 画像をテクスチャとして使用するのに適したフォーマットに変換し、ダウンスケールする。 |
| Texture Swizzle | レンダリング | スレッド、基本、Windows | plain texture ... swizzle | 必要に応じてCPU上でテクスチャデータをスウィズリングする。 |
| Texture Upload | レンダー | スレッド化、基本、Windows | plain texture ... upload / atlastexture uploaded | テクスチャデータをGPUにアップロードする。 |
| Texture Mipmap | レンダリング | スレッド化、基本、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 | レンダー | フレームのレンダリング時間。描画コールの回数も表示される。 |
| Prepare Frame | レンダー | フレームの準備にかかる時間。リソースは準備段階で割り当てられ、ロードされる。シーンロード後の最初のフレームは、ほとんどのリソースがロードされるため、通常他のフレームよりも時間がかかります。 |
| Synchronize Frame | レンダー(Render | フレームの同期時間。Synchronizeは、フロントエンドからバックエンドの値の更新を行います。また、Qt Quick Scene Graph と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 | レンダリング | 単一の描画または計算呼び出しにかかった時間。重いGPU操作を特定するのに便利です。 |
| Render Pass | レンダー | レンダーパス全体にかかる時間。フレームバッファのグループ化されたレンダリング操作を表示します。 |
統計情報の表示
Statistics ビューには、各バインディング、作成、コンパイル、JavaScript、またはシグナル イベントがトリガーされた回数と、それにかかった平均時間が表示されます。どのイベントを最適化すべきかを知るには、統計情報を調べます。発生回数が多い場合は、イベントが不必要にトリガーされている可能性があります。発生時間の中央値、最長時間、最短時間を表示するには、コンテキストメニューからExtended Event Statistics を選択します。
イベントを選択すると、コード・エディタのソース・コードからそのイベントに移動します。

Callers とCallees は、イベント間の依存関係を表示します。Callers は、バインディングのトリガーとなる QML イベントをまとめたものです。Callees はバインディングのトリガーとなるQMLイベントをまとめています。バインディングを変更すると、どの QML イベントが影響を受けるかがわかります。
イベントを選択すると、コードエディターのソースコードからそのイベントに移動します。
Timeline ビューでイベントを選択すると、そのイベントに関する情報がStatistics とFlame Graph ビューに表示されます。
1つのビューまたは行の内容をクリップボードにコピーするには、コンテキストメニューからCopy Table またはCopy Row を選択します。
統計情報を炎グラフで表示する
Flame Graph ビューでは、QML と JavaScript の実行に関する統計的な概要がより簡潔に表示されます。Total Time のビューでは、横棒はすべての JavaScript と QML イベントの実行時間に対して、ある関数のすべての呼び出しにかかった時間を示しています。ネスティングは、どの関数が他の関数から呼び出されたかを示しています。

関数によって割り当てられたメモリの総量を表示するには、ドロップダウンメニューからMemory を選択します。
関数によって実行されたメモリ割り当ての数を表示するには、Allocations を選択します。
ビュー内の項目をダブルクリックすると、そのビューにズームインします。ビューの空の領域をダブルクリックすると、再びズームアウトします。
Timeline のビューとは異なり、Flame Graph のビューでは、QML や JavaScript が全く実行されていない時間スパンは表示されません。したがって、フレームごとの実行時間の分析には適していません。しかし、様々なQMLやJavaScriptのイベントの総影響を見ることは非常に簡単です。
Profile QML applications、How To: Analyze、Analyzer、Analyzing Codeも参照してください 。
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.