• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--
2-- Copyright 2024 The Android Open Source Project
3--
4-- Licensed under the Apache License, Version 2.0 (the "License");
5-- you may not use this file except in compliance with the License.
6-- You may obtain a copy of the License at
7--
8--     https://www.apache.org/licenses/LICENSE-2.0
9--
10-- Unless required by applicable law or agreed to in writing, software
11-- distributed under the License is distributed on an "AS IS" BASIS,
12-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-- See the License for the specific language governing permissions and
14-- limitations under the License.
15
16INCLUDE PERFETTO MODULE android.startup.startups;
17INCLUDE PERFETTO MODULE android.frames.timeline;
18INCLUDE PERFETTO MODULE slices.with_context;
19
20CREATE PERFETTO VIEW _startups_with_upid AS
21WITH joined_with_processes AS (
22  SELECT
23    s.*,
24    p.upid
25  FROM android_startups s
26  LEFT JOIN android_startup_processes p USING (startup_id)
27),
28fallback AS (
29  SELECT
30    s.*,
31    upid FROM android_startups s
32  JOIN process p ON (p.name glob s.package)
33)
34  SELECT
35    j.startup_id,
36    j.ts,
37    j.ts_end,
38    j.dur,
39    j.package,
40    j.startup_type,
41    COALESCE(j.upid, f.upid) AS upid
42  FROM joined_with_processes j
43  LEFT JOIN fallback f ON (j.upid IS NULL AND j.startup_id = f.startup_id);
44
45-- Get Time To Initial Display of the startup calculated as time between the
46-- startup started and the first frame that was started by Choreographer on the
47-- UI thread of the startup finished drawing.
48-- TTID (https://developer.android.com/topic/performance/vitals/launch-time#time-initial)
49-- Googlers: see go/android-performance-metrics-glossary for details.
50CREATE PERFETTO TABLE _ttid AS
51WITH frames_with_upid AS (
52  SELECT
53  f.*,
54  upid
55  FROM android_frames f
56  JOIN thread t ON (f.ui_thread_utid = t.utid)
57),
58  -- First `DrawFrame` on Render Thread after the startup.
59first_frame_for_startup AS (
60  SELECT
61    startup_id,
62    frame_id,
63    s.ts AS startup_ts,
64    draw_frame_id,
65    s.upid
66  FROM _startups_with_upid s
67  JOIN frames_with_upid f ON (s.upid = f.upid AND s.ts <= f.ts)
68  GROUP BY startup_id
69  ORDER BY startup_id, f.ts)
70SELECT
71  startup_id,
72  frame_id,
73  draw_frame_id,
74  ts + dur - startup_ts AS ttid,
75  upid
76FROM first_frame_for_startup
77JOIN slice ON (slice.id = draw_frame_id);
78
79-- Get Time To Full Display of the startup calculated as time between the
80-- startup started and the first frame that was started by Choreographer after
81-- or containing the `reportFullyDrawn()` slice on the UI thread of the startup
82-- finished drawing.
83-- TTFD (https://developer.android.com/topic/performance/vitals/launch-time#retrieve-TTFD)
84-- Googlers: see go/android-performance-metrics-glossary for details.
85CREATE PERFETTO TABLE _ttfd AS
86-- First `reportFullyDrawn` slice for each startup.
87WITH first_report_fully_drawn_for_startup AS (
88  SELECT
89  startup_id,
90  s.ts AS startup_ts,
91  t.ts AS report_fully_drawn_ts,
92  t.utid,
93  s.upid
94FROM _startups_with_upid s
95JOIN thread_slice t ON (s.upid = t.upid AND t.ts >= s.ts)
96WHERE name GLOB "reportFullyDrawn*" AND t.is_main_thread = 1
97GROUP BY startup_id
98ORDER BY startup_id, t.ts),
99-- After the first `reportFullyDrawn` find the first `Choreographer#DoFrame` on
100-- the UI thread and it's first `DrawFrame` on Render Thread.
101first_frame_after_report_for_startup AS (
102  SELECT
103    startup_id,
104    frame_id,
105    startup_ts,
106    draw_frame_id,
107    s.upid
108  FROM first_report_fully_drawn_for_startup s
109  JOIN android_frames f ON (
110    s.utid = f.ui_thread_utid
111    -- We are looking for the first DrawFrame that was started by the first
112    -- "Choreographer#DoFrame" on UI thread after or containing
113    -- reportFullyDrawn. In Android UIs, it's common to have UI code happen
114    -- either before a frame, or during it, and generally non-trivial amounts
115    -- of "update UI model" code doesn't try to differentiate these. We account
116    -- for both of these by looking for the first UI slice that ends after the
117    -- "reportFullyDrawnSlice" begins.
118    AND report_fully_drawn_ts < (f.ts + f.dur))
119  GROUP BY startup_id
120  ORDER BY startup_id, f.ts
121)
122-- Get TTFD as the difference between the start of the startup and the end of
123-- `DrawFrame` slice we previously found.
124SELECT
125  startup_id,
126  frame_id,
127  draw_frame_id,
128  ts + dur - startup_ts AS ttfd,
129  upid
130FROM first_frame_after_report_for_startup
131JOIN slice ON (slice.id = draw_frame_id);
132
133-- Startup metric defintions, which focus on the observable time range:
134-- TTID - Time To Initial Display
135-- * https://developer.android.com/topic/performance/vitals/launch-time#time-initial
136-- * end of first RenderThread.DrawFrame - bindApplication
137-- TTFD - Time To Full Display
138-- * https://developer.android.com/topic/performance/vitals/launch-time#retrieve-TTFD
139-- * end of next RT.DrawFrame, after reportFullyDrawn called - bindApplication
140-- Googlers: see go/android-performance-metrics-glossary for details.
141CREATE PERFETTO TABLE android_startup_time_to_display(
142  -- Startup id.
143  startup_id INT,
144  -- Time to initial display (TTID)
145  time_to_initial_display INT,
146  -- Time to full display (TTFD)
147  time_to_full_display INT,
148  -- `android_frames.frame_id` of frame for initial display
149  ttid_frame_id INT,
150  -- `android_frames.frame_id` of frame for full display
151  ttfd_frame_id INT,
152  -- `process.upid` of the startup
153  upid INT
154) AS
155SELECT
156  startup_id,
157  ttid AS time_to_initial_display,
158  ttfd AS time_to_full_display,
159  _ttid.frame_id AS ttid_frame_id,
160  _ttfd.frame_id AS ttfd_frame_id,
161  _ttid.upid
162FROM android_startups
163LEFT JOIN _ttid USING (startup_id)
164LEFT JOIN _ttfd USING (startup_id);
165