このページでは

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の実行状況のグラフィカルな表現と、記録されたすべてのイベントの要約表示が表示されます。

QML Profiler

タイムライン(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 UsageJavaScript メモリマネージャーによるブロックの割り当てを表示します。通常、メモリマネージャーは大きなメモリブロックを 1 つの塊として確保し、後でそれを小さな単位に分割してアプリケーションに割り当てます。アプリケーションが特定のサイズを超える単一のメモリブロックを要求した場合、メモリマネージャーはそれらを個別に割り当てます。これら 2 つの動作モードは、異なる色のイベントとして表示されます。 2行目には、割り当てられたメモリの実際の使用状況が表示されます。これは、アプリケーションが実際に要求したJavaScriptヒープの量です。
Input Eventsマウスおよびキーボードのイベントを表示します。
Painting未使用。
Animationsアクティブなアニメーションの数と、それらが実行されているフレームレートを表示します。レンダリングスレッドのアニメーションは別の行に表示されます。
CompilingQML ファイルのコンパイルに要した時間を表示します。
Creatingシーン内の要素の作成に費やされた時間を表示します。要素の作成は 2 段階で行われます。第 1 段階は、子要素を含むデータ構造の作成です。第 2 段階は、完了コールバックを表します。ただし、すべての要素が完了コールバックをトリガーするわけではありません。これらの段階は、タイムライン上で個別のイベントとして表示されます。
Bindingバインディングが評価された時刻と、その評価に要した時間を表示します。
Handling Signalシグナルが処理された時刻と、その処理に要した時間を表示します。
JavaScriptバインディングやシグナルハンドラの背後にある実際のJavaScriptの実行に要した時間を表示します。バインディングの評価やシグナルの処理に使用されている可能性のあるすべてのJavaScript関数が一覧表示されます。
Quick3DQt Quick の3Dフレームのレンダリングに費やされた時間、フレームの準備および同期に関するタイミング情報、パーティクルシステムの更新時間とパーティクル更新回数、ならびにテクスチャおよびメッシュのメモリ割り当てとメモリ消費量を表示します。

このイベントタイプは、Qt 6.3 以降で利用可能です。

シーングラフイベントの分析

シーングラフカテゴリを理解するには、Qt Quick 』の「シーングラフ」および『Qt Quick の「シーングラフのデフォルトレンダラー」で、Qt Quick のシーングラフの仕組みについて詳しく読んでください。以下のイベントは、Scene Graph カテゴリで報告されます。すべてのイベントがすべてのレンダリングループで生成されるわけではありません。WindowsおよびBasicのレンダリングループでは、すべてが同じスレッドで実行されるため、GUIスレッドとレンダリングスレッドの区別は意味をなしません。

環境変数 QSG_RENDER_TIMING を設定すると、プロファイル対象のアプリケーションから得られるタイミングと類似しているが、若干異なるタイミングのテキスト出力を取得できます。その違いは以下の通りです。

イベントの種類スレッドレンダリングループの種類QSG_RENDER_TIMING の出力におけるラベル説明
PolishGUIスレッド型、基本、WindowspolishQQuickItem::updatePolish() を使用してアイテムがレンダリングされる前の最終的な調整を行います。
GUI Thread WaitGUIスレッド対応lockQQuickWindow::afterAnimating() シグナルに接続されたスロットを実行し、GUI Thread Sync で同じミューテックスを待機する前に、レンダリングスレッドのミューテックスをロックします。これがRender Thread Sync のかなり前に開始される場合、GUI スレッドに余剰時間が生じ、その時間を追加の QML や JavaScript の実行に利用できます。
GUI Thread SyncGUIスレッド化blockedForSyncGUIスレッドがレンダリングスレッドを待機してブロックされている時間。
AnimationsGUIスレッド化、WindowsanimationsGUIスレッドでのアニメーションの進行。基本レンダリングループでは、アニメーションはレンダリングと同期して駆動されません。これが、基本レンダリングループを使用している際にアニメーションイベントが表示されない理由です。この場合のアニメーションのタイミングを確認するには、「Animations 」カテゴリをご覧ください。
Render Thread Syncレンダリングスレッド化、基本、WindowsFrame rendered ... syncQQuickItem::updatePaintNode() を使用して、QML 状態をシーングラフに同期させます。
Renderレンダリングスレッド化、基本、WindowsFrame rendered ... renderフレームのレンダリングに要した合計時間。これには、必要なすべてのデータの準備およびGPUへのアップロードが含まれます。これは総レンダリング時間です。以下の「Render Render の正味時間」と混同しないでください。
Swapレンダリングスレッド化、基本、WindowsFrame rendered ... swapレンダリング後のフレームのスワップ。
Render Preprocessレンダリングスレッド化、基本、Windowstime in renderer ... preprocessプリプロセスが必要なすべてのノードに対して、QSGNode::preprocess() を呼び出します。これは、Render ステップの一部です。
Render Updateレンダリングスレッド化、基本、Windowstime in renderer ... updatesシーングラフ内のすべてのノードを反復処理し、ジオメトリ、変形、不透明度、およびその他の状態を更新します。「Render Thread Sync 」ステージでは、各ノードはGUIスレッドからの状態情報に基づいて個別に更新されます。「Render Update 」では、すべてのノードが組み合わされて最終的なシーンが生成されます。これは、「Render 」ステップの一部です。
Render Bindレンダリングスレッド化、基本、Windowstime in renderer ... bindingOpenGLレンダリング用に正しいフレームバッファをバインドします。これは、大まかなRender ステップの一部です。
Render Renderレンダリングスレッド化、基本、Windowstime in renderer ... renderingOpenGLを介してすべてのデータをGPUに送信する実際の処理。これは、Render ステップの一部です。
Material Compileレンダリングスレッド化、基本、Windowsshader compiledGLSL シェーダープログラムのコンパイル。
Glyph Renderレンダリングスレッド化、基本、Windowsglyphs ... renderingフォントグリフをテクスチャにレンダリングします。
Glyph Uploadレンダリングスレッド化、基本、Windowsスレッド化、基本、Windowsglyphs ... uploadGPUへのグリフテクスチャのアップロード。
Texture Bindレンダリングスレッド化、基本、Windowsplain texture ... bindglBindTextures を使用して、OpenGL コンテキストにテクスチャをバインドします。
Texture Convertレンダリングスレッド化、基本、Windowsスレッド化、基本、Windowsplain texture ... convertフォーマットの変換と画像の縮小を行い、テクスチャとして使用できるようにする。
Texture Swizzleレンダリングスレッド対応、基本、Windowsスレッド対応、基本、Windowsplain texture ... swizzle必要に応じて、CPU上でテクスチャデータのスウィズリングを行います。
Texture Uploadレンダリングスレッド化、基本、Windowsplain texture ... upload / atlastexture uploadedテクスチャデータを GPU にアップロードします。
Texture Mipmapレンダリングスレッド化、基本、Windowsスレッド化、基本、Windowsplain texture ... mipmapGPU上でテクスチャのミップマッピングを行います。
Texture Deleteレンダリングスレッド化、基本、Windowsplain texture deleted不要になったテクスチャをGPUから削除します。

Qt Quick 3D イベントの分析

以下は、Qt Quick 3D のイベントの一覧です。レンダリングされる各フレームは、synchronize、prepare、render の各フェーズで構成されており、これらはこの順序で実行されます。synchronize はシーングラフの同期フェーズで発生し、prepare および render はシーングラフのレンダリングフェーズで発生します。

環境変数 `QSG_RENDERER_DEBUG=render ` を設定すると、さまざまなレンダリングパスごとのレンダリング呼び出し回数の追加テキスト出力が得られます。これらの呼び出し回数は、`Render Frame` イベント内で合計されます。

イベントタイプスレッド説明
Render FrameRenderフレームのレンダリング時間。また、ドローコールの数も表示されます。
Prepare Frameレンダリングフレームの準備に要した時間。リソースは準備フェーズで割り当てられ、読み込まれます。シーンの読み込み後の最初のフレームは、その時点でほとんどのリソースが読み込まれるため、通常、他のフレームよりも時間がかかります。
Synchronize Frameレンダリングフレームの同期時間。同期処理では、フロントエンドからバックエンドの値を更新します。また、Qt Quick のシーングラフとQt Quick 3D間で共有されるリソースの管理も行います。
Mesh Loadレンダリングメッシュの読み込み時間。すべてのメッシュの合計メモリ使用量を表示します。アンロードも表示します。
Custom Mesh Loadレンダリングカスタムメッシュの読み込み時間。すべてのメッシュの合計メモリ使用量を表示します。アンロードも表示します。
Texture Loadレンダリングテクスチャの読み込み時間。すべてのテクスチャの合計メモリ使用量を表示します。アンロードも表示します。
Generate Shaderレンダリングマテリアル用のシェーダーを生成する時間。
Load Shaderレンダリング組み込みシェーダーの読み込みにかかる時間。
Particle UpdateGUIパーティクルシステムの更新時間。更新されたパーティクルの数が表示されます。
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.