ProfilingManager プロファイルをクエリする

ProfilingManager プロファイルのクエリは、通常の Perfetto プロファイルのクエリと似ています。プロファイルのクエリ方法については、PerfettoSQL のスタートガイドをご覧ください。

通常の Perfetto トレースと ProfilingManager トレースの重要な違いは、ProfilingManager トレースがトレース リダクタを通過することです。このリダクタは、プライバシー上の理由から、アプリに関係のない他のプロセスに関する情報を削除します。

Perfetto 標準ライブラリの一部のクエリは、リダクトされたトレースでは使用できません。これは、ProfilingManager が他のプロセスではなく、アプリのプロファイリング データのみを収集するためです。そのため、ProfilingManager で使用できるクエリは、ローカル Perfetto を使用して記録された完全なシステム プロファイルのクエリよりも少ないセットになります。

クエリ空間は縮小されますが、Perfetto 標準ライブラリの多くの PerfettoSQL クエリとテーブルはそのまま使用できるため、ぜひお試しください。

また、Android トレースの分析で、 変更せずに使用できるクエリを見つけて、有用なパフォーマンス データを取得することをおすすめします。

ProfilingManager のサンプルクエリ

クエリをシンプルにするために、このセクションでは ProfilingManager で動作するクエリのリストを示します。これらのクエリは、そのまま使用することも、他のクエリを作成するための例として使用することもできます。

最も重複しているスライスを見つける

このクエリは、トレース内で繰り返されるスライスを見つけ、出現頻度で並べ替えて、最も重複しているスライスを最初に表示します。

重複した作業を見つけることは、トレースで不要な作業を見つける一般的な方法です。

-- You only need to call this once in the session to create the function
DROP TABLE IF EXISTS find_duplicates;
CREATE PERFETTO FUNCTION find_duplicates(pattern STRING) RETURNS
TABLE(name STRING, count_slice LONG) AS SELECT name, COUNT(dur) as count_slice FROM slice WHERE name GLOB $pattern GROUP BY name HAVING COUNT(name) >= 2 ORDER BY count_slice DESC;

-- Subsequent calls can just use the function to find dupes
SELECT * FROM find_duplicates('*Text*')

ジャンククエリ

遅いフレームを見つける

このクエリは、アプリがフレームの生成に時間がかかりすぎるフレームを見つけます。想定されるフレームレートは 60 Hz(16.6 ミリ秒)です。Perfetto テーブルのスライス期間はナノ秒単位で保存されるため、dur は 16,660,000 に設定されています。

INCLUDE PERFETTO module android.frames.timeline;
SELECT * FROM android_frames WHERE dur > 16660000;

ジャンクの原因となるフレームを見つける

INCLUDE PERFETTO module android.frames.timeline;
SELECT * FROM actual_frame_timeline_slice WHERE jank_type = 'App Deadline Missed';

このクエリは、アプリがフレームの生成に時間がかかりすぎるため、トレース内でジャンクが発生する場所を見つけるのに役立ちます。これは、UI スレッドがフレームを生成できなかったことを意味します。極端な状況では、ANR の前に発生する可能性があります。

最も重複しているオブジェクトを見つける

ヒープダンプなどのメモリ関連のプロファイルをクエリして、より複雑なメモリ分析を行うこともできます。

INCLUDE PERFETTO MODULE android.memory.heap_graph.heap_graph_class_aggregation;

SELECT * FROM android_heap_graph_class_aggregation WHERE obj_count >= 2
ORDER BY obj_count DESC LIMIT 100

このクエリは、重複している上位 100 個のオブジェクトを返します。これにより、複数回インスタンス化されたオブジェクトを見つけることができます。これにより、オブジェクトをキャッシュする機会を見つけたり、意図しない重複を特定したりできます。

コールド スタートアップ レイテンシ

スタートアップのクエリも可能です。このセクションでは、トレース内のコールド スタートアップ時間を推定するためのより詳細なクエリについて説明します。

-- This function finds slices that match the given GLOB $pattern
CREATE OR REPLACE FUNCTION find_slices(pattern STRING) RETURNS
TABLE (name STRING, ts LONG, dur LONG) AS
SELECT name,ts,dur FROM slice WHERE name GLOB $pattern;

-- This function generates a slice that starts at $startSlicePattern and finishes at the slice matched by $endSlicePattern. If $inclusive is true, then the end slice dur will be added, otherwise, the end slice start time will be used.
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;

-- Using these functions we can estimate cold startup time by generating a slice between bindApplication and first frame.
SELECT * from generate_start_to_end_slices('bindApplication','*Choreographer#doFrame [0-9]*', true)

このクエリは、スタートアップ時間を定義する 2 つのスライス(bindApplication(通常はコールドアプリの起動時に発生)と最初の Choreographer#doFrame スライス(最初に生成されたフレーム))の間の時間を表すスライスを生成します。この指標は、コールド スタートアップの TTFF(最初のフレームまでの時間)を効果的に推定します。