ProfilingManager を使用して複数のトレースを収集すると、それらを個別に調べてパフォーマンスの問題を見つけることは現実的ではなくなります。一括トレース分析を使用すると、トレースのデータセットに対して同時にクエリを実行して、次のことができます。
- 一般的なパフォーマンスの低下を特定する。
- 統計分布(P50、P90、P99 レイテンシなど)を計算する。
- 複数のトレースにわたるパターンを見つける。
- 外れ値トレースを見つけて、パフォーマンスの問題を把握してデバッグします。
このセクションでは、Perfetto Python Batch Trace Processor を使用して、ローカルに保存された一連のトレース全体で起動指標を分析し、外れ値トレースを特定して詳細な分析を行う方法について説明します。
クエリを設計する
まず、比較する指標を抽出する PerfettoSQL クエリを作成します。次の例では、図 1 に示すように、activityStart から最初のレンダリング フレーム(Choreographer#doFrame)までのアプリ制御の起動レイテンシを測定します。
activityStart から生成された最初のフレームまでのトレース セクション。CREATE OR REPLACE PERFETTO FUNCTION find_slices(pattern STRING) RETURNS
TABLE (name STRING, ts LONG, dur LONG) AS
SELECT name,ts,dur FROM slice WHERE name GLOB $pattern;
CREATE OR REPLACE PERFETTO FUNCTION generate_start_to_end_slices(startSlicePattern STRING, endSlicePattern STRING, inclusive BOOL) RETURNS
TABLE(name STRING, ts LONG, dur LONG) AS
SELECT name, ts, MIN(startToEndDur) as dur
FROM
(SELECT S.name as name, S.ts as ts, E.ts + IIF($inclusive, E.dur, 0) - S.ts as startToEndDur
FROM find_slices($startSlicePattern) as S CROSS JOIN find_slices($endSlicePattern) as E
WHERE startToEndDur > 0)
GROUP BY name, ts;
SELECT ts,name,dur from generate_start_to_end_slices('activityStart','*Choreographer#doFrame [0-9]*', true)
Perfetto UI 内でクエリを実行し、クエリ結果を使用してデバッグトラックを生成し(図 2)、タイムライン内で可視化できます(図 3)。
Python 環境を設定する
ローカルマシンに Python をインストールし、必要なライブラリをインストールします。
pip install perfetto pandas plotly
一括トレース分析スクリプトを作成する
次のサンプル スクリプトは、Perfetto の Python BatchTraceProcessor を使用して、複数のトレースでクエリを実行します。
from perfetto.batch_trace_processor import BatchTraceProcessor
import glob
import plotly.express as px
# Collect all trace files in the local directory
traces = glob.glob('*.perfetto-trace')
if not traces:
print("No .perfetto-trace files found in the current directory.")
exit(1)
if __name__ == '__main__':
# Process all traces in parallel to aggregate metrics across runs
with BatchTraceProcessor(traces) as btp:
query = """
CREATE OR REPLACE PERFETTO FUNCTION find_slices(pattern STRING) RETURNS
TABLE (name STRING, ts LONG, dur LONG) AS
SELECT name,ts,dur FROM slice WHERE name GLOB $pattern;
CREATE OR REPLACE PERFETTO FUNCTION generate_start_to_end_slices(startSlicePattern STRING, endSlicePattern STRING, inclusive BOOL) RETURNS
TABLE(name STRING, ts LONG, dur LONG) AS
SELECT name, ts, MIN(startToEndDur) as dur
FROM
(SELECT S.name as name, S.ts as ts, E.ts + IIF($inclusive, E.dur, 0) - S.ts as startToEndDur
FROM find_slices($startSlicePattern) as S CROSS JOIN find_slices($endSlicePattern) as E
WHERE startToEndDur > 0)
GROUP BY name, ts;
SELECT ts,name,dur / 1000000 as dur_ms from generate_start_to_end_slices('activityStart','*Choreographer#doFrame [0-9]*', true)
"""
df = btp.query_and_flatten(query)
# Plot the distribution of startup times, tracking trace file paths on
# hover
violin = px.violin(df, x='dur_ms', hover_data='_path', title='startup time', points='all')
violin.show()
スクリプトについて
Python スクリプトを実行すると、次の処理が行われます。
- このスクリプトは、ローカル ディレクトリで
.perfetto-traceという接尾辞が付いたすべての Perfetto トレースを検索し、それらを分析のソース トレースとして使用します。 - このクエリは、
activityStartトレース スライスからアプリによって生成された最初のフレームまでの時間に対応する起動時間のサブセットを計算する一括トレースクエリを実行します。 - バイオリン プロットを使用してレイテンシをミリ秒単位でプロットし、起動時間の分布を可視化します。
結果を解釈する
スクリプトを実行すると、2 つの異なるレイテンシ ピークを持つバイモーダル分布を示すバイオリン プロットが生成されます(図 4)。プロット内の個々のデータポイントにカーソルを合わせると、_path ファイル名を確認し、各ピークのトレースを比較できます(図 5)。
- 高レイテンシ トレース(右側のピーク): Perfetto UI でこのグループのトレースを開くと、起動中に追加の
MyFlaggedFeatureスライスが実行されていることがわかります(図 6)。 - 低レイテンシのトレース(左側のピーク): 高速なグループからトレースを開くと、
MyFlaggedFeatureが存在しないことが確認できます(図 7)。これは、一部のユーザーに対して有効になっているフィーチャー トグルが起動の回帰を引き起こしたことを示しています。
MyFlaggedFeature スライスが追加された、高レイテンシのトレース起動。
この例では、一括トレース分析を使用する多くの方法の 1 つを示します。その他のユースケースとしては、フィールドから統計情報を抽出して影響を測定することや、回帰を検出することなどが挙げられます。