• 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;
17
18INCLUDE PERFETTO MODULE android.startup.startups_maxsdk28;
19
20INCLUDE PERFETTO MODULE android.startup.startups_minsdk29;
21
22INCLUDE PERFETTO MODULE android.startup.startups_minsdk33;
23
24INCLUDE PERFETTO MODULE android.version;
25
26CREATE PERFETTO TABLE _android_startups_raw AS
27WITH
28  version AS (
29    SELECT
30      CASE
31        WHEN _android_sdk_version() >= 33
32        THEN 33
33        WHEN _android_sdk_version() >= 29
34        THEN 29
35        WHEN _android_sdk_version() IS NOT NULL
36        THEN 28
37        WHEN (
38          SELECT
39            count()
40          FROM slice
41          WHERE
42            name GLOB 'launchingActivity#*:*'
43        ) > 0
44        THEN 33
45        WHEN (
46          SELECT
47            count()
48          FROM slice
49          WHERE
50            name GLOB 'MetricsLogger:*'
51        ) > 0
52        THEN 29
53        ELSE 28
54      END AS v
55  )
56SELECT
57  _auto_id AS startup_id,
58  ts,
59  ts_end,
60  dur,
61  package,
62  startup_type
63FROM _startups_maxsdk28
64WHERE
65  (
66    SELECT
67      v
68    FROM version
69  ) = 28
70UNION ALL
71SELECT
72  _auto_id AS startup_id,
73  ts,
74  ts_end,
75  dur,
76  package,
77  startup_type
78FROM _startups_minsdk29
79WHERE
80  (
81    SELECT
82      v
83    FROM version
84  ) = 29
85UNION ALL
86SELECT
87  startup_id,
88  ts,
89  ts_end,
90  dur,
91  package,
92  startup_type
93FROM _startups_minsdk33
94WHERE
95  (
96    SELECT
97      v
98    FROM version
99  ) = 33;
100
101-- Create a table containing only the slices which are necessary for determining
102-- whether a startup happened.
103CREATE PERFETTO TABLE _startup_indicator_slices AS
104SELECT
105  ts,
106  name,
107  track_id
108FROM slice
109WHERE
110  name IN ('bindApplication', 'activityStart', 'activityResume');
111
112CREATE PERFETTO FUNCTION _startup_indicator_slice_count(
113    start_ts TIMESTAMP,
114    end_ts TIMESTAMP,
115    utid JOINID(thread.id),
116    name STRING
117)
118RETURNS LONG AS
119SELECT
120  count(1)
121FROM thread_track AS t
122JOIN _startup_indicator_slices AS s
123  ON s.track_id = t.id
124WHERE
125  t.utid = $utid AND s.ts >= $start_ts AND s.ts < $end_ts AND s.name = $name;
126
127-- Maps a startup to the set of processes that handled the activity start.
128--
129-- The vast majority of cases should be a single process. However it is
130-- possible that the process dies during the activity startup and is respawned.
131CREATE PERFETTO TABLE android_startup_processes (
132  -- Startup id.
133  startup_id LONG,
134  -- Upid of process on which activity started.
135  upid JOINID(process.id),
136  -- Pid of process on which activity started.
137  pid LONG,
138  -- Type of the startup.
139  startup_type STRING
140) AS
141-- This is intentionally a materialized query. For some reason, if we don't
142-- materialize, we end up with a query which is an order of magnitude slower :(
143WITH
144  startup_with_type AS MATERIALIZED (
145    SELECT
146      startup_id,
147      upid,
148      pid,
149      CASE
150        -- type parsed from platform event takes precedence if available
151        WHEN startup_type IS NOT NULL
152        THEN startup_type
153        WHEN bind_app > 0 AND a_start > 0 AND a_resume > 0
154        THEN 'cold'
155        WHEN a_start > 0 AND a_resume > 0
156        THEN 'warm'
157        WHEN a_resume > 0
158        THEN 'hot'
159        ELSE NULL
160      END AS startup_type
161    FROM (
162      SELECT
163        l.startup_id,
164        l.startup_type,
165        p.upid,
166        p.pid,
167        _startup_indicator_slice_count(l.ts, l.ts_end, t.utid, 'bindApplication') AS bind_app,
168        _startup_indicator_slice_count(l.ts, l.ts_end, t.utid, 'activityStart') AS a_start,
169        _startup_indicator_slice_count(l.ts, l.ts_end, t.utid, 'activityResume') AS a_resume
170      FROM _android_startups_raw AS l
171      JOIN android_process_metadata AS p
172        ON (
173          l.package = p.package_name
174          -- If the package list data source was not enabled in the trace, nothing
175          -- will match the above constraint so also match any process whose name
176          -- is a prefix of the package name.
177          OR (
178            (
179              SELECT
180                count(1) = 0
181              FROM package_list
182            )
183            AND p.process_name GLOB l.package || '*'
184          )
185        )
186      JOIN thread AS t
187        ON (
188          p.upid = t.upid AND t.is_main_thread
189        )
190      -- Filter out the non-startup processes with the same package name as that of a startup.
191      WHERE
192        a_resume > 0
193    )
194  )
195SELECT
196  *
197FROM startup_with_type
198WHERE
199  startup_type IS NOT NULL;
200
201-- All activity startups in the trace by startup id.
202-- Populated by different scripts depending on the platform version/contents.
203CREATE PERFETTO VIEW android_startups (
204  -- Startup id.
205  startup_id ID,
206  -- Timestamp of startup start.
207  ts TIMESTAMP,
208  -- Timestamp of startup end.
209  ts_end LONG,
210  -- Startup duration.
211  dur DURATION,
212  -- Package name.
213  package STRING,
214  -- Startup type.
215  startup_type STRING
216) AS
217SELECT
218  r.startup_id,
219  r.ts,
220  r.ts_end,
221  r.dur,
222  r.package,
223  coalesce(r.startup_type, max(p.startup_type)) AS startup_type
224FROM _android_startups_raw AS r
225LEFT JOIN android_startup_processes AS p
226  USING (startup_id)
227GROUP BY
228  r.startup_id;
229
230-- Maps a startup to the set of threads on processes that handled the
231-- activity start.
232CREATE PERFETTO VIEW android_startup_threads (
233  -- Startup id.
234  startup_id LONG,
235  -- Timestamp of start.
236  ts TIMESTAMP,
237  -- Duration of startup.
238  dur DURATION,
239  -- Upid of process involved in startup.
240  upid JOINID(process.id),
241  -- Pid if process involved in startup.
242  pid LONG,
243  -- Utid of the thread.
244  utid JOINID(thread.id),
245  -- Tid of the thread.
246  tid LONG,
247  -- Name of the thread.
248  thread_name STRING,
249  -- Thread is a main thread.
250  is_main_thread BOOL
251) AS
252SELECT
253  startups.startup_id,
254  startups.ts,
255  startups.dur,
256  android_startup_processes.upid,
257  android_startup_processes.pid,
258  thread.utid,
259  thread.tid,
260  thread.name AS thread_name,
261  thread.is_main_thread AS is_main_thread
262FROM android_startups AS startups
263JOIN android_startup_processes
264  USING (startup_id)
265JOIN thread
266  USING (upid);
267
268---
269--- Functions
270---
271
272-- All the slices for all startups in trace.
273--
274-- Generally, this view should not be used. Instead, use one of the view functions related
275-- to the startup slices which are created from this table.
276CREATE PERFETTO VIEW android_thread_slices_for_all_startups (
277  -- Timestamp of startup.
278  startup_ts TIMESTAMP,
279  -- Timestamp of startup end.
280  startup_ts_end LONG,
281  -- Startup id.
282  startup_id LONG,
283  -- UTID of thread with slice.
284  utid JOINID(thread.id),
285  --Tid of thread.
286  tid LONG,
287  -- Name of thread.
288  thread_name STRING,
289  -- Whether it is main thread.
290  is_main_thread BOOL,
291  -- Arg set id.
292  arg_set_id ARGSETID,
293  -- Slice id.
294  slice_id JOINID(slice.id),
295  -- Name of slice.
296  slice_name STRING,
297  -- Timestamp of slice start.
298  slice_ts TIMESTAMP,
299  -- Slice duration.
300  slice_dur LONG
301) AS
302SELECT
303  st.ts AS startup_ts,
304  st.ts + st.dur AS startup_ts_end,
305  st.startup_id,
306  st.utid,
307  st.tid,
308  st.thread_name,
309  st.is_main_thread,
310  slice.arg_set_id,
311  slice.id AS slice_id,
312  slice.name AS slice_name,
313  slice.ts AS slice_ts,
314  slice.dur AS slice_dur
315FROM android_startup_threads AS st
316JOIN thread_track
317  USING (utid)
318JOIN slice
319  ON (
320    slice.track_id = thread_track.id
321  )
322WHERE
323  slice.ts BETWEEN st.ts AND st.ts + st.dur;
324
325-- Given a startup id and GLOB for a slice name, returns matching slices with data.
326CREATE PERFETTO FUNCTION android_slices_for_startup_and_slice_name(
327    -- Startup id.
328    startup_id LONG,
329    -- Glob of the slice.
330    slice_name STRING
331)
332RETURNS TABLE (
333  -- Id of the slice.
334  slice_id JOINID(slice.id),
335  -- Name of the slice.
336  slice_name STRING,
337  -- Timestamp of start of the slice.
338  slice_ts TIMESTAMP,
339  -- Duration of the slice.
340  slice_dur DURATION,
341  -- Name of the thread with the slice.
342  thread_name STRING,
343  -- Tid of the thread with the slice.
344  tid LONG,
345  -- Arg set id.
346  arg_set_id ARGSETID
347) AS
348SELECT
349  slice_id,
350  slice_name,
351  slice_ts,
352  slice_dur,
353  thread_name,
354  tid,
355  arg_set_id
356FROM android_thread_slices_for_all_startups
357WHERE
358  startup_id = $startup_id AND slice_name GLOB $slice_name;
359
360-- A Perfetto view that lists matching slices for class loading during app startup.
361CREATE PERFETTO VIEW android_class_loading_for_startup (
362  -- Id of the slice.
363  slice_id JOINID(slice.id),
364  -- Startup id.
365  startup_id LONG,
366  -- Name of the slice.
367  slice_name STRING,
368  -- Timestamp of start of the slice.
369  slice_ts TIMESTAMP,
370  -- Duration of the slice.
371  slice_dur DURATION,
372  -- Name of the thread with the slice.
373  thread_name STRING,
374  -- Tid of the thread with the slice.
375  tid LONG,
376  -- Arg set id.
377  arg_set_id ARGSETID
378) AS
379SELECT
380  slice_id,
381  startup_id,
382  slice_name,
383  slice_ts,
384  slice_dur,
385  thread_name,
386  tid,
387  arg_set_id
388FROM android_thread_slices_for_all_startups
389WHERE
390  slice_name GLOB "L*;";
391
392-- Returns binder transaction slices for a given startup id with duration over threshold.
393CREATE PERFETTO FUNCTION android_binder_transaction_slices_for_startup(
394    -- Startup id.
395    startup_id LONG,
396    -- Only return slices with duration over threshold.
397    threshold DOUBLE
398)
399RETURNS TABLE (
400  -- Slice id.
401  id LONG,
402  -- Slice duration.
403  slice_dur DURATION,
404  -- Name of the thread with slice.
405  thread_name STRING,
406  -- Name of the process with slice.
407  process STRING,
408  -- Arg set id.
409  arg_set_id ARGSETID,
410  -- Whether is main thread.
411  is_main_thread BOOL
412) AS
413SELECT
414  slice_id AS id,
415  slice_dur,
416  thread_name,
417  process.name AS process,
418  s.arg_set_id,
419  is_main_thread
420FROM android_thread_slices_for_all_startups AS s
421JOIN process
422  ON (
423    extract_arg(s.arg_set_id, "destination process") = process.pid
424  )
425WHERE
426  startup_id = $startup_id
427  AND slice_name GLOB "binder transaction"
428  AND slice_dur > $threshold;
429
430-- Returns duration of startup for slice name.
431--
432-- Sums duration of all slices of startup with provided name.
433CREATE PERFETTO FUNCTION android_sum_dur_for_startup_and_slice(
434    -- Startup id.
435    startup_id LONG,
436    -- Slice name.
437    slice_name STRING
438)
439-- Sum of duration.
440RETURNS LONG AS
441SELECT
442  sum(slice_dur)
443FROM android_thread_slices_for_all_startups
444WHERE
445  startup_id = $startup_id AND slice_name GLOB $slice_name;
446
447-- Returns duration of startup for slice name on main thread.
448--
449-- Sums duration of all slices of startup with provided name only on main thread.
450CREATE PERFETTO FUNCTION android_sum_dur_on_main_thread_for_startup_and_slice(
451    -- Startup id.
452    startup_id LONG,
453    -- Slice name.
454    slice_name STRING
455)
456-- Sum of duration.
457RETURNS LONG AS
458SELECT
459  sum(slice_dur)
460FROM android_thread_slices_for_all_startups
461WHERE
462  startup_id = $startup_id AND slice_name GLOB $slice_name AND is_main_thread;
463