• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--
2-- Copyright 2022 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--
16
17INCLUDE PERFETTO MODULE android.startup.startups;
18
19SELECT RUN_METRIC('android/startup/thread_state_breakdown.sql');
20SELECT RUN_METRIC('android/startup/system_state.sql');
21SELECT RUN_METRIC('android/startup/mcycles_per_launch.sql');
22-- Define helper functions related to slow start thresholds
23SELECT RUN_METRIC('android/startup/slow_start_thresholds.sql');
24
25CREATE OR REPLACE PERFETTO FUNCTION _is_spans_overlapping(
26  ts1 LONG,
27  ts_end1 LONG,
28  ts2 LONG,
29  ts_end2 LONG)
30RETURNS BOOL AS
31SELECT (IIF($ts1 < $ts2, $ts2, $ts1)
32      < IIF($ts_end1 < $ts_end2, $ts_end1, $ts_end2));
33
34CREATE OR REPLACE PERFETTO FUNCTION get_percent(num LONG, total LONG)
35RETURNS STRING AS
36  SELECT SUBSTRING(CAST(($num * 100 + 0.0) / $total AS STRING), 1, 5);
37
38CREATE OR REPLACE PERFETTO FUNCTION get_ns_to_s(ns LONG)
39RETURNS STRING AS
40  SELECT CAST(($ns + 0.0) / 1e9 AS STRING);
41
42CREATE OR REPLACE PERFETTO FUNCTION get_ns_to_ms(ns LONG)
43RETURNS STRING AS
44  SELECT SUBSTRING(CAST(($ns + 0.0) / 1e6 AS STRING), 1, 6);
45
46CREATE OR REPLACE PERFETTO FUNCTION get_main_thread_time_for_launch_in_runnable_state(
47  startup_id LONG, num_threads INT)
48RETURNS PROTO AS
49  SELECT AndroidStartupMetric_TraceThreadSectionInfo(
50    'start_timestamp', MIN(ts),
51    'end_timestamp', MAX(ts + dur),
52    'thread_section', RepeatedField(AndroidStartupMetric_TraceThreadSection(
53      'start_timestamp', ts, 'end_timestamp', ts + dur,
54      'thread_tid', tid, 'process_pid', pid,
55      'thread_name', thread_name)))
56  FROM (
57    SELECT p.pid, ts, dur, thread.tid, thread_name
58    FROM launch_threads_by_thread_state l, android_startup_processes p
59    JOIN thread USING (utid)
60    WHERE l.startup_id = $startup_id AND (state GLOB "R" OR state GLOB "R+") AND l.is_main_thread
61      AND p.startup_id = $startup_id
62    ORDER BY dur DESC
63    LIMIT $num_threads);
64
65CREATE OR REPLACE PERFETTO FUNCTION get_main_thread_time_for_launch_and_state(
66  startup_id LONG, state STRING, num_threads INT)
67RETURNS PROTO AS
68  SELECT AndroidStartupMetric_TraceThreadSectionInfo(
69    'start_timestamp', MIN(ts),
70    'end_timestamp', MAX(ts + dur),
71    'thread_section', RepeatedField(AndroidStartupMetric_TraceThreadSection(
72      'start_timestamp', ts, 'end_timestamp', ts + dur,
73      'thread_tid', tid, 'process_pid', pid,
74      'thread_name', thread_name)))
75  FROM (
76    SELECT p.pid, ts, dur, thread.tid, thread_name
77    FROM launch_threads_by_thread_state l, android_startup_processes p
78    JOIN thread USING (utid)
79    WHERE l.startup_id = $startup_id AND state GLOB $state AND l.is_main_thread
80      AND p.startup_id = $startup_id
81    ORDER BY dur DESC
82    LIMIT $num_threads);
83
84CREATE OR REPLACE PERFETTO FUNCTION get_main_thread_time_for_launch_state_and_io_wait(
85  startup_id INT, state STRING, io_wait BOOL, num_threads INT)
86RETURNS PROTO AS
87  SELECT AndroidStartupMetric_TraceThreadSectionInfo(
88    'start_timestamp', MIN(ts),
89    'end_timestamp', MAX(ts + dur),
90    'thread_section', RepeatedField(AndroidStartupMetric_TraceThreadSection(
91      'start_timestamp', ts, 'end_timestamp', ts + dur,
92      'thread_tid', tid, 'process_pid', pid,
93      'thread_name', thread_name)))
94  FROM (
95    SELECT p.pid, ts, dur, thread.tid, thread_name
96    FROM launch_threads_by_thread_state l, android_startup_processes p
97    JOIN thread USING (utid)
98    WHERE l.startup_id = $startup_id AND state GLOB $state
99      AND l.is_main_thread AND l.io_wait = $io_wait
100      AND p.startup_id = $startup_id
101    ORDER BY dur DESC
102    LIMIT $num_threads);
103
104CREATE OR REPLACE PERFETTO FUNCTION get_thread_time_for_launch_state_and_thread(
105  startup_id INT, state STRING, thread_name STRING, num_threads INT)
106RETURNS PROTO AS
107  SELECT AndroidStartupMetric_TraceThreadSectionInfo(
108    'start_timestamp', MIN(ts),
109    'end_timestamp', MAX(ts + dur),
110    'thread_section', RepeatedField(AndroidStartupMetric_TraceThreadSection(
111      'start_timestamp', ts, 'end_timestamp', ts + dur,
112      'thread_tid', tid, 'process_pid', pid,
113      'thread_name', thread_name)))
114  FROM (
115    SELECT p.pid, ts, dur, thread.tid, thread_name
116    FROM launch_threads_by_thread_state l, android_startup_processes p
117    JOIN thread USING (utid)
118    WHERE l.startup_id = $startup_id AND state GLOB $state AND thread_name = $thread_name
119      AND p.startup_id = $startup_id
120    ORDER BY dur DESC
121    LIMIT $num_threads);
122
123CREATE OR REPLACE PERFETTO FUNCTION get_missing_baseline_profile_for_launch(
124  startup_id LONG, pkg_name STRING)
125RETURNS PROTO AS
126  SELECT AndroidStartupMetric_TraceSliceSectionInfo(
127    'slice_section', RepeatedField(AndroidStartupMetric_TraceSliceSection(
128      'thread_tid', tid,
129      'process_pid', pid,
130      'start_timestamp', slice_ts,
131      'end_timestamp', slice_ts + slice_dur,
132      'slice_id', slice_id,
133      'slice_name', slice_name)),
134    'start_timestamp', MIN(slice_ts),
135    'end_timestamp', MAX(slice_ts + slice_dur))
136  FROM (
137    SELECT p.pid, tid, slice_ts, slice_dur, slice_id, slice_name
138    FROM ANDROID_SLICES_FOR_STARTUP_AND_SLICE_NAME($startup_id,
139      "location=* status=* filter=* reason=*"), android_startup_processes p
140    WHERE
141      -- when location is the package odex file and the reason is "install" or "install-dm",
142      -- if the compilation filter is not "speed-profile", baseline/cloud profile is missing.
143      SUBSTR(STR_SPLIT(slice_name, " status=", 0), LENGTH("location=") + 1)
144        GLOB ("*" || $pkg_name || "*odex")
145      AND (STR_SPLIT(slice_name, " reason=", 1) = "install"
146      OR STR_SPLIT(slice_name, " reason=", 1) = "install-dm")
147      AND p.startup_id = $startup_id
148    ORDER BY slice_dur DESC
149    LIMIT 1);
150
151CREATE OR REPLACE PERFETTO FUNCTION get_run_from_apk(startup_id LONG)
152RETURNS PROTO AS
153  SELECT AndroidStartupMetric_TraceSliceSectionInfo(
154    'slice_section', RepeatedField(AndroidStartupMetric_TraceSliceSection(
155      'thread_tid', tid,
156      'process_pid', pid,
157      'start_timestamp', slice_ts,
158      'end_timestamp', slice_ts + slice_dur,
159      'slice_id', slice_id,
160      'slice_name', slice_name)),
161    'start_timestamp', MIN(slice_ts),
162    'end_timestamp', MAX(slice_ts + slice_dur))
163  FROM (
164    SELECT p.pid, tid, slice_ts, slice_dur, slice_id, slice_name
165    FROM android_thread_slices_for_all_startups l, android_startup_processes p
166    WHERE
167      l.startup_id = $startup_id AND is_main_thread AND
168      slice_name GLOB "location=* status=* filter=* reason=*" AND
169      STR_SPLIT(STR_SPLIT(slice_name, " filter=", 1), " reason=", 0)
170        GLOB ("*" || "run-from-apk" || "*")
171      AND p.startup_id = $startup_id
172    ORDER BY slice_dur DESC
173    LIMIT 1);
174
175CREATE OR REPLACE PERFETTO FUNCTION get_unlock_running_during_launch_slice(startup_id LONG,
176  pid INT)
177RETURNS PROTO AS
178  SELECT AndroidStartupMetric_TraceSliceSectionInfo(
179    'slice_section', RepeatedField(AndroidStartupMetric_TraceSliceSection(
180      'thread_tid', tid,
181      'process_pid', $pid,
182      'start_timestamp', slice_ts,
183      'end_timestamp', slice_ts + slice_dur,
184      'slice_id', slice_id,
185      'slice_name', slice_name)),
186    'start_timestamp', MIN(slice_ts),
187    'end_timestamp', MAX(slice_ts + slice_dur))
188  FROM (
189    SELECT tid, slice.ts as slice_ts, slice.dur as slice_dur,
190      slice.id as slice_id, slice.name as slice_name
191    FROM slice, android_startups launches
192    JOIN thread_track ON slice.track_id = thread_track.id
193    JOIN thread USING(utid)
194    JOIN process USING(upid)
195    WHERE launches.startup_id = $startup_id
196    AND slice.name = "KeyguardUpdateMonitor#onAuthenticationSucceeded"
197    AND process.name = "com.android.systemui"
198    AND slice.ts >= launches.ts
199    AND (slice.ts + slice.dur) <= launches.ts_end
200    LIMIT 1);
201
202CREATE OR REPLACE PERFETTO FUNCTION get_gc_activity(startup_id LONG, num_slices INT)
203RETURNS PROTO  AS
204  SELECT AndroidStartupMetric_TraceSliceSectionInfo(
205    'slice_section', RepeatedField(AndroidStartupMetric_TraceSliceSection(
206      'thread_tid', tid,
207      'process_pid', pid,
208      'start_timestamp', slice_ts,
209      'end_timestamp', slice_ts + slice_dur,
210      'slice_id', slice_id,
211      'slice_name', slice_name)),
212    'start_timestamp', MIN(slice_ts),
213    'end_timestamp', MAX(slice_ts + slice_dur))
214  FROM (
215    SELECT p.pid, tid, slice_ts, slice_dur, slice_id, slice_name
216    FROM android_thread_slices_for_all_startups slice, android_startup_processes p
217    WHERE
218      p.startup_id = $startup_id AND
219      slice.startup_id = $startup_id AND
220      (
221        slice_name GLOB "*semispace GC" OR
222        slice_name GLOB "*mark sweep GC" OR
223        slice_name GLOB "*concurrent copying GC"
224      )
225    ORDER BY slice_dur DESC
226    LIMIT $num_slices);
227
228CREATE OR REPLACE PERFETTO FUNCTION get_dur_on_main_thread_for_startup_and_slice(
229  startup_id LONG, slice_name STRING, num_slices INT)
230RETURNS PROTO AS
231  SELECT AndroidStartupMetric_TraceSliceSectionInfo(
232    'slice_section', RepeatedField(AndroidStartupMetric_TraceSliceSection(
233      'thread_tid', tid,
234      'process_pid', pid,
235      'start_timestamp', slice_ts,
236      'end_timestamp', slice_ts + slice_dur,
237      'slice_id', slice_id,
238      'slice_name', slice_name)),
239    'start_timestamp', MIN(slice_ts),
240    'end_timestamp', MAX(slice_ts + slice_dur))
241  FROM (
242    SELECT p.pid, tid, slice_ts, slice_dur, slice_id, slice_name
243    FROM android_thread_slices_for_all_startups l,
244      android_startup_processes p
245    WHERE l.startup_id = $startup_id AND p.startup_id == $startup_id
246      AND slice_name GLOB $slice_name
247    ORDER BY slice_dur DESC
248    LIMIT $num_slices);
249
250CREATE OR REPLACE PERFETTO FUNCTION get_main_thread_binder_transactions_blocked(
251  startup_id LONG, threshold DOUBLE, num_slices INT)
252RETURNS PROTO AS
253  SELECT AndroidStartupMetric_TraceSliceSectionInfo(
254    'slice_section', RepeatedField(AndroidStartupMetric_TraceSliceSection(
255      'thread_tid', tid,
256      'process_pid', pid,
257      'start_timestamp', slice_ts, 'end_timestamp', slice_ts + slice_dur,
258      'slice_id', slice_id, 'slice_name', slice_name)),
259    'start_timestamp', MIN(slice_ts),
260    'end_timestamp', MAX(slice_ts + slice_dur))
261  FROM (
262    SELECT pid, request.tid as tid, request.slice_ts as slice_ts, request.slice_dur as slice_dur,
263      request.id as slice_id, request.slice_name as slice_name
264    FROM (
265      SELECT p.pid, tid, slice_id as id, slice_dur, thread_name, process.name as process,
266        s.arg_set_id, is_main_thread,
267        slice_ts, s.utid, slice_name
268      FROM android_thread_slices_for_all_startups s,
269        android_startup_processes p
270      JOIN process ON (
271        EXTRACT_ARG(s.arg_set_id, "destination process") = process.pid
272      )
273      WHERE s.startup_id = $startup_id AND slice_name GLOB "binder transaction"
274        AND slice_dur > $threshold AND p.startup_id = $startup_id
275    ) request
276    JOIN following_flow(request.id) arrow
277    JOIN slice reply ON reply.id = arrow.slice_in
278    JOIN thread USING (utid)
279    WHERE reply.dur > $threshold AND request.is_main_thread
280    ORDER BY request.slice_dur DESC
281    LIMIT $num_slices);
282
283CREATE OR REPLACE PERFETTO FUNCTION get_slices_concurrent_to_launch(
284  startup_id INT, slice_glob STRING, num_slices INT, pid INT)
285RETURNS PROTO AS
286  SELECT AndroidStartupMetric_TraceSliceSectionInfo(
287    'slice_section', RepeatedField(AndroidStartupMetric_TraceSliceSection(
288      'thread_tid', tid,
289      'process_pid', $pid,
290      'start_timestamp', ts, 'end_timestamp', ts + dur,
291      'slice_id', id, 'slice_name', name)),
292    'start_timestamp', MIN(ts),
293    'end_timestamp', MAX(ts + dur))
294  FROM (
295    SELECT thread.tid, s.ts as ts, dur, s.id, s.name FROM slice s
296    JOIN thread_track t ON s.track_id = t.id
297    JOIN thread USING(utid)
298    JOIN (
299      SELECT ts, ts_end
300      FROM android_startups
301      WHERE startup_id = $startup_id
302    ) launch
303    WHERE
304      s.name GLOB $slice_glob AND
305      s.ts BETWEEN launch.ts AND launch.ts_end
306    ORDER BY dur DESC LIMIT $num_slices);
307
308CREATE OR REPLACE PERFETTO FUNCTION get_slices_for_startup_and_slice_name(
309  startup_id INT, slice_name STRING, num_slices INT, pid int)
310RETURNS PROTO AS
311  SELECT AndroidStartupMetric_TraceSliceSectionInfo(
312    'slice_section', RepeatedField(AndroidStartupMetric_TraceSliceSection(
313      'thread_tid', tid,
314      'process_pid', $pid,
315      'start_timestamp', slice_ts, 'end_timestamp', slice_ts + slice_dur,
316      'slice_id', slice_id, 'slice_name', slice_name)),
317    'start_timestamp', MIN(slice_ts),
318    'end_timestamp', MAX(slice_ts + slice_dur))
319  FROM (
320    SELECT tid, slice_ts, slice_dur, slice_id, slice_name
321    FROM android_thread_slices_for_all_startups
322    WHERE startup_id = $startup_id AND slice_name GLOB $slice_name
323    ORDER BY slice_dur DESC
324    LIMIT $num_slices);
325
326CREATE OR REPLACE PERFETTO FUNCTION get_process_running_concurrent_to_launch(
327  startup_id INT, process_glob STRING)
328RETURNS STRING AS
329  SELECT process.name
330     FROM sched
331     JOIN thread USING (utid)
332     JOIN process USING (upid)
333     JOIN (
334       SELECT ts, ts_end
335       FROM android_startups
336       WHERE startup_id = $startup_id
337       ) launch
338     WHERE
339       process.name GLOB $process_glob AND
340       sched.ts BETWEEN launch.ts AND launch.ts_end
341       ORDER BY (launch.ts_end - sched.ts) DESC
342       LIMIT 1;
343
344CREATE OR REPLACE PERFETTO FUNCTION get_slow_start_reason_with_details(startup_id LONG)
345RETURNS PROTO AS
346      SELECT RepeatedField(AndroidStartupMetric_SlowStartReason(
347        'reason_id', reason_id,
348        'reason', slow_cause,
349        'severity', severity,
350        'launch_dur', launch_dur,
351        'expected_value', expected_val,
352        'actual_value', actual_val,
353        'trace_slice_sections', trace_slices,
354        'trace_thread_sections', trace_threads,
355        'additional_info', extra))
356      FROM (
357        SELECT 'No baseline or cloud profiles' as slow_cause,
358          launch.dur as launch_dur,
359          'NO_BASELINE_OR_CLOUD_PROFILES' as reason_id,
360          'ERROR' as severity,
361          AndroidStartupMetric_ThresholdValue(
362            'value', FALSE,
363            'unit', 'TRUE_OR_FALSE') as expected_val,
364          AndroidStartupMetric_ActualValue(
365            'value', TRUE) as actual_val,
366          get_missing_baseline_profile_for_launch(launch.startup_id, launch.package)
367            as trace_slices,
368          NULL as trace_threads,
369          NULL as extra
370        FROM android_startups launch
371        WHERE launch.startup_id = $startup_id
372          AND missing_baseline_profile_for_launch(launch.startup_id, launch.package)
373
374        UNION ALL
375        SELECT 'Optimized artifacts missing, run from apk' as slow_cause,
376          launch.dur as launch_dur,
377          'RUN_FROM_APK' as reason_id,
378          'ERROR' as severity,
379          AndroidStartupMetric_ThresholdValue(
380            'value', FALSE,
381            'unit', 'TRUE_OR_FALSE') as expected_val,
382          AndroidStartupMetric_ActualValue(
383            'value', TRUE) as actual_val,
384          get_run_from_apk(launch.startup_id)
385            as trace_slices,
386          NULL as trace_threads,
387          NULL as extra
388        FROM android_startups launch
389        WHERE launch.startup_id = $startup_id
390          AND run_from_apk_for_launch(launch.startup_id)
391
392        UNION ALL
393        SELECT 'Unlock running during launch' as slow_cause,
394          launch.dur as launch_dur,
395          'UNLOCK_RUNNING' as reason_id,
396          'ERROR' as severity,
397          AndroidStartupMetric_ThresholdValue(
398            'value', FALSE,
399            'unit', 'TRUE_OR_FALSE') as expected_val,
400          AndroidStartupMetric_ActualValue(
401            'value', TRUE) as actual_val,
402          get_unlock_running_during_launch_slice(launch.startup_id,
403            (SELECT pid FROM android_startup_processes WHERE launch.startup_id = startup_id))
404            as trace_slices,
405          NULL as trace_threads,
406          NULL as extra
407        FROM android_startups launch
408        WHERE launch.startup_id = $startup_id
409         AND is_unlock_running_during_launch(launch.startup_id)
410
411        UNION ALL
412        SELECT 'App in debuggable mode' as slow_cause,
413          launch.dur as launch_dur,
414          'APP_IN_DEBUGGABLE_MODE' as reason_id,
415          'ERROR' as severity,
416          AndroidStartupMetric_ThresholdValue(
417            'value', FALSE,
418            'unit', 'TRUE_OR_FALSE') as expected_val,
419          AndroidStartupMetric_ActualValue(
420            'value', TRUE) as actual_val,
421          NULL as trace_slices,
422          NULL as trace_threads,
423          NULL as extra
424        FROM android_startups launch
425        WHERE launch.startup_id = $startup_id
426          AND is_process_debuggable(launch.package)
427
428        UNION ALL
429        SELECT 'GC Activity' as slow_cause,
430          launch.dur as launch_dur,
431          'GC_ACTIVITY' as reason_id,
432          'ERROR' as severity,
433          AndroidStartupMetric_ThresholdValue(
434            'value', FALSE,
435            'unit', 'TRUE_OR_FALSE') as expected_val,
436          AndroidStartupMetric_ActualValue(
437            'value', TRUE) as actual_val,
438          get_gc_activity(launch.startup_id, 1)
439            as trace_slices,
440          NULL as trace_threads,
441          NULL as extra
442        FROM android_startups launch
443        WHERE launch.startup_id = $startup_id
444          AND total_gc_time_by_launch(launch.startup_id) > 0
445
446        UNION ALL
447        SELECT 'dex2oat running during launch' AS slow_cause,
448          launch.dur as launch_dur,
449          'DEX2OAT_RUNNING' as reason_id,
450          'WARNING' as severity,
451          AndroidStartupMetric_ThresholdValue(
452            'value', FALSE,
453            'unit', 'TRUE_OR_FALSE') as expected_val,
454          AndroidStartupMetric_ActualValue(
455            'value', TRUE) as actual_val,
456          NULL as trace_slices,
457          NULL as trace_threads,
458          'Process: ' || get_process_running_concurrent_to_launch(launch.startup_id, '*dex2oat64')
459            as extra
460        FROM android_startups launch
461        WHERE launch.startup_id = $startup_id AND
462          dur_of_process_running_concurrent_to_launch(launch.startup_id, '*dex2oat64') > 0
463
464        UNION ALL
465        SELECT 'installd running during launch' AS slow_cause,
466          launch.dur as launch_dur,
467          'INSTALLD_RUNNING' as reason_id,
468          'ERROR' as severity,
469          AndroidStartupMetric_ThresholdValue(
470            'value', FALSE,
471            'unit', 'TRUE_OR_FALSE') as expected_val,
472          AndroidStartupMetric_ActualValue(
473            'value', TRUE) as actual_val,
474          NULL as trace_slices,
475          NULL as trace_threads,
476          'Process: ' || get_process_running_concurrent_to_launch(launch.startup_id, '*installd')
477            as extra
478        FROM android_startups launch
479        WHERE launch.startup_id = $startup_id AND
480          dur_of_process_running_concurrent_to_launch(launch.startup_id, '*installd') > 0
481
482        UNION ALL
483        SELECT 'Main Thread - Time spent in Runnable state' as slow_cause,
484          launch.dur as launch_dur,
485          'MAIN_THREAD_TIME_SPENT_IN_RUNNABLE' as reason_id,
486          'WARNING' as severity,
487          AndroidStartupMetric_ThresholdValue(
488            'value', threshold_runnable_percentage(),
489            'unit', 'PERCENTAGE',
490            'higher_expected', FALSE) as expected_val,
491          AndroidStartupMetric_ActualValue(
492            'value',
493              main_thread_time_for_launch_in_runnable_state(launch.startup_id) * 100 / launch.dur,
494            'dur', main_thread_time_for_launch_in_runnable_state(launch.startup_id)) as actual_val,
495          NULL as trace_slices,
496          get_main_thread_time_for_launch_in_runnable_state(launch.startup_id, 3)
497            as trace_threads,
498          NULL as extra
499        FROM android_startups launch
500        WHERE launch.startup_id = $startup_id
501          AND main_thread_time_for_launch_in_runnable_state(launch.startup_id) >
502            launch.dur / 100 * threshold_runnable_percentage()
503
504        UNION ALL
505        SELECT 'Main Thread - Time spent in interruptible sleep state' as slow_cause,
506          launch.dur as launch_dur,
507          'MAIN_THREAD_TIME_SPENT_IN_INTERRUPTIBLE_SLEEP' as reason_id,
508          'WARNING' as severity,
509          AndroidStartupMetric_ThresholdValue(
510            'value', threshold_interruptible_sleep_ns(),
511            'unit', 'NS',
512            'higher_expected', FALSE) as expected_val,
513          AndroidStartupMetric_ActualValue(
514            'value', main_thread_time_for_launch_and_state(launch.startup_id, 'S')) as actual_val,
515          NULL as trace_slices,
516          get_main_thread_time_for_launch_and_state(launch.startup_id, 'S', 3)
517            as trace_threads,
518          NULL as extra
519        FROM android_startups launch
520        WHERE launch.startup_id = $startup_id
521          AND main_thread_time_for_launch_and_state(launch.startup_id, 'S') >
522            threshold_interruptible_sleep_ns()
523
524        UNION ALL
525        SELECT 'Main Thread - Time spent in Blocking I/O' as slow_cause,
526          launch.dur as launch_dur,
527          'MAIN_THREAD_TIME_SPENT_IN_BLOCKING_IO' as reason_id,
528          'WARNING' as severity,
529          AndroidStartupMetric_ThresholdValue(
530            'value', threshold_blocking_io_ns(),
531            'unit', 'NS',
532            'higher_expected', FALSE) as expected_val,
533          AndroidStartupMetric_ActualValue(
534            'value', main_thread_time_for_launch_state_and_io_wait(
535              launch.startup_id, 'D*', TRUE)) as actual_val,
536          NULL as trace_slices,
537          get_main_thread_time_for_launch_state_and_io_wait(
538            launch.startup_id, 'D*', TRUE, 3)
539            as trace_threads,
540          NULL as extra
541        FROM android_startups launch
542        WHERE launch.startup_id = $startup_id
543          AND main_thread_time_for_launch_state_and_io_wait(launch.startup_id, 'D*', TRUE) >
544            threshold_blocking_io_ns()
545
546        UNION ALL
547        SELECT 'Main Thread - Time spent in OpenDexFilesFromOat*' as slow_cause,
548          launch.dur as launch_dur,
549          'MAIN_THREAD_TIME_SPENT_IN_OPEN_DEX_FILES_FROM_OAT' as reason_id,
550          'WARNING' as severity,
551          AndroidStartupMetric_ThresholdValue(
552            'value', threshold_open_dex_files_from_oat_percentage(),
553            'unit', 'PERCENTAGE',
554            'higher_expected', FALSE) as expected_val,
555          AndroidStartupMetric_ActualValue(
556            'value', android_sum_dur_on_main_thread_for_startup_and_slice(
557              launch.startup_id, 'OpenDexFilesFromOat*') * 100 / launch.dur,
558            'dur', android_sum_dur_on_main_thread_for_startup_and_slice(
559              launch.startup_id, 'OpenDexFilesFromOat*')) as actual_val,
560          get_dur_on_main_thread_for_startup_and_slice(launch.startup_id, 'OpenDexFilesFromOat*', 3)
561            as trace_slices,
562          NULL as trace_threads,
563          NULL as extra
564        FROM android_startups launch
565        WHERE launch.startup_id = $startup_id AND
566          android_sum_dur_on_main_thread_for_startup_and_slice(
567          launch.startup_id, 'OpenDexFilesFromOat*') >
568            launch.dur / 100 * threshold_open_dex_files_from_oat_percentage()
569
570        UNION ALL
571        SELECT 'Time spent in bindApplication' as slow_cause,
572          launch.dur as launch_dur,
573          'TIME_SPENT_IN_BIND_APPLICATION' as reason_id,
574          'WARNING' as severity,
575          AndroidStartupMetric_ThresholdValue(
576            'value', threshold_bind_application_ns(),
577            'unit', 'NS',
578            'higher_expected', FALSE) as expected_val,
579          AndroidStartupMetric_ActualValue(
580            'value', android_sum_dur_for_startup_and_slice(
581              launch.startup_id, 'bindApplication')) as actual_val,
582          get_dur_on_main_thread_for_startup_and_slice(launch.startup_id, 'bindApplication', 3)
583            as trace_slices,
584          NULL as trace_threads,
585          NULL as extra
586        FROM android_startups launch
587        WHERE launch.startup_id = $startup_id
588          AND android_sum_dur_for_startup_and_slice(launch.startup_id, 'bindApplication') >
589            threshold_bind_application_ns()
590
591        UNION ALL
592        SELECT 'Time spent in view inflation' as slow_cause,
593          launch.dur as launch_dur,
594          'TIME_SPENT_IN_VIEW_INFLATION' as reason_id,
595          'WARNING' as severity,
596          AndroidStartupMetric_ThresholdValue(
597            'value', threshold_view_inflation_ns(),
598            'unit', 'NS',
599            'higher_expected', FALSE) as expected_val,
600          AndroidStartupMetric_ActualValue(
601            'value', android_sum_dur_for_startup_and_slice(
602              launch.startup_id, 'inflate')) as actual_val,
603          get_dur_on_main_thread_for_startup_and_slice(launch.startup_id, 'inflate', 3)
604            as trace_slices,
605          NULL as trace_threads,
606          NULL as extra
607        FROM android_startups launch
608        WHERE launch.startup_id = $startup_id
609          AND android_sum_dur_for_startup_and_slice(launch.startup_id, 'inflate') >
610            threshold_view_inflation_ns()
611
612        UNION ALL
613        SELECT 'Time spent in ResourcesManager#getResources' as slow_cause,
614          launch.dur as launch_dur,
615          'TIME_SPENT_IN_RESOURCES_MANAGER_GET_RESOURCES' as reason_id,
616          'WARNING' as severity,
617          AndroidStartupMetric_ThresholdValue(
618            'value', threshold_resources_manager_get_resources_ns(),
619            'unit', 'NS',
620            'higher_expected', FALSE) as expected_val,
621          AndroidStartupMetric_ActualValue(
622            'value', android_sum_dur_for_startup_and_slice(
623              launch.startup_id, 'ResourcesManager#getResources')) as actual_val,
624          get_dur_on_main_thread_for_startup_and_slice(
625            launch.startup_id, 'ResourcesManager#getResources', 3)
626            as trace_slices,
627          NULL as trace_threads,
628          NULL as extra
629        FROM android_startups launch
630        WHERE launch.startup_id = $startup_id
631          AND android_sum_dur_for_startup_and_slice(
632          launch.startup_id, 'ResourcesManager#getResources') >
633            threshold_resources_manager_get_resources_ns()
634
635        UNION ALL
636        SELECT 'Time spent verifying classes' as slow_cause,
637          launch.dur as launch_dur,
638          'TIME_SPENT_VERIFYING_CLASSES' as reason_id,
639          'WARNING' as severity,
640          AndroidStartupMetric_ThresholdValue(
641            'value', threshold_verify_classes_percentage(),
642            'unit', 'PERCENTAGE',
643            'higher_expected', FALSE) as expected_val,
644          AndroidStartupMetric_ActualValue(
645            'value', android_sum_dur_for_startup_and_slice(
646              launch.startup_id, 'VerifyClass*') * 100 / launch.dur,
647            'dur', android_sum_dur_for_startup_and_slice(
648              launch.startup_id, 'VerifyClass*')) as actual_val,
649          get_dur_on_main_thread_for_startup_and_slice(launch.startup_id, 'VerifyClass*', 3)
650            as trace_slices,
651          NULL as trace_threads,
652          NULL as extra
653        FROM android_startups launch
654        WHERE launch.startup_id = $startup_id AND
655          android_sum_dur_for_startup_and_slice(launch.startup_id, 'VerifyClass*')
656            > launch.dur / 100 * threshold_verify_classes_percentage()
657
658        UNION ALL
659        SELECT 'Potential CPU contention with another process' AS slow_cause,
660          launch.dur as launch_dur,
661          'POTENTIAL_CPU_CONTENTION_WITH_ANOTHER_PROCESS' as reason_id,
662          'WARNING' as severity,
663          AndroidStartupMetric_ThresholdValue(
664            'value', threshold_potential_cpu_contention_ns(),
665            'unit', 'NS',
666            'higher_expected', FALSE) as expected_val,
667          AndroidStartupMetric_ActualValue(
668            'value',
669              main_thread_time_for_launch_in_runnable_state(launch.startup_id)) as actual_val,
670          NULL as trace_slices,
671          get_main_thread_time_for_launch_in_runnable_state(launch.startup_id, 3)
672            as trace_threads,
673          NULL as extra
674        FROM android_startups launch
675        WHERE launch.startup_id = $startup_id AND
676          main_thread_time_for_launch_in_runnable_state(launch.startup_id) >
677            threshold_potential_cpu_contention_ns() AND
678          most_active_process_for_launch(launch.startup_id) IS NOT NULL
679
680        UNION ALL
681        SELECT 'JIT Activity' as slow_cause,
682          launch.dur as launch_dur,
683          'JIT_ACTIVITY' as reason_id,
684          'WARNING' as severity,
685          AndroidStartupMetric_ThresholdValue(
686            'value', threshold_jit_activity_ns(),
687            'unit', 'NS',
688            'higher_expected', FALSE) as expected_val,
689          AndroidStartupMetric_ActualValue(
690            'value', thread_time_for_launch_state_and_thread(
691              launch.startup_id, 'Running', 'Jit thread pool')) as actual_val,
692          NULL as trace_slices,
693          get_thread_time_for_launch_state_and_thread(
694            launch.startup_id, 'Running', 'Jit thread pool', 3)
695            as trace_threads,
696          NULL as extra
697        FROM android_startups launch
698        WHERE launch.startup_id = $startup_id
699        AND thread_time_for_launch_state_and_thread(
700          launch.startup_id,
701          'Running',
702          'Jit thread pool'
703        ) > threshold_jit_activity_ns()
704
705        UNION ALL
706        SELECT 'Main Thread - Lock contention' as slow_cause,
707          launch.dur as launch_dur,
708          'MAIN_THREAD_LOCK_CONTENTION' as reason_id,
709          'WARNING' as severity,
710          AndroidStartupMetric_ThresholdValue(
711            'value', threshold_lock_contention_percentage(),
712            'unit', 'PERCENTAGE',
713            'higher_expected', FALSE) as expected_val,
714          AndroidStartupMetric_ActualValue(
715            'value', android_sum_dur_on_main_thread_for_startup_and_slice(
716              launch.startup_id, 'Lock contention on*') * 100 / launch.dur,
717            'dur', android_sum_dur_on_main_thread_for_startup_and_slice(
718              launch.startup_id, 'Lock contention on*')) as actual_val,
719          get_dur_on_main_thread_for_startup_and_slice(launch.startup_id, 'Lock contention on*', 3)
720            as trace_slices,
721          NULL as trace_threads,
722          NULL as extra
723        FROM android_startups launch
724        WHERE launch.startup_id = $startup_id
725          AND android_sum_dur_on_main_thread_for_startup_and_slice(
726          launch.startup_id,
727          'Lock contention on*'
728        ) > launch.dur / 100 * threshold_lock_contention_percentage()
729
730        UNION ALL
731        SELECT 'Main Thread - Monitor contention' as slow_cause,
732          launch.dur as launch_dur,
733          'MAIN_THREAD_MONITOR_CONTENTION' as reason_id,
734          'WARNING' as severity,
735          AndroidStartupMetric_ThresholdValue(
736            'value', threshold_monitor_contention_percentage(),
737            'unit', 'PERCENTAGE',
738            'higher_expected', FALSE) as expected_val,
739          AndroidStartupMetric_ActualValue(
740            'value', android_sum_dur_on_main_thread_for_startup_and_slice(
741              launch.startup_id, 'Lock contention on a monitor*') * 100 / launch.dur,
742            'dur', android_sum_dur_on_main_thread_for_startup_and_slice(
743              launch.startup_id, 'Lock contention on a monitor*')) as actual_val,
744          get_dur_on_main_thread_for_startup_and_slice(
745            launch.startup_id, 'Lock contention on a monitor*', 3)
746            as trace_slices,
747          NULL as trace_threads,
748          NULL as extra
749        FROM android_startups launch
750        WHERE launch.startup_id = $startup_id
751          AND android_sum_dur_on_main_thread_for_startup_and_slice(
752            launch.startup_id,
753            'Lock contention on a monitor*'
754          ) > launch.dur / 100 * threshold_monitor_contention_percentage()
755
756        UNION ALL
757        SELECT 'JIT compiled methods' as slow_cause,
758          launch.dur as launch_dur,
759          'JIT_COMPILED_METHODS' as reason_id,
760          'WARNING' as severity,
761          AndroidStartupMetric_ThresholdValue(
762            'value', threshold_jit_compiled_methods_count(),
763            'unit', 'COUNT',
764            'higher_expected', FALSE) as expected_val,
765          AndroidStartupMetric_ActualValue(
766            'value', (SELECT COUNT(1)
767              FROM ANDROID_SLICES_FOR_STARTUP_AND_SLICE_NAME(launch.startup_id, 'JIT compiling*')
768              WHERE thread_name = 'Jit thread pool')) as actual_val,
769          get_slices_for_startup_and_slice_name(launch.startup_id, 'JIT compiling*', 3,
770            (SELECT pid FROM android_startup_processes WHERE launch.startup_id = startup_id))
771            as trace_slices,
772          NULL as traced_threads,
773          NULL as extra
774        FROM android_startups launch
775        WHERE launch.startup_id = $startup_id
776          AND (
777          SELECT COUNT(1)
778          FROM ANDROID_SLICES_FOR_STARTUP_AND_SLICE_NAME(launch.startup_id, 'JIT compiling*')
779          WHERE thread_name = 'Jit thread pool') > threshold_jit_compiled_methods_count()
780
781        UNION ALL
782        SELECT 'Broadcast dispatched count' as slow_cause,
783          launch.dur as launch_dur,
784          'BROADCAST_DISPATCHED_COUNT' as reason_id,
785          'WARNING' as severity,
786          AndroidStartupMetric_ThresholdValue(
787            'value', threshold_broadcast_dispatched_count(),
788            'unit', 'COUNT',
789            'higher_expected', FALSE) as expected_val,
790          AndroidStartupMetric_ActualValue(
791            'value', count_slices_concurrent_to_launch(launch.startup_id,
792              'Broadcast dispatched*')) as actual_val,
793          get_slices_concurrent_to_launch(launch.startup_id, 'Broadcast dispatched*', 3,
794            (SELECT pid FROM android_startup_processes WHERE launch.startup_id = startup_id))
795            as trace_slices,
796          NULL as trace_threads,
797          NULL as extra
798        FROM android_startups launch
799        WHERE launch.startup_id = $startup_id
800          AND count_slices_concurrent_to_launch(
801          launch.startup_id,
802          'Broadcast dispatched*') > threshold_broadcast_dispatched_count()
803
804        UNION ALL
805        SELECT 'Broadcast received count' as slow_cause,
806          launch.dur as launch_dur,
807          'BROADCAST_RECEIVED_COUNT' as reason_id,
808          'WARNING' as severity,
809          AndroidStartupMetric_ThresholdValue(
810            'value', threshold_broadcast_received_count(),
811            'unit', 'COUNT',
812            'higher_expected', FALSE) as expected_val,
813          AndroidStartupMetric_ActualValue(
814            'value', count_slices_concurrent_to_launch(launch.startup_id,
815              'broadcastReceiveReg*')) as actual_val,
816          get_slices_concurrent_to_launch(launch.startup_id, 'broadcastReceiveReg*', 3,
817            (SELECT pid FROM android_startup_processes WHERE launch.startup_id = startup_id))
818            as trace_slices,
819          NULL as trace_threads,
820          NULL as extra
821        FROM android_startups launch
822        WHERE launch.startup_id = $startup_id
823          AND count_slices_concurrent_to_launch(
824            launch.startup_id,
825            'broadcastReceiveReg*') > threshold_broadcast_received_count()
826
827        UNION ALL
828        SELECT 'Startup running concurrent to launch' as slow_cause,
829          launch.dur as launch_dur,
830          'STARTUP_RUNNING_CONCURRENT' as reason_id,
831          'ERROR' as severity,
832          AndroidStartupMetric_ThresholdValue(
833            'value', FALSE,
834            'unit', 'TRUE_OR_FALSE') as expected_val,
835          AndroidStartupMetric_ActualValue(
836            'value', TRUE) as actual_val,
837          NULL as trace_slices,
838          NULL as trace_threads,
839          'Package: ' || (
840            SELECT package
841            FROM android_startups l
842            WHERE l.startup_id != launch.startup_id
843              AND _is_spans_overlapping(l.ts, l.ts_end, launch.ts, launch.ts_end)
844              LIMIT 1) as extra
845        FROM android_startups launch
846        WHERE launch.startup_id = $startup_id
847          AND EXISTS(
848          SELECT package
849          FROM android_startups l
850          WHERE l.startup_id != launch.startup_id
851            AND _is_spans_overlapping(l.ts, l.ts_end, launch.ts, launch.ts_end))
852
853        UNION ALL
854        SELECT 'Main Thread - Binder transactions blocked' as slow_cause,
855          launch.dur as launch_dur,
856          'MAIN_THREAD_BINDER_TRANSCATIONS_BLOCKED' as reason_id,
857          'WARNING' as severity,
858          AndroidStartupMetric_ThresholdValue(
859            'value', FALSE,
860            'unit', 'TRUE_OR_FALSE') as expected_val,
861          AndroidStartupMetric_ActualValue(
862            'value', TRUE) as actual_val,
863          get_main_thread_binder_transactions_blocked(launch.startup_id, 2e7, 3)
864            as trace_slices,
865          NULL as trace_threads,
866          NULL as extra
867        FROM android_startups launch
868        WHERE launch.startup_id = $startup_id
869          AND (
870          SELECT COUNT(1)
871          FROM BINDER_TRANSACTION_REPLY_SLICES_FOR_LAUNCH(launch.startup_id, 2e7)) > 0
872    );
873