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