• 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
17-- Create the base tables and views containing the launch spans.
18SELECT RUN_METRIC('android/android_startup_launches.sql');
19SELECT RUN_METRIC('android/process_metadata.sql');
20SELECT RUN_METRIC('android/hsc_startups.sql');
21
22-- Create the base CPU span join table.
23SELECT RUN_METRIC('android/android_cpu_agg.sql');
24
25-- Create a span join safe launches view; since both views
26-- being span joined have an "id" column, we need to rename
27-- the id column for launches to disambiguate the two.
28DROP VIEW IF EXISTS launches_span_join_safe;
29CREATE VIEW launches_span_join_safe AS
30SELECT ts, dur, id AS launch_id
31FROM launches;
32
33-- Span join the CPU table with the launches table to get the
34-- breakdown per-cpu.
35DROP TABLE IF EXISTS cpu_freq_sched_per_thread_per_launch;
36CREATE VIRTUAL TABLE cpu_freq_sched_per_thread_per_launch
37USING SPAN_JOIN(
38  launches_span_join_safe,
39  cpu_freq_sched_per_thread PARTITIONED cpu
40);
41
42SELECT RUN_METRIC('android/cpu_info.sql');
43
44DROP VIEW IF EXISTS mcycles_per_core_type_per_launch;
45CREATE VIEW mcycles_per_core_type_per_launch AS
46SELECT
47  launch_id,
48  IFNULL(core_type_per_cpu.core_type, 'unknown') AS core_type,
49  CAST(SUM(dur * freq_khz / 1000) / 1e9 AS INT) AS mcycles
50FROM cpu_freq_sched_per_thread_per_launch
51LEFT JOIN core_type_per_cpu USING (cpu)
52WHERE utid != 0
53GROUP BY 1, 2;
54
55-- Slices for forked processes. Never present in hot starts.
56-- Prefer this over process start_ts, since the process might have
57-- been preforked.
58DROP VIEW IF EXISTS zygote_fork_slice;
59CREATE VIEW zygote_fork_slice AS
60SELECT slice.ts, slice.dur, STR_SPLIT(slice.name, ": ", 1) AS process_name
61FROM slice WHERE name LIKE 'Start proc: %';
62
63DROP TABLE IF EXISTS zygote_forks_by_id;
64CREATE TABLE zygote_forks_by_id AS
65SELECT
66  launches.id,
67  zygote_fork_slice.ts,
68  zygote_fork_slice.dur
69FROM zygote_fork_slice
70JOIN launches
71ON (launches.ts < zygote_fork_slice.ts
72    AND zygote_fork_slice.ts + zygote_fork_slice.dur < launches.ts_end
73    AND zygote_fork_slice.process_name = launches.package
74);
75
76DROP VIEW IF EXISTS launch_main_threads;
77CREATE VIEW launch_main_threads AS
78SELECT
79  launches.ts AS ts,
80  launches.dur AS dur,
81  launches.id AS launch_id,
82  thread.utid AS utid
83FROM launches
84JOIN launch_processes ON launches.id = launch_processes.launch_id
85JOIN process USING(upid)
86JOIN thread ON (process.upid = thread.upid AND process.pid = thread.tid)
87ORDER BY ts;
88
89DROP VIEW IF EXISTS thread_state_extended;
90CREATE VIEW thread_state_extended AS
91SELECT
92  ts,
93  IIF(dur = -1, (SELECT end_ts FROM trace_bounds), dur) AS dur,
94  utid,
95  state
96FROM thread_state;
97
98DROP TABLE IF EXISTS main_thread_state;
99CREATE VIRTUAL TABLE main_thread_state
100USING SPAN_JOIN(
101  launch_main_threads PARTITIONED utid,
102  thread_state_extended PARTITIONED utid);
103
104DROP VIEW IF EXISTS launch_by_thread_state;
105CREATE VIEW launch_by_thread_state AS
106SELECT launch_id, state, SUM(dur) AS dur
107FROM main_thread_state
108GROUP BY 1, 2;
109
110-- Tracks all main thread process threads.
111DROP VIEW IF EXISTS launch_threads;
112CREATE VIEW launch_threads AS
113SELECT
114  launches.id AS launch_id,
115  launches.ts AS ts,
116  launches.dur AS dur,
117  thread.utid AS utid,
118  thread.name AS thread_name
119FROM launches
120JOIN launch_processes ON (launches.id = launch_processes.launch_id)
121JOIN thread ON (launch_processes.upid = thread.upid);
122
123-- Tracks all slices for the main process threads
124DROP VIEW IF EXISTS main_process_slice_unaggregated;
125CREATE VIEW main_process_slice_unaggregated AS
126SELECT
127  launch_threads.launch_id AS launch_id,
128  launch_threads.utid AS utid,
129  launch_threads.thread_name AS thread_name,
130  slice.name AS slice_name,
131  slice.ts AS slice_ts,
132  slice.dur AS slice_dur
133FROM launch_threads
134JOIN thread_track USING (utid)
135JOIN slice ON (
136  slice.track_id = thread_track.id
137  AND slice.ts BETWEEN launch_threads.ts AND launch_threads.ts + launch_threads.dur)
138WHERE slice.name IN (
139  'PostFork',
140  'ActivityThreadMain',
141  'bindApplication',
142  'activityStart',
143  'activityRestart',
144  'activityResume',
145  'inflate',
146  'ResourcesManager#getResources',
147  'binder transaction')
148  OR slice.name LIKE 'performResume:%'
149  OR slice.name LIKE 'performCreate:%'
150  OR slice.name LIKE 'location=% status=% filter=% reason=%'
151  OR slice.name LIKE 'OpenDexFilesFromOat%'
152  OR slice.name LIKE 'VerifyClass%'
153  OR slice.name LIKE 'Choreographer#doFrame%'
154  OR slice.name LIKE 'JIT compiling%'
155  OR slice.name LIKE '%mark sweep GC'
156  OR slice.name LIKE '%concurrent copying GC'
157  OR slice.name LIKE '%semispace GC';
158
159DROP TABLE IF EXISTS main_process_slice;
160CREATE TABLE main_process_slice AS
161SELECT
162  launch_id,
163  CASE
164    WHEN slice_name LIKE 'OpenDexFilesFromOat%' THEN 'OpenDexFilesFromOat'
165    WHEN slice_name LIKE 'VerifyClass%' THEN 'VerifyClass'
166    WHEN slice_name LIKE 'JIT compiling%' THEN 'JIT compiling'
167    WHEN slice_name LIKE '%mark sweep GC' THEN 'GC'
168    WHEN slice_name LIKE '%concurrent copying GC' THEN 'GC'
169    WHEN slice_name LIKE '%semispace GC' THEN 'GC'
170    ELSE slice_name
171  END AS name,
172  AndroidStartupMetric_Slice(
173    'dur_ns', SUM(slice_dur),
174    'dur_ms', SUM(slice_dur) / 1e6
175  ) AS slice_proto
176FROM main_process_slice_unaggregated
177GROUP BY 1, 2;
178
179DROP TABLE IF EXISTS report_fully_drawn_per_launch;
180CREATE TABLE report_fully_drawn_per_launch AS
181WITH report_fully_drawn_launch_slices AS (
182  SELECT
183    launches.id AS launch_id,
184    launches.ts AS launch_ts,
185    min(slice.ts) as report_fully_drawn_ts
186  FROM launches
187  JOIN launch_processes ON (launches.id = launch_processes.launch_id)
188  JOIN thread ON (launch_processes.upid = thread.upid)
189  JOIN thread_track USING (utid)
190  JOIN slice ON (
191    slice.track_id = thread_track.id
192    AND slice.ts >= launches.ts)
193  WHERE slice.name LIKE 'reportFullyDrawn%'
194  GROUP BY launches.id
195)
196SELECT
197  launch_id,
198  report_fully_drawn_ts - launch_ts as report_fully_drawn_dur
199FROM report_fully_drawn_launch_slices;
200
201DROP VIEW IF EXISTS to_event_protos;
202CREATE VIEW to_event_protos AS
203SELECT
204  slice.name as slice_name,
205  launch_id,
206  AndroidStartupMetric_Slice(
207    'dur_ns', slice.ts - l.ts,
208    'dur_ms', (slice.ts - l.ts) / 1e6
209  ) as slice_proto
210FROM launch_main_threads l
211JOIN thread_track USING (utid)
212JOIN slice ON (
213  slice.track_id = thread_track.id
214  AND slice.ts BETWEEN l.ts AND l.ts + l.dur);
215
216DROP VIEW IF EXISTS gc_slices;
217CREATE VIEW gc_slices AS
218  SELECT
219    slice_ts AS ts,
220    slice_dur AS dur,
221    utid,
222    launch_id
223  FROM main_process_slice_unaggregated
224  WHERE (
225    slice_name LIKE '%mark sweep GC'
226    OR slice_name LIKE '%concurrent copying GC'
227    OR slice_name LIKE '%semispace GC');
228
229DROP TABLE IF EXISTS gc_slices_by_state;
230CREATE VIRTUAL TABLE gc_slices_by_state
231USING SPAN_JOIN(gc_slices PARTITIONED utid, thread_state_extended PARTITIONED utid);
232
233DROP TABLE IF EXISTS gc_slices_by_state_materialized;
234CREATE TABLE gc_slices_by_state_materialized AS
235SELECT launch_id, SUM(dur) as sum_dur
236FROM gc_slices_by_state
237WHERE state = 'Running'
238GROUP BY launch_id;
239
240DROP TABLE IF EXISTS launch_threads_cpu;
241CREATE VIRTUAL TABLE launch_threads_cpu
242USING SPAN_JOIN(launch_threads PARTITIONED utid, thread_state_extended PARTITIONED utid);
243
244DROP TABLE IF EXISTS launch_threads_cpu_materialized;
245CREATE TABLE launch_threads_cpu_materialized AS
246SELECT launch_id, SUM(dur) as sum_dur
247FROM launch_threads_cpu
248WHERE thread_name = 'Jit thread pool' AND state = 'Running'
249GROUP BY launch_id;
250
251DROP TABLE IF EXISTS activity_names_materialized;
252CREATE TABLE activity_names_materialized AS
253SELECT launch_id, slice_name, slice_ts
254FROM main_process_slice_unaggregated
255WHERE (slice_name LIKE 'performResume:%' OR slice_name LIKE 'performCreate:%');
256
257DROP TABLE IF EXISTS jit_compiled_methods_materialized;
258CREATE TABLE jit_compiled_methods_materialized AS
259SELECT
260  launch_id,
261  COUNT(1) as count
262FROM main_process_slice_unaggregated
263WHERE
264  slice_name LIKE 'JIT compiling%'
265  AND thread_name = 'Jit thread pool'
266GROUP BY launch_id;
267
268DROP TABLE IF EXISTS long_binder_transactions;
269CREATE TABLE long_binder_transactions AS
270SELECT
271  launch_id, slice_dur, thread_name
272FROM
273  main_process_slice_unaggregated
274WHERE
275  slice_name = 'binder transaction'
276  AND slice_dur >= 1e8;
277
278DROP VIEW IF EXISTS startup_view;
279CREATE VIEW startup_view AS
280SELECT
281  AndroidStartupMetric_Startup(
282    'startup_id', launches.id,
283    'package_name', launches.package,
284    'process_name', (
285      SELECT p.name
286      FROM launch_processes lp
287      JOIN process p USING (upid)
288      WHERE lp.launch_id = launches.id
289      LIMIT 1
290    ),
291    'process', (
292      SELECT m.metadata
293      FROM process_metadata m
294      JOIN launch_processes p USING (upid)
295      WHERE p.launch_id = launches.id
296      LIMIT 1
297    ),
298    'activities', (
299      SELECT RepeatedField(AndroidStartupMetric_Activity(
300        'name', (SELECT STR_SPLIT(s.slice_name, ':', 1)),
301        'method', (SELECT STR_SPLIT(s.slice_name, ':', 0)),
302        'ts_method_start', s.slice_ts
303      ))
304      FROM activity_names_materialized s
305      WHERE s.launch_id = launches.id
306    ),
307    'long_binder_transactions', (
308      SELECT RepeatedField(AndroidStartupMetric_BinderTransaction(
309        'duration', AndroidStartupMetric_Slice(
310          'dur_ns', lbt.slice_dur,
311          'dur_ms', lbt.slice_dur / 1e6
312        ),
313        'thread', lbt.thread_name
314      ))
315      FROM long_binder_transactions lbt
316      WHERE lbt.launch_id = launches.id
317    ),
318    'zygote_new_process', EXISTS(SELECT TRUE FROM zygote_forks_by_id WHERE id = launches.id),
319    'activity_hosting_process_count', (
320      SELECT COUNT(1) FROM launch_processes p
321      WHERE p.launch_id = launches.id
322    ),
323    'event_timestamps', AndroidStartupMetric_EventTimestamps(
324      'intent_received', launches.ts,
325      'first_frame', launches.ts_end
326    ),
327    'to_first_frame', AndroidStartupMetric_ToFirstFrame(
328      'dur_ns', launches.dur,
329      'dur_ms', launches.dur / 1e6,
330      'main_thread_by_task_state', AndroidStartupMetric_TaskStateBreakdown(
331        'running_dur_ns', IFNULL(
332            (
333            SELECT dur FROM launch_by_thread_state l
334            WHERE l.launch_id = launches.id AND state = 'Running'
335            ), 0),
336        'runnable_dur_ns', IFNULL(
337            (
338            SELECT dur FROM launch_by_thread_state l
339            WHERE l.launch_id = launches.id AND state = 'R'
340            ), 0),
341        'uninterruptible_sleep_dur_ns', IFNULL(
342            (
343            SELECT dur FROM launch_by_thread_state l
344            WHERE l.launch_id = launches.id AND (state = 'D' or state = 'DK')
345            ), 0),
346        'interruptible_sleep_dur_ns', IFNULL(
347            (
348            SELECT dur FROM launch_by_thread_state l
349            WHERE l.launch_id = launches.id AND state = 'S'
350            ), 0)
351      ),
352      'mcycles_by_core_type', AndroidStartupMetric_McyclesByCoreType(
353        'little', (
354          SELECT mcycles
355          FROM mcycles_per_core_type_per_launch m
356          WHERE m.launch_id = launches.id AND m.core_type = 'little'
357        ),
358        'big', (
359          SELECT mcycles
360          FROM mcycles_per_core_type_per_launch m
361          WHERE m.launch_id = launches.id AND m.core_type = 'big'
362        ),
363        'bigger', (
364          SELECT mcycles
365          FROM mcycles_per_core_type_per_launch m
366          WHERE m.launch_id = launches.id AND m.core_type = 'bigger'
367        ),
368        'unknown', (
369          SELECT mcycles
370          FROM mcycles_per_core_type_per_launch m
371          WHERE m.launch_id = launches.id AND m.core_type = 'unknown'
372        )
373      ),
374      'to_post_fork', (
375        SELECT slice_proto
376        FROM to_event_protos p
377        WHERE p.launch_id = launches.id AND slice_name = 'PostFork'
378      ),
379      'to_activity_thread_main', (
380        SELECT slice_proto
381        FROM to_event_protos p
382        WHERE p.launch_id = launches.id AND slice_name = 'ActivityThreadMain'
383      ),
384      'to_bind_application', (
385        SELECT slice_proto
386        FROM to_event_protos p
387        WHERE p.launch_id = launches.id AND slice_name = 'bindApplication'
388      ),
389      'other_processes_spawned_count', (
390        SELECT COUNT(1) FROM process
391        WHERE (process.name IS NULL OR process.name != launches.package)
392        AND process.start_ts BETWEEN launches.ts AND launches.ts + launches.dur
393      ),
394      'time_activity_manager', (
395        SELECT AndroidStartupMetric_Slice(
396          'dur_ns', l.ts - launches.ts,
397          'dur_ms', (l.ts - launches.ts) / 1e6
398        )
399        FROM launching_events l
400        WHERE l.ts BETWEEN launches.ts AND launches.ts + launches.dur
401      ),
402      'time_post_fork', (
403        SELECT slice_proto
404        FROM main_process_slice s
405        WHERE s.launch_id = launches.id AND name = 'PostFork'
406      ),
407      'time_activity_thread_main', (
408        SELECT slice_proto
409        FROM main_process_slice s
410        WHERE s.launch_id = launches.id AND name = 'ActivityThreadMain'
411      ),
412      'time_bind_application', (
413        SELECT slice_proto
414        FROM main_process_slice s
415        WHERE s.launch_id = launches.id AND name = 'bindApplication'
416      ),
417      'time_activity_start', (
418        SELECT slice_proto
419        FROM main_process_slice s
420        WHERE s.launch_id = launches.id AND name = 'activityStart'
421      ),
422      'time_activity_resume', (
423        SELECT slice_proto
424        FROM main_process_slice s
425        WHERE s.launch_id = launches.id AND name = 'activityResume'
426      ),
427      'time_activity_restart', (
428        SELECT slice_proto
429        FROM main_process_slice s
430        WHERE s.launch_id = launches.id AND name = 'activityRestart'
431      ),
432      'time_choreographer', (
433        SELECT slice_proto
434        FROM main_process_slice s
435        WHERE s.launch_id = launches.id AND name LIKE 'Choreographer#doFrame%'
436      ),
437      'time_before_start_process', (
438        SELECT AndroidStartupMetric_Slice(
439          'dur_ns', ts - launches.ts,
440          'dur_ms', (ts - launches.ts) / 1e6
441        )
442        FROM zygote_forks_by_id z
443        WHERE z.id = launches.id
444      ),
445      'time_during_start_process', (
446        SELECT AndroidStartupMetric_Slice(
447          'dur_ns', dur,
448          'dur_ms', dur / 1e6
449        )
450        FROM zygote_forks_by_id z
451        WHERE z.id = launches.id
452      ),
453      'time_inflate', (
454        SELECT slice_proto
455        FROM main_process_slice s
456        WHERE s.launch_id = launches.id AND name = 'inflate'
457      ),
458      'time_get_resources', (
459        SELECT slice_proto
460        FROM main_process_slice s
461        WHERE s.launch_id = launches.id
462        AND name = 'ResourcesManager#getResources'
463      ),
464      'time_dex_open', (
465        SELECT slice_proto
466        FROM main_process_slice s
467        WHERE s.launch_id = launches.id AND name = 'OpenDexFilesFromOat'
468      ),
469      'time_verify_class', (
470        SELECT slice_proto
471        FROM main_process_slice s
472        WHERE s.launch_id = launches.id AND name = 'VerifyClass'
473      ),
474      'jit_compiled_methods', (
475        SELECT count
476        FROM jit_compiled_methods_materialized s
477        WHERE s.launch_id = launches.id
478      ),
479      'time_jit_thread_pool_on_cpu', (
480        SELECT
481          NULL_IF_EMPTY(AndroidStartupMetric_Slice(
482            'dur_ns', sum_dur,
483            'dur_ms', sum_dur / 1e6
484          ))
485        FROM launch_threads_cpu_materialized
486        WHERE launch_id = launches.id
487      ),
488      'time_gc_total', (
489        SELECT slice_proto
490        FROM main_process_slice s
491        WHERE s.launch_id = launches.id AND name = 'GC'
492      ),
493      'time_gc_on_cpu', (
494        SELECT
495          NULL_IF_EMPTY(AndroidStartupMetric_Slice(
496            'dur_ns', sum_dur,
497            'dur_ms', sum_dur / 1e6
498          ))
499        FROM gc_slices_by_state_materialized
500        WHERE launch_id = launches.id
501      )
502    ),
503    'hsc', (
504      SELECT NULL_IF_EMPTY(AndroidStartupMetric_HscMetrics(
505        'full_startup', (
506          SELECT AndroidStartupMetric_Slice(
507            'dur_ns', h.ts_total,
508            'dur_ms', h.ts_total / 1e6
509          )
510          FROM hsc_based_startup_times h
511          WHERE h.id = launches.id
512        )
513      ))
514    ),
515    'report_fully_drawn', (
516      SELECT NULL_IF_EMPTY(AndroidStartupMetric_Slice(
517        'dur_ns', report_fully_drawn_dur,
518        'dur_ms', report_fully_drawn_dur / 1e6
519      ))
520      FROM report_fully_drawn_per_launch r
521      WHERE r.launch_id = launches.id
522    ),
523    'optimization_status',(
524      SELECT RepeatedField(AndroidStartupMetric_OptimizationStatus(
525        'location', SUBSTR(STR_SPLIT(name, ' status=', 0), LENGTH('location=') + 1),
526        'odex_status', STR_SPLIT(STR_SPLIT(name, ' status=', 1), ' filter=', 0),
527        'compilation_filter', STR_SPLIT(STR_SPLIT(name, ' filter=', 1), ' reason=', 0),
528        'compilation_reason', STR_SPLIT(name, ' reason=', 1)
529      ))
530      FROM main_process_slice s
531      WHERE name LIKE 'location=% status=% filter=% reason=%'
532    )
533  ) as startup
534FROM launches;
535
536DROP VIEW IF EXISTS android_startup_event;
537CREATE VIEW android_startup_event AS
538SELECT
539  'slice' as track_type,
540  'Android App Startups' as track_name,
541  l.ts as ts,
542  l.dur as dur,
543  l.package as slice_name
544FROM launches l;
545
546DROP VIEW IF EXISTS android_startup_output;
547CREATE VIEW android_startup_output AS
548SELECT
549  AndroidStartupMetric(
550    'startup', (
551      SELECT RepeatedField(startup) FROM startup_view
552    )
553  );
554