• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--
2-- Copyright 2019 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.process_metadata;
17INCLUDE PERFETTO MODULE android.startup.startups_maxsdk28;
18INCLUDE PERFETTO MODULE android.startup.startups_minsdk29;
19INCLUDE PERFETTO MODULE android.startup.startups_minsdk33;
20
21CREATE PERFETTO FUNCTION _slice_count(
22  -- Name of the slices to counted.
23  slice_glob STRING)
24-- Number of slices with the name.
25RETURNS INT AS
26SELECT COUNT(1) FROM slice WHERE name GLOB $slice_glob;
27
28-- Gather all startup data. Populate by different sdks.
29CREATE PERFETTO TABLE _all_startups AS
30SELECT sdk, startup_id, ts, ts_end, dur, package, startup_type FROM _startups_maxsdk28
31UNION ALL
32SELECT sdk, startup_id, ts, ts_end, dur, package, startup_type FROM _startups_minsdk29
33UNION ALL
34SELECT sdk, startup_id, ts, ts_end, dur, package, startup_type FROM _startups_minsdk33;
35
36-- All activity startups in the trace by startup id.
37-- Populated by different scripts depending on the platform version/contents.
38CREATE PERFETTO TABLE android_startups(
39  -- Startup id.
40  startup_id INT,
41  -- Timestamp of startup start.
42  ts INT,
43  -- Timestamp of startup end.
44  ts_end INT,
45  -- Startup duration.
46  dur INT,
47  -- Package name.
48  package STRING,
49  -- Startup type.
50  startup_type STRING
51) AS
52SELECT startup_id, ts, ts_end, dur, package, startup_type FROM
53_all_startups WHERE ( CASE
54  WHEN _slice_count('launchingActivity#*:*') > 0
55    THEN sdk = "minsdk33"
56  WHEN _slice_count('MetricsLogger:*') > 0
57    THEN sdk = "minsdk29"
58  ELSE sdk = "maxsdk28"
59  END);
60
61-- Create a table containing only the slices which are necessary for determining
62-- whether a startup happened.
63CREATE PERFETTO TABLE _startup_indicator_slices AS
64SELECT ts, name, track_id
65FROM slice
66WHERE name IN ('bindApplication', 'activityStart', 'activityResume');
67
68CREATE PERFETTO FUNCTION _startup_indicator_slice_count(start_ts LONG,
69                                                                end_ts LONG,
70                                                                utid INT,
71                                                                name STRING)
72RETURNS INT AS
73SELECT COUNT(1)
74FROM thread_track t
75JOIN _startup_indicator_slices s ON s.track_id = t.id
76WHERE
77  t.utid = $utid AND
78  s.ts >= $start_ts AND
79  s.ts < $end_ts AND
80  s.name = $name;
81
82-- Maps a startup to the set of processes that handled the activity start.
83--
84-- The vast majority of cases should be a single process. However it is
85-- possible that the process dies during the activity startup and is respawned.
86CREATE PERFETTO TABLE android_startup_processes(
87  -- Startup id.
88  startup_id INT,
89  -- Upid of process on which activity started.
90  upid INT,
91  -- Type of the startup.
92  startup_type INT
93) AS
94-- This is intentionally a materialized query. For some reason, if we don't
95-- materialize, we end up with a query which is an order of magnitude slower :(
96WITH startup_with_type AS MATERIALIZED (
97  SELECT
98    startup_id,
99    upid,
100    CASE
101      -- type parsed from platform event takes precedence if available
102      WHEN startup_type IS NOT NULL THEN startup_type
103      WHEN bind_app > 0 AND a_start > 0 AND a_resume > 0 THEN 'cold'
104      WHEN a_start > 0 AND a_resume > 0 THEN 'warm'
105      WHEN a_resume > 0 THEN 'hot'
106      ELSE NULL
107    END AS startup_type
108  FROM (
109    SELECT
110      l.startup_id,
111      l.startup_type,
112      p.upid,
113      _startup_indicator_slice_count(l.ts, l.ts_end, t.utid, 'bindApplication') AS bind_app,
114      _startup_indicator_slice_count(l.ts, l.ts_end, t.utid, 'activityStart') AS a_start,
115      _startup_indicator_slice_count(l.ts, l.ts_end, t.utid, 'activityResume') AS a_resume
116    FROM android_startups l
117    JOIN android_process_metadata p ON (
118      l.package = p.package_name
119      -- If the package list data source was not enabled in the trace, nothing
120      -- will match the above constraint so also match any process whose name
121      -- is a prefix of the package name.
122      OR (
123        (SELECT COUNT(1) = 0 FROM package_list)
124        AND p.process_name GLOB l.package || '*'
125      )
126      )
127    JOIN thread t ON (p.upid = t.upid AND t.is_main_thread)
128    -- Filter out the non-startup processes with the same package name as that of a startup.
129    WHERE a_resume > 0
130  )
131)
132SELECT *
133FROM startup_with_type
134WHERE startup_type IS NOT NULL;
135
136
137-- Maps a startup to the set of threads on processes that handled the
138-- activity start.
139CREATE PERFETTO VIEW android_startup_threads(
140  -- Startup id.
141  startup_id INT,
142  -- Timestamp of start.
143  ts INT,
144  -- Duration of startup.
145  dur INT,
146  -- Upid of process involved in startup.
147  upid INT,
148  -- Utid of the thread.
149  utid INT,
150  -- Name of the thread.
151  thread_name STRING,
152  -- Thread is a main thread.
153  is_main_thread BOOL
154) AS
155SELECT
156  startups.startup_id,
157  startups.ts,
158  startups.dur,
159  android_startup_processes.upid,
160  thread.utid,
161  thread.name AS thread_name,
162  thread.is_main_thread AS is_main_thread
163FROM android_startups startups
164JOIN android_startup_processes USING (startup_id)
165JOIN thread USING (upid);
166
167---
168--- Functions
169---
170
171-- All the slices for all startups in trace.
172--
173-- Generally, this view should not be used. Instead, use one of the view functions related
174-- to the startup slices which are created from this table.
175CREATE PERFETTO VIEW android_thread_slices_for_all_startups(
176  -- Timestamp of startup.
177  startup_ts INT,
178  -- Timestamp of startup end.
179  startup_ts_end INT,
180  -- Startup id.
181  startup_id INT,
182  -- UTID of thread with slice.
183  utid INT,
184  -- Name of thread.
185  thread_name STRING,
186  -- Whether it is main thread.
187  is_main_thread BOOL,
188  -- Arg set id.
189  arg_set_id INT,
190  -- Slice id.
191  slice_id INT,
192  -- Name of slice.
193  slice_name STRING,
194  -- Timestamp of slice start.
195  slice_ts INT,
196  -- Slice duration.
197  slice_dur INT
198) AS
199SELECT
200  st.ts AS startup_ts,
201  st.ts + st.dur AS startup_ts_end,
202  st.startup_id,
203  st.utid,
204  st.thread_name,
205  st.is_main_thread,
206  slice.arg_set_id,
207  slice.id as slice_id,
208  slice.name AS slice_name,
209  slice.ts AS slice_ts,
210  slice.dur AS slice_dur
211FROM android_startup_threads st
212JOIN thread_track USING (utid)
213JOIN slice ON (slice.track_id = thread_track.id)
214WHERE slice.ts BETWEEN st.ts AND st.ts + st.dur;
215
216-- Given a startup id and GLOB for a slice name, returns matching slices with data.
217CREATE PERFETTO FUNCTION android_slices_for_startup_and_slice_name(
218  -- Startup id.
219  startup_id INT,
220  -- Glob of the slice.
221  slice_name STRING)
222RETURNS TABLE(
223  -- Id of the slice.
224  slice_id INT,
225  -- Name of the slice.
226  slice_name STRING,
227  -- Timestamp of start of the slice.
228  slice_ts INT,
229  -- Duration of the slice.
230  slice_dur INT,
231  -- Name of the thread with the slice.
232  thread_name STRING,
233  -- Arg set id.
234  arg_set_id INT
235) AS
236SELECT slice_id, slice_name, slice_ts, slice_dur, thread_name, arg_set_id
237FROM android_thread_slices_for_all_startups
238WHERE startup_id = $startup_id AND slice_name GLOB $slice_name;
239
240-- Returns binder transaction slices for a given startup id with duration over threshold.
241CREATE PERFETTO FUNCTION android_binder_transaction_slices_for_startup(
242  -- Startup id.
243  startup_id INT,
244  -- Only return slices with duration over threshold.
245  threshold DOUBLE)
246RETURNS TABLE(
247  -- Slice id.
248  id INT,
249  -- Slice duration.
250  slice_dur INT,
251  -- Name of the thread with slice.
252  thread_name STRING,
253  -- Name of the process with slice.
254  process STRING,
255  -- Arg set id.
256  arg_set_id INT,
257  -- Whether is main thread.
258  is_main_thread BOOL
259) AS
260SELECT
261  slice_id as id,
262  slice_dur,
263  thread_name,
264  process.name as process,
265  s.arg_set_id,
266  is_main_thread
267FROM android_thread_slices_for_all_startups s
268JOIN process ON (
269  EXTRACT_ARG(s.arg_set_id, "destination process") = process.pid
270)
271WHERE startup_id = $startup_id
272  AND slice_name GLOB "binder transaction"
273  AND slice_dur > $threshold;
274
275-- Returns duration of startup for slice name.
276--
277-- Sums duration of all slices of startup with provided name.
278CREATE PERFETTO FUNCTION android_sum_dur_for_startup_and_slice(
279  -- Startup id.
280  startup_id LONG,
281  -- Slice name.
282  slice_name STRING)
283-- Sum of duration.
284RETURNS INT AS
285SELECT SUM(slice_dur)
286FROM android_thread_slices_for_all_startups
287WHERE startup_id = $startup_id
288  AND slice_name GLOB $slice_name;
289
290-- Returns duration of startup for slice name on main thread.
291--
292-- Sums duration of all slices of startup with provided name only on main thread.
293CREATE PERFETTO FUNCTION android_sum_dur_on_main_thread_for_startup_and_slice(
294  -- Startup id.
295  startup_id LONG,
296  -- Slice name.
297  slice_name STRING)
298-- Sum of duration.
299RETURNS INT AS
300SELECT SUM(slice_dur)
301FROM android_thread_slices_for_all_startups
302WHERE startup_id = $startup_id
303  AND slice_name GLOB $slice_name
304  AND is_main_thread;
305