• 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--
16
17SELECT RUN_METRIC('android/cpu_info.sql');
18
19-- Create the base tables and views containing the launch spans.
20INCLUDE PERFETTO MODULE android.startup.startups;
21
22-- TTID and TTFD
23INCLUDE PERFETTO MODULE android.startup.time_to_display;
24
25SELECT RUN_METRIC('android/process_metadata.sql');
26
27-- Define the helper functions which will be used throught the remainder
28-- of the metric.
29SELECT RUN_METRIC('android/startup/slice_functions.sql');
30INCLUDE PERFETTO MODULE intervals.overlap;
31
32-- Define helper functions related to slow start reasons
33SELECT RUN_METRIC('android/startup/slow_start_reasons.sql');
34
35-- Run all the HSC metrics.
36SELECT RUN_METRIC('android/startup/hsc.sql');
37
38-- Define some helper functions related to breaking down thread state
39-- for launches.
40SELECT RUN_METRIC('android/startup/thread_state_breakdown.sql');
41
42-- Define helper functions to break down slices/threads by thread
43-- state.
44SELECT RUN_METRIC('android/startup/mcycles_per_launch.sql');
45
46-- Define helper functions for GC slices.
47SELECT RUN_METRIC('android/startup/gc_slices.sql');
48
49-- Define helper functions for system state.
50SELECT RUN_METRIC('android/startup/system_state.sql');
51
52CREATE OR REPLACE PERFETTO FUNCTION _is_spans_overlapping(
53  ts1 LONG,
54  ts_end1 LONG,
55  ts2 LONG,
56  ts_end2 LONG)
57RETURNS BOOL AS
58SELECT (IIF($ts1 < $ts2, $ts2, $ts1)
59      < IIF($ts_end1 < $ts_end2, $ts_end1, $ts_end2));
60
61-- Returns the slices for forked processes. Never present in hot starts.
62-- Prefer this over process start_ts, since the process might have
63-- been preforked.
64CREATE OR REPLACE PERFETTO FUNCTION zygote_fork_for_launch(startup_id INT)
65RETURNS TABLE(ts INT, dur INT) AS
66SELECT slice.ts, slice.dur
67FROM android_startups l
68JOIN slice ON (
69  l.ts < slice.ts AND
70  slice.ts + slice.dur < l.ts_end AND
71  STR_SPLIT(slice.name, ': ', 1) = l.package
72)
73WHERE l.startup_id = $startup_id AND slice.name GLOB 'Start proc: *';
74
75-- Returns the fully drawn slice proto given a launch id.
76CREATE OR REPLACE PERFETTO FUNCTION report_fully_drawn_for_launch(startup_id INT)
77RETURNS PROTO AS
78SELECT
79  startup_slice_proto(report_fully_drawn_ts - launch_ts)
80FROM (
81  SELECT
82    launches.ts AS launch_ts,
83    min(slice.ts) AS report_fully_drawn_ts
84  FROM android_startups launches
85  JOIN android_startup_processes ON (launches.startup_id = android_startup_processes.startup_id)
86  JOIN thread USING (upid)
87  JOIN thread_track USING (utid)
88  JOIN slice ON (slice.track_id = thread_track.id)
89  WHERE
90    slice.name GLOB "reportFullyDrawn*" AND
91    slice.ts >= launches.ts AND
92    launches.startup_id = $startup_id
93);
94
95-- Given a launch id and GLOB for a slice name, returns the N longest slice name and duration.
96CREATE OR REPLACE PERFETTO FUNCTION get_long_slices_for_launch(
97  startup_id INT, slice_name STRING, top_n INT)
98RETURNS TABLE(slice_name STRING, slice_dur INT) AS
99SELECT slice_name, slice_dur
100FROM android_thread_slices_for_all_startups s
101WHERE s.startup_id = $startup_id AND s.slice_name GLOB $slice_name
102ORDER BY slice_dur DESC
103LIMIT $top_n;
104
105-- Returns the number of CPUs.
106CREATE OR REPLACE PERFETTO FUNCTION get_number_of_cpus()
107RETURNS INT AS
108SELECT COUNT(DISTINCT cpu)
109FROM core_type_per_cpu;
110
111-- Define the view
112DROP VIEW IF EXISTS startup_view;
113CREATE PERFETTO VIEW startup_view AS
114SELECT
115  AndroidStartupMetric_Startup(
116    'startup_id', launches.startup_id,
117    'startup_type', launches.startup_type,
118    'cpu_count', (
119      SELECT COUNT(DISTINCT cpu) from sched
120    ),
121    'package_name', launches.package,
122    'process_name', (
123      SELECT p.name
124      FROM android_startup_processes lp
125      JOIN process p USING (upid)
126      WHERE lp.startup_id =launches.startup_id
127      LIMIT 1
128    ),
129    'process', (
130      SELECT m.metadata
131      FROM process_metadata m
132      JOIN android_startup_processes p USING (upid)
133      WHERE p.startup_id =launches.startup_id
134      LIMIT 1
135    ),
136    'activities', (
137      SELECT RepeatedField(AndroidStartupMetric_Activity(
138        'name', (SELECT STR_SPLIT(s.slice_name, ':', 1)),
139        'method', (SELECT STR_SPLIT(s.slice_name, ':', 0)),
140        'ts_method_start', s.slice_ts
141        ))
142      FROM thread_slices_for_all_launches s
143      WHERE
144        s.startup_id =launches.startup_id
145        AND (s.slice_name GLOB 'performResume:*' OR s.slice_name GLOB 'performCreate:*')
146    ),
147    'long_binder_transactions', (
148      SELECT RepeatedField(
149        AndroidStartupMetric_BinderTransaction(
150          "duration", startup_slice_proto(s.slice_dur),
151          "thread", s.thread_name,
152          "destination_thread", EXTRACT_ARG(s.arg_set_id, "destination name"),
153          "destination_process", s.process,
154          "flags", EXTRACT_ARG(s.arg_set_id, "flags"),
155          "code", EXTRACT_ARG(s.arg_set_id, "code"),
156          "data_size", EXTRACT_ARG(s.arg_set_id, "data_size")
157        )
158      )
159      FROM ANDROID_BINDER_TRANSACTION_SLICES_FOR_STARTUP(launches.startup_id, 2e7) s
160    ),
161    'zygote_new_process', EXISTS(SELECT TRUE FROM ZYGOTE_FORK_FOR_LAUNCH(launches.startup_id)),
162    'activity_hosting_process_count', (
163      SELECT COUNT(1) FROM android_startup_processes p
164      WHERE p.startup_id =launches.startup_id
165    ),
166    'time_to_initial_display', (
167      SELECT time_to_initial_display
168      FROM android_startup_time_to_display s
169      WHERE s.startup_id = launches.startup_id
170    ),
171    'time_to_full_display', (
172      SELECT time_to_full_display
173      FROM android_startup_time_to_display s
174      WHERE s.startup_id = launches.startup_id
175    ),
176    'event_timestamps', AndroidStartupMetric_EventTimestamps(
177      'intent_received', launches.ts,
178      'first_frame', launches.ts_end
179    ),
180    'to_first_frame', AndroidStartupMetric_ToFirstFrame(
181      'dur_ns', launches.dur,
182      'dur_ms', launches.dur / 1e6,
183      'main_thread_by_task_state', AndroidStartupMetric_TaskStateBreakdown(
184        'running_dur_ns', IFNULL(
185          main_thread_time_for_launch_and_state(launches.startup_id, 'Running'), 0
186        ),
187        'runnable_dur_ns', IFNULL(
188          main_thread_time_for_launch_in_runnable_state(launches.startup_id), 0
189        ),
190        'uninterruptible_sleep_dur_ns', IFNULL(
191          main_thread_time_for_launch_and_state(launches.startup_id, 'D*'), 0
192        ),
193        'interruptible_sleep_dur_ns', IFNULL(
194          main_thread_time_for_launch_and_state(launches.startup_id, 'S'), 0
195        ),
196        'uninterruptible_io_sleep_dur_ns', IFNULL(
197          main_thread_time_for_launch_state_and_io_wait(launches.startup_id, 'D*', TRUE), 0
198        ),
199        'uninterruptible_non_io_sleep_dur_ns', IFNULL(
200          main_thread_time_for_launch_state_and_io_wait(launches.startup_id, 'D*', FALSE), 0
201        )
202
203      ),
204      'mcycles_by_core_type', NULL_IF_EMPTY(AndroidStartupMetric_McyclesByCoreType(
205        'little', mcycles_for_launch_and_core_type(launches.startup_id, 'little'),
206        'big', mcycles_for_launch_and_core_type(launches.startup_id, 'big'),
207        'bigger', mcycles_for_launch_and_core_type(launches.startup_id, 'bigger'),
208        'unknown', mcycles_for_launch_and_core_type(launches.startup_id, 'unknown')
209      )),
210      'to_post_fork',
211      launch_to_main_thread_slice_proto(launches.startup_id, 'PostFork'),
212      'to_activity_thread_main',
213      launch_to_main_thread_slice_proto(launches.startup_id, 'ActivityThreadMain'),
214      'to_bind_application',
215      launch_to_main_thread_slice_proto(launches.startup_id, 'bindApplication'),
216      'time_activity_manager', (
217        SELECT startup_slice_proto(l.ts - launches.ts)
218        FROM _startup_events l
219        WHERE l.ts BETWEEN launches.ts AND launches.ts + launches.dur
220      ),
221      'time_post_fork',
222      dur_sum_slice_proto_for_launch(launches.startup_id, 'PostFork'),
223      'time_activity_thread_main',
224      dur_sum_slice_proto_for_launch(launches.startup_id, 'ActivityThreadMain'),
225      'time_bind_application',
226      dur_sum_slice_proto_for_launch(launches.startup_id, 'bindApplication'),
227      'time_activity_start',
228      dur_sum_slice_proto_for_launch(launches.startup_id, 'activityStart'),
229      'time_activity_resume',
230      dur_sum_slice_proto_for_launch(launches.startup_id, 'activityResume'),
231      'time_activity_restart',
232      dur_sum_slice_proto_for_launch(launches.startup_id, 'activityRestart'),
233      'time_choreographer',
234      dur_sum_slice_proto_for_launch(launches.startup_id, 'Choreographer#doFrame*'),
235      'time_inflate',
236      dur_sum_slice_proto_for_launch(launches.startup_id, 'inflate'),
237      'time_get_resources',
238      dur_sum_slice_proto_for_launch(launches.startup_id, 'ResourcesManager#getResources'),
239      'time_class_initialization',
240      dur_sum_slice_proto_for_launch(launches.startup_id, 'L*/*;'),
241      'time_dex_open',
242      dur_sum_slice_proto_for_launch(launches.startup_id, 'OpenDexFilesFromOat*'),
243      'time_verify_class',
244      dur_sum_slice_proto_for_launch(launches.startup_id, 'VerifyClass*'),
245      'time_gc_total', (
246        SELECT NULL_IF_EMPTY(startup_slice_proto(total_gc_time_by_launch(launches.startup_id)))
247      ),
248      'time_dex_open_thread_main',
249      dur_sum_main_thread_slice_proto_for_launch(
250        launches.startup_id,
251        'OpenDexFilesFromOat*'),
252      'time_dlopen_thread_main',
253      dur_sum_main_thread_slice_proto_for_launch(
254        launches.startup_id,
255        'dlopen:*.so'),
256      'time_lock_contention_thread_main',
257      dur_sum_main_thread_slice_proto_for_launch(
258        launches.startup_id,
259        'Lock contention on*'
260      ),
261      'time_monitor_contention_thread_main',
262      dur_sum_main_thread_slice_proto_for_launch(
263        launches.startup_id,
264        'Lock contention on a monitor*'
265      ),
266      'time_before_start_process', (
267        SELECT startup_slice_proto(ts - launches.ts)
268        FROM ZYGOTE_FORK_FOR_LAUNCH(launches.startup_id)
269      ),
270      'time_to_running_state',
271      time_to_running_state_for_launch(launches.startup_id),
272      'time_jit_thread_pool_on_cpu', NULL_IF_EMPTY(startup_slice_proto(
273        thread_time_for_launch_state_and_thread(
274         launches.startup_id,
275          'Running',
276          'Jit thread pool'
277        )
278      )),
279      'time_gc_on_cpu', (
280        SELECT startup_slice_proto(sum_dur)
281        FROM running_gc_slices_materialized
282        WHERE launches.startup_id = startup_id
283      ),
284      'time_during_start_process', (
285        SELECT startup_slice_proto(dur)
286        FROM ZYGOTE_FORK_FOR_LAUNCH(launches.startup_id)
287      ),
288      'jit_compiled_methods', (
289        SELECT IIF(COUNT(1) = 0, NULL, COUNT(1))
290        FROM ANDROID_SLICES_FOR_STARTUP_AND_SLICE_NAME(launches.startup_id, 'JIT compiling*')
291        WHERE thread_name = 'Jit thread pool'
292      ),
293      'class_initialization_count', (
294        SELECT IIF(COUNT(1) = 0, NULL, COUNT(1))
295        FROM ANDROID_SLICES_FOR_STARTUP_AND_SLICE_NAME(launches.startup_id, 'L*/*;')
296      ),
297      'other_processes_spawned_count', (
298        SELECT COUNT(1)
299        FROM process
300        WHERE
301          process.start_ts BETWEEN launches.ts AND launches.ts + launches.dur
302          AND process.upid NOT IN (
303            SELECT upid FROM android_startup_processes
304            WHERE android_startup_processes.startup_id =launches.startup_id
305          )
306      )
307    ),
308    'hsc', NULL_IF_EMPTY(AndroidStartupMetric_HscMetrics(
309      'full_startup', (
310        SELECT startup_slice_proto(h.ts_total)
311        FROM hsc_based_startup_times h
312        WHERE h.id =launches.startup_id
313      )
314    )),
315    'report_fully_drawn', NULL_IF_EMPTY(report_fully_drawn_for_launch(launches.startup_id)),
316    'optimization_status', (
317      SELECT RepeatedField(AndroidStartupMetric_OptimizationStatus(
318        'location', SUBSTR(STR_SPLIT(slice_name, ' status=', 0), LENGTH('location=') + 1),
319        'odex_status', STR_SPLIT(STR_SPLIT(slice_name, ' status=', 1), ' filter=', 0),
320        'compilation_filter', STR_SPLIT(STR_SPLIT(slice_name, ' filter=', 1), ' reason=', 0),
321        'compilation_reason', STR_SPLIT(slice_name, ' reason=', 1),
322        'summary',
323        summary_for_optimization_status(
324          SUBSTR(STR_SPLIT(slice_name, ' status=', 0), LENGTH('location=') + 1),
325          STR_SPLIT(STR_SPLIT(slice_name, ' status=', 1), ' filter=', 0),
326          STR_SPLIT(STR_SPLIT(slice_name, ' filter=', 1), ' reason=', 0),
327          STR_SPLIT(slice_name, ' reason=', 1))
328        ))
329      FROM (
330        SELECT *
331        FROM ANDROID_SLICES_FOR_STARTUP_AND_SLICE_NAME(
332         launches.startup_id,
333          'location=* status=* filter=* reason=*'
334        )
335        ORDER BY slice_name
336      )
337    ),
338    'verify_class', (
339      SELECT RepeatedField(AndroidStartupMetric_VerifyClass(
340        'name', STR_SPLIT(slice_name, "VerifyClass ", 1),
341        'dur_ns', slice_dur))
342      FROM GET_LONG_SLICES_FOR_LAUNCH(launches.startup_id, "VerifyClass *", 5)
343    ),
344    'startup_concurrent_to_launch', (
345      SELECT RepeatedField(package)
346      FROM android_startups l
347      WHERE l.startup_id != launches.startup_id
348        AND _is_spans_overlapping(l.ts, l.ts_end, launches.ts, launches.ts_end)
349    ),
350    'dlopen_file', (
351      SELECT RepeatedField(STR_SPLIT(slice_name, "dlopen: ", 1))
352      FROM android_thread_slices_for_all_startups s
353      WHERE startup_id = launches.startup_id AND slice_name GLOB "dlopen: *.so"
354    ),
355    'system_state', AndroidStartupMetric_SystemState(
356      'dex2oat_running',
357      dur_of_process_running_concurrent_to_launch(launches.startup_id, '*dex2oat64') > 0,
358      'installd_running',
359      dur_of_process_running_concurrent_to_launch(launches.startup_id, '*installd') > 0,
360      'broadcast_dispatched_count',
361      count_slices_concurrent_to_launch(launches.startup_id, 'Broadcast dispatched*'),
362      'broadcast_received_count',
363      count_slices_concurrent_to_launch(launches.startup_id, 'broadcastReceiveReg*'),
364      'most_active_non_launch_processes',
365      n_most_active_process_names_for_launch(launches.startup_id),
366      'installd_dur_ns',
367      dur_of_process_running_concurrent_to_launch(launches.startup_id, '*installd'),
368      'dex2oat_dur_ns',
369      dur_of_process_running_concurrent_to_launch(launches.startup_id, '*dex2oat64')
370    ),
371    -- Remove slow_start_reason implementation once slow_start_reason_detailed
372    -- is added to slow_start dashboards. (b/308460401)
373    'slow_start_reason', (SELECT RepeatedField(slow_cause)
374      FROM (
375        SELECT 'No baseline or cloud profiles' AS slow_cause
376        WHERE missing_baseline_profile_for_launch(launches.startup_id, launches.package)
377
378        UNION ALL
379        SELECT 'Optimized artifacts missing, run from apk'
380        WHERE  run_from_apk_for_launch(launches.startup_id)
381
382        UNION ALL
383        SELECT 'Unlock running during launch'
384        WHERE is_unlock_running_during_launch(launches.startup_id)
385
386        UNION ALL
387        SELECT 'App in debuggable mode'
388        WHERE is_process_debuggable(launches.package)
389
390        UNION ALL
391        SELECT 'GC Activity'
392        WHERE total_gc_time_by_launch(launches.startup_id) > 0
393
394        UNION ALL
395        SELECT 'dex2oat running during launch' AS slow_cause
396        WHERE
397          dur_of_process_running_concurrent_to_launch(launches.startup_id, '*dex2oat64') > 0
398
399        UNION ALL
400        SELECT 'installd running during launch' AS slow_cause
401        WHERE
402          dur_of_process_running_concurrent_to_launch(launches.startup_id, '*installd') > 0
403
404        UNION ALL
405        SELECT 'Main Thread - Time spent in Runnable state'
406          AS slow_cause
407        WHERE
408          get_number_of_cpus() > 2 AND
409          main_thread_time_for_launch_in_runnable_state(launches.startup_id) > launches.dur * 0.15
410
411        UNION ALL
412        SELECT 'Main Thread - Time spent in interruptible sleep state'
413          AS slow_cause
414        WHERE main_thread_time_for_launch_and_state(launches.startup_id, 'S') > 2900e6
415
416        UNION ALL
417        SELECT 'Main Thread - Time spent in Blocking I/O'
418        WHERE main_thread_time_for_launch_state_and_io_wait(launches.startup_id, 'D*', TRUE) > 450e6
419
420        UNION ALL
421        SELECT 'Main Thread - Time spent in OpenDexFilesFromOat*'
422          AS slow_cause
423        WHERE android_sum_dur_on_main_thread_for_startup_and_slice(
424          launches.startup_id, 'OpenDexFilesFromOat*') > launches.dur * 0.2
425
426        UNION ALL
427        SELECT 'Time spent in bindApplication'
428          AS slow_cause
429        WHERE android_sum_dur_for_startup_and_slice(launches.startup_id, 'bindApplication') > 1250e6
430
431        UNION ALL
432        SELECT 'Time spent in view inflation'
433          AS slow_cause
434        WHERE android_sum_dur_for_startup_and_slice(launches.startup_id, 'inflate') > 450e6
435
436        UNION ALL
437        SELECT 'Time spent in ResourcesManager#getResources'
438          AS slow_cause
439        WHERE android_sum_dur_for_startup_and_slice(
440          launches.startup_id, 'ResourcesManager#getResources') > 130e6
441
442        UNION ALL
443        SELECT 'Time spent verifying classes'
444          AS slow_cause
445        WHERE
446          android_sum_dur_for_startup_and_slice(launches.startup_id, 'VerifyClass*')
447            > launches.dur * 0.15
448
449        UNION ALL
450        SELECT 'Potential CPU contention with another process' AS slow_cause
451        WHERE
452          get_number_of_cpus() > 2 AND
453          main_thread_time_for_launch_in_runnable_state(launches.startup_id) > 100e6 AND
454          most_active_process_for_launch(launches.startup_id) IS NOT NULL
455
456        UNION ALL
457        SELECT 'JIT Activity'
458          AS slow_cause
459        WHERE thread_time_for_launch_state_and_thread(
460          launches.startup_id,
461          'Running',
462          'Jit thread pool'
463        ) > 100e6
464
465        UNION ALL
466        SELECT 'Main Thread - Lock contention'
467          AS slow_cause
468        WHERE android_sum_dur_on_main_thread_for_startup_and_slice(
469          launches.startup_id,
470          'Lock contention on*'
471        ) > launches.dur * 0.2
472
473        UNION ALL
474        SELECT 'Main Thread - Monitor contention'
475          AS slow_cause
476        WHERE android_sum_dur_on_main_thread_for_startup_and_slice(
477          launches.startup_id,
478          'Lock contention on a monitor*'
479        ) > launches.dur * 0.15
480
481        UNION ALL
482        SELECT 'JIT compiled methods'
483        WHERE (
484          SELECT COUNT(1)
485          FROM ANDROID_SLICES_FOR_STARTUP_AND_SLICE_NAME(launches.startup_id, 'JIT compiling*')
486          WHERE thread_name = 'Jit thread pool'
487        ) > 65
488
489        UNION ALL
490        SELECT 'Broadcast dispatched count'
491        WHERE count_slices_concurrent_to_launch(
492          launches.startup_id,
493          'Broadcast dispatched*'
494        ) > 15
495
496        UNION ALL
497        SELECT 'Broadcast received count'
498        WHERE count_slices_concurrent_to_launch(
499          launches.startup_id,
500          'broadcastReceiveReg*'
501        ) > 50
502
503        UNION ALL
504        SELECT 'Startup running concurrent to launch'
505        WHERE EXISTS(
506          SELECT package
507          FROM android_startups l
508          WHERE l.startup_id != launches.startup_id
509            AND _is_spans_overlapping(l.ts, l.ts_end, launches.ts, launches.ts_end)
510        )
511
512        UNION ALL
513        SELECT 'Main Thread - Binder transactions blocked'
514        WHERE (
515          SELECT COUNT(1)
516          FROM binder_transaction_reply_slices_for_launch(launches.startup_id, 2e7)
517        ) > 0
518
519      )
520    ),
521    'slow_start_reason_with_details', get_slow_start_reason_with_details(launches.startup_id)
522  ) AS startup
523FROM android_startups launches;
524
525DROP VIEW IF EXISTS android_startup_output;
526CREATE PERFETTO VIEW android_startup_output AS
527SELECT
528  AndroidStartupMetric(
529    'startup', (
530      SELECT RepeatedField(startup) FROM startup_view
531    )
532  );
533