Wykonywanie zapytań na profilach za pomocą PerfettoSQL

Możesz wysyłać zapytania do profili ProfilingManager za pomocą PerfettoSQL i modułów z biblioteki standardowej Perfetto. ProfilingManager usuwa ze śledzenia systemu dane, które nie dotyczą procesu aplikacji, dlatego zapytania do biblioteki standardowej na poziomie systemu, które zależą od innych procesów, nie są obsługiwane. Jednak większość zapytań o zakresie aplikacji i standardowych modułów biblioteki działa bez zmian. Więcej gotowych do użycia zapytań znajdziesz w artykule Analizowanie logów czasu Androida.

Przykładowe zapytania dotyczące ProfilingManager

Możesz użyć tych przykładowych zapytań bezpośrednio lub jako szablonów do własnej analizy PerfettoSQL.

Znajdowanie najbardziej zduplikowanych wycinków

Powtarzające się wycinki często wskazują na zbędną pracę. Szczegółowe informacje o składni funkcji znajdziesz w artykule na temat definiowania funkcji w PerfettoSQL. Poniższe zapytanie definiuje funkcję PerfettoSQL wielokrotnego użytku, która znajduje wycinki pasujące do wzorca GLOB i sortuje je według częstotliwości:

-- You only need to call this once in the session to create or update the function
CREATE OR REPLACE 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*')

Zapytania dotyczące zacinania się

Aby zidentyfikować powolne lub zacinające się klatki w śledzeniu systemu, użyj tych zapytań.

Znajdowanie spowolnionych klatek

To zapytanie znajduje klatki, których renderowanie trwa dłużej niż 16,6 ms (60 Hz). Perfetto przechowuje czas trwania wycinków w nanosekundach, więc wartość dur jest porównywana z wartością 16660000:

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

Znajdowanie klatek powodujących zacinanie się

To zapytanie używa modułu osi czasu klatek, aby znaleźć klatki, w przypadku których aplikacja nie zmieściła się w terminie renderowania zgodnie z częstotliwością odświeżania urządzenia:

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

Znajdowanie najbardziej zduplikowanych obiektów

W zrzucie sterty Javy to zapytanie zwraca 100 najpopularniejszych klas z co najmniej 2 instancjami, co pomaga wykryć niezamierzone duplikaty lub możliwości buforowania:

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

Czas oczekiwania na uruchomienie „na zimno”

To zapytanie szacuje czas do pierwszej klatki (TTFF) podczas uruchomienia „na zimno”, mierząc czas między bindApplication a pierwszym wycinkiem Choreographer#doFrame:

-- This function finds slices that match the given GLOB $pattern
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;

-- 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)