Query ProfilingManager profiles
Stay organized with collections
Save and categorize content based on your preferences.
Querying ProfilingManager profiles is similar to querying regular Perfetto
profiles. Therefore, review Getting Started with PerfettoSQL for a guide on
how to query profiles.
An important distinction between regular Perfetto traces and ProfilingManager
traces is that ProfilingManager traces pass through a trace redactor. This
redactor removes information about other processes unrelated to your app for
privacy reasons.
Some queries from the Perfetto standard library are not usable on redacted
traces. This is because ProfilingManager only collects profiling data for your
app, not other processes. As a result, the queries you can use with
ProfilingManager are a smaller set than those for full system profiles
recorded using local Perfetto.
Even though the querying space is reduced, you can still use many PerfettoSQL queries and tables from the Perfetto Standard Library as-is, so we encourage you to try them.
We also recommend that you review Analyzing Android Traces to find ready-to-use queries that provide useful performance data without modification.
ProfilingManager sample queries
To simplify the querying journey, this section provides a list of queries that
work with ProfilingManager. You can use these queries directly or as examples
to build other queries.
Find the most duplicated slices
This query finds repeated slices in a trace and sorts them by how often they appear, showing the most duplicated ones first.
Finding duplicated work is a common way to find unnecessary work in a trace.
-- You only need to call this once in the session to create the function
DROPTABLEIFEXISTSfind_duplicates;
CREATEPERFETTOFUNCTIONfind_duplicates(patternSTRING)RETURNS
TABLE(nameSTRING,count_sliceLONG)ASSELECTname,COUNT(dur)ascount_sliceFROMsliceWHEREnameGLOB$patternGROUPBYnameHAVINGCOUNT(name)>=2ORDERBYcount_sliceDESC;
-- Subsequent calls can just use the function to find dupes
SELECT*FROMfind_duplicates('*Text*')
Jank queries
Find slow frames
This query finds frames where your app takes too long to generate a frame,
assuming an expected frame rate of 60 Hz (16.6 ms). The dur is set to
16,660,000 because slice durations in Perfetto tables are stored in nanoseconds.
INCLUDEPERFETTOmoduleandroid.frames.timeline;
SELECT*FROMandroid_framesWHEREdur > 16660000;
Find jank-causing frames
INCLUDEPERFETTOmoduleandroid.frames.timeline;
SELECT*FROMactual_frame_timeline_sliceWHEREjank_type='App Deadline Missed';
This query is useful to find locations where jank occurs in the trace because the app takes too long to generate a frame. This means that the UI thread failed to generate a frame. Under extreme circumstances, this could precede an ANR.
Find most duplicated objects
You can also query memory-related profiles, such as heap dumps, to perform more complex memory analyses.
INCLUDEPERFETTOMODULEandroid.memory.heap_graph.heap_graph_class_aggregation;
SELECT*FROMandroid_heap_graph_class_aggregationWHEREobj_count>=2
ORDERBYobj_countDESCLIMIT100
This query returns the top 100 duplicated objects. This can help you find objects that are instantiated multiple times, which might reveal opportunities for caching them or identify unintended duplicates.
Cold startup latency
You can also query for startups. This section provides a more elaborate query to estimate cold startup time in a trace.
-- This function finds slices that match the given GLOB $pattern
CREATEORREPLACEFUNCTIONfind_slices(patternSTRING)RETURNS
TABLE(nameSTRING,tsLONG,durLONG)AS
SELECTname,ts,durFROMsliceWHEREnameGLOB$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.
CREATEORREPLACEPERFETTOFUNCTIONgenerate_start_to_end_slices(startSlicePatternSTRING,endSlicePatternSTRING,inclusiveBOOL)RETURNS
TABLE(nameSTRING,tsLONG,durLONG)AS
SELECTname,ts,MIN(startToEndDur)asdur
FROM
(SELECTS.nameasname,S.tsasts,E.ts+IIF($inclusive,E.dur,0)-S.tsasstartToEndDur
FROMfind_slices($startSlicePattern)asSCROSSJOINfind_slices($endSlicePattern)asE
WHEREstartToEndDur > 0)
GROUPBYname,ts;
-- Using these functions we can estimate cold startup time by generating a slice between bindApplication and first frame.
SELECT*fromgenerate_start_to_end_slices('bindApplication','*Choreographer#doFrame [0-9]*',true)
This query generates a slice that represents the time between two slices that
define the startup time: bindApplication (typically found at the start of a
cold app launch) and the first Choreographer#doFrame slice (the first
generated frame). This metric effectively estimates cold startup TTFF (time to
first frame).