Consultar perfis com o PerfettoSQL

É possível consultar perfis ProfilingManager usando o PerfettoSQL e módulos da biblioteca padrão do Perfetto. Como o ProfilingManager edita rastreamentos do sistema para incluir apenas os dados do processo do app, as consultas de biblioteca padrão em todo o sistema que dependem de outros processos não são compatíveis. No entanto, a maioria das consultas com escopo de app e dos módulos de biblioteca padrão funciona sem modificações. Para mais consultas prontas para uso, consulte Como analisar traces do Android.

Consultas de amostra do ProfilingManager

Use as consultas de exemplo a seguir diretamente ou como modelos para sua própria análise do PerfettoSQL.

Encontrar as frações mais duplicadas

As frações repetidas geralmente indicam trabalho redundante. Para detalhes sobre a sintaxe da função, consulte Como definir funções no PerfettoSQL. A consulta a seguir define uma função reutilizável do PerfettoSQL que encontra frações que correspondem a um padrão GLOB e as classifica por frequência:

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

Consultas de instabilidade

Use as consultas a seguir para identificar frames lentos ou instáveis em um rastreamento do sistema.

Encontrar frames lentos

Essa consulta encontra frames que levam mais de 16,6 ms (60 Hz) para serem renderizados. Como o Perfetto armazena as durações de frações em nanossegundos, dur é comparado com 16660000:

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

Encontrar frames que causam instabilidade

Essa consulta usa o módulo de linha do tempo de frames para encontrar frames em que o app perdeu o prazo de renderização de acordo com a taxa de atualização do dispositivo:

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

Encontrar os objetos mais duplicados

Em um heap dump do Java, essa consulta retorna as 100 principais classes com duas ou mais instâncias para ajudar você a identificar duplicatas não intencionais ou oportunidades de armazenamento em cache:

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

Latência de inicialização a frio

Essa consulta estima o tempo de inicialização a frio até o primeiro frame (TTFF, na sigla em inglês) medindo a duração entre bindApplication e a primeira fração 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)