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', ( 118 SELECT lp.startup_type 119 FROM android_startup_processes lp 120 WHERE lp.startup_id =launches.startup_id 121 LIMIT 1 122 ), 123 'package_name', launches.package, 124 'process_name', ( 125 SELECT p.name 126 FROM android_startup_processes lp 127 JOIN process p USING (upid) 128 WHERE lp.startup_id =launches.startup_id 129 LIMIT 1 130 ), 131 'process', ( 132 SELECT m.metadata 133 FROM process_metadata m 134 JOIN android_startup_processes p USING (upid) 135 WHERE p.startup_id =launches.startup_id 136 LIMIT 1 137 ), 138 'activities', ( 139 SELECT RepeatedField(AndroidStartupMetric_Activity( 140 'name', (SELECT STR_SPLIT(s.slice_name, ':', 1)), 141 'method', (SELECT STR_SPLIT(s.slice_name, ':', 0)), 142 'ts_method_start', s.slice_ts 143 )) 144 FROM thread_slices_for_all_launches s 145 WHERE 146 s.startup_id =launches.startup_id 147 AND (s.slice_name GLOB 'performResume:*' OR s.slice_name GLOB 'performCreate:*') 148 ), 149 'long_binder_transactions', ( 150 SELECT RepeatedField( 151 AndroidStartupMetric_BinderTransaction( 152 "duration", startup_slice_proto(s.slice_dur), 153 "thread", s.thread_name, 154 "destination_thread", EXTRACT_ARG(s.arg_set_id, "destination name"), 155 "destination_process", s.process, 156 "flags", EXTRACT_ARG(s.arg_set_id, "flags"), 157 "code", EXTRACT_ARG(s.arg_set_id, "code"), 158 "data_size", EXTRACT_ARG(s.arg_set_id, "data_size") 159 ) 160 ) 161 FROM ANDROID_BINDER_TRANSACTION_SLICES_FOR_STARTUP(launches.startup_id, 2e7) s 162 ), 163 'zygote_new_process', EXISTS(SELECT TRUE FROM ZYGOTE_FORK_FOR_LAUNCH(launches.startup_id)), 164 'activity_hosting_process_count', ( 165 SELECT COUNT(1) FROM android_startup_processes p 166 WHERE p.startup_id =launches.startup_id 167 ), 168 'time_to_initial_display', ( 169 SELECT time_to_initial_display 170 FROM android_startup_time_to_display s 171 WHERE s.startup_id = launches.startup_id 172 ), 173 'time_to_full_display', ( 174 SELECT time_to_full_display 175 FROM android_startup_time_to_display s 176 WHERE s.startup_id = launches.startup_id 177 ), 178 'event_timestamps', AndroidStartupMetric_EventTimestamps( 179 'intent_received', launches.ts, 180 'first_frame', launches.ts_end 181 ), 182 'to_first_frame', AndroidStartupMetric_ToFirstFrame( 183 'dur_ns', launches.dur, 184 'dur_ms', launches.dur / 1e6, 185 'main_thread_by_task_state', AndroidStartupMetric_TaskStateBreakdown( 186 'running_dur_ns', IFNULL( 187 main_thread_time_for_launch_and_state(launches.startup_id, 'Running'), 0 188 ), 189 'runnable_dur_ns', IFNULL( 190 main_thread_time_for_launch_in_runnable_state(launches.startup_id), 0 191 ), 192 'uninterruptible_sleep_dur_ns', IFNULL( 193 main_thread_time_for_launch_and_state(launches.startup_id, 'D*'), 0 194 ), 195 'interruptible_sleep_dur_ns', IFNULL( 196 main_thread_time_for_launch_and_state(launches.startup_id, 'S'), 0 197 ), 198 'uninterruptible_io_sleep_dur_ns', IFNULL( 199 main_thread_time_for_launch_state_and_io_wait(launches.startup_id, 'D*', TRUE), 0 200 ), 201 'uninterruptible_non_io_sleep_dur_ns', IFNULL( 202 main_thread_time_for_launch_state_and_io_wait(launches.startup_id, 'D*', FALSE), 0 203 ) 204 205 ), 206 'mcycles_by_core_type', NULL_IF_EMPTY(AndroidStartupMetric_McyclesByCoreType( 207 'little', mcycles_for_launch_and_core_type(launches.startup_id, 'little'), 208 'big', mcycles_for_launch_and_core_type(launches.startup_id, 'big'), 209 'bigger', mcycles_for_launch_and_core_type(launches.startup_id, 'bigger'), 210 'unknown', mcycles_for_launch_and_core_type(launches.startup_id, 'unknown') 211 )), 212 'to_post_fork', 213 launch_to_main_thread_slice_proto(launches.startup_id, 'PostFork'), 214 'to_activity_thread_main', 215 launch_to_main_thread_slice_proto(launches.startup_id, 'ActivityThreadMain'), 216 'to_bind_application', 217 launch_to_main_thread_slice_proto(launches.startup_id, 'bindApplication'), 218 'time_activity_manager', ( 219 SELECT startup_slice_proto(l.ts - launches.ts) 220 FROM _startup_events l 221 WHERE l.ts BETWEEN launches.ts AND launches.ts + launches.dur 222 ), 223 'time_post_fork', 224 dur_sum_slice_proto_for_launch(launches.startup_id, 'PostFork'), 225 'time_activity_thread_main', 226 dur_sum_slice_proto_for_launch(launches.startup_id, 'ActivityThreadMain'), 227 'time_bind_application', 228 dur_sum_slice_proto_for_launch(launches.startup_id, 'bindApplication'), 229 'time_activity_start', 230 dur_sum_slice_proto_for_launch(launches.startup_id, 'activityStart'), 231 'time_activity_resume', 232 dur_sum_slice_proto_for_launch(launches.startup_id, 'activityResume'), 233 'time_activity_restart', 234 dur_sum_slice_proto_for_launch(launches.startup_id, 'activityRestart'), 235 'time_choreographer', 236 dur_sum_slice_proto_for_launch(launches.startup_id, 'Choreographer#doFrame*'), 237 'time_inflate', 238 dur_sum_slice_proto_for_launch(launches.startup_id, 'inflate'), 239 'time_get_resources', 240 dur_sum_slice_proto_for_launch(launches.startup_id, 'ResourcesManager#getResources'), 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 'other_processes_spawned_count', ( 294 SELECT COUNT(1) 295 FROM process 296 WHERE 297 process.start_ts BETWEEN launches.ts AND launches.ts + launches.dur 298 AND process.upid NOT IN ( 299 SELECT upid FROM android_startup_processes 300 WHERE android_startup_processes.startup_id =launches.startup_id 301 ) 302 ) 303 ), 304 'hsc', NULL_IF_EMPTY(AndroidStartupMetric_HscMetrics( 305 'full_startup', ( 306 SELECT startup_slice_proto(h.ts_total) 307 FROM hsc_based_startup_times h 308 WHERE h.id =launches.startup_id 309 ) 310 )), 311 'report_fully_drawn', NULL_IF_EMPTY(report_fully_drawn_for_launch(launches.startup_id)), 312 'optimization_status', ( 313 SELECT RepeatedField(AndroidStartupMetric_OptimizationStatus( 314 'location', SUBSTR(STR_SPLIT(slice_name, ' status=', 0), LENGTH('location=') + 1), 315 'odex_status', STR_SPLIT(STR_SPLIT(slice_name, ' status=', 1), ' filter=', 0), 316 'compilation_filter', STR_SPLIT(STR_SPLIT(slice_name, ' filter=', 1), ' reason=', 0), 317 'compilation_reason', STR_SPLIT(slice_name, ' reason=', 1), 318 'summary', 319 summary_for_optimization_status( 320 SUBSTR(STR_SPLIT(slice_name, ' status=', 0), LENGTH('location=') + 1), 321 STR_SPLIT(STR_SPLIT(slice_name, ' status=', 1), ' filter=', 0), 322 STR_SPLIT(STR_SPLIT(slice_name, ' filter=', 1), ' reason=', 0), 323 STR_SPLIT(slice_name, ' reason=', 1)) 324 )) 325 FROM ( 326 SELECT * 327 FROM ANDROID_SLICES_FOR_STARTUP_AND_SLICE_NAME( 328 launches.startup_id, 329 'location=* status=* filter=* reason=*' 330 ) 331 ORDER BY slice_name 332 ) 333 ), 334 'verify_class', ( 335 SELECT RepeatedField(AndroidStartupMetric_VerifyClass( 336 'name', STR_SPLIT(slice_name, "VerifyClass ", 1), 337 'dur_ns', slice_dur)) 338 FROM GET_LONG_SLICES_FOR_LAUNCH(launches.startup_id, "VerifyClass *", 5) 339 ), 340 'startup_concurrent_to_launch', ( 341 SELECT RepeatedField(package) 342 FROM android_startups l 343 WHERE l.startup_id != launches.startup_id 344 AND _is_spans_overlapping(l.ts, l.ts_end, launches.ts, launches.ts_end) 345 ), 346 'dlopen_file', ( 347 SELECT RepeatedField(STR_SPLIT(slice_name, "dlopen: ", 1)) 348 FROM android_thread_slices_for_all_startups s 349 WHERE startup_id = launches.startup_id AND slice_name GLOB "dlopen: *.so" 350 ), 351 'system_state', AndroidStartupMetric_SystemState( 352 'dex2oat_running', 353 dur_of_process_running_concurrent_to_launch(launches.startup_id, '*dex2oat64') > 0, 354 'installd_running', 355 dur_of_process_running_concurrent_to_launch(launches.startup_id, '*installd') > 0, 356 'broadcast_dispatched_count', 357 count_slices_concurrent_to_launch(launches.startup_id, 'Broadcast dispatched*'), 358 'broadcast_received_count', 359 count_slices_concurrent_to_launch(launches.startup_id, 'broadcastReceiveReg*'), 360 'most_active_non_launch_processes', 361 n_most_active_process_names_for_launch(launches.startup_id), 362 'installd_dur_ns', 363 dur_of_process_running_concurrent_to_launch(launches.startup_id, '*installd'), 364 'dex2oat_dur_ns', 365 dur_of_process_running_concurrent_to_launch(launches.startup_id, '*dex2oat64') 366 ), 367 -- Remove slow_start_reason implementation once slow_start_reason_detailed 368 -- is added to slow_start dashboards. (b/308460401) 369 'slow_start_reason', (SELECT RepeatedField(slow_cause) 370 FROM ( 371 SELECT 'No baseline or cloud profiles' AS slow_cause 372 WHERE missing_baseline_profile_for_launch(launches.startup_id, launches.package) 373 374 UNION ALL 375 SELECT 'Optimized artifacts missing, run from apk' 376 WHERE run_from_apk_for_launch(launches.startup_id) 377 378 UNION ALL 379 SELECT 'Unlock running during launch' 380 WHERE is_unlock_running_during_launch(launches.startup_id) 381 382 UNION ALL 383 SELECT 'App in debuggable mode' 384 WHERE is_process_debuggable(launches.package) 385 386 UNION ALL 387 SELECT 'GC Activity' 388 WHERE total_gc_time_by_launch(launches.startup_id) > 0 389 390 UNION ALL 391 SELECT 'dex2oat running during launch' AS slow_cause 392 WHERE 393 dur_of_process_running_concurrent_to_launch(launches.startup_id, '*dex2oat64') > 0 394 395 UNION ALL 396 SELECT 'installd running during launch' AS slow_cause 397 WHERE 398 dur_of_process_running_concurrent_to_launch(launches.startup_id, '*installd') > 0 399 400 UNION ALL 401 SELECT 'Main Thread - Time spent in Runnable state' 402 AS slow_cause 403 WHERE 404 get_number_of_cpus() > 2 AND 405 main_thread_time_for_launch_in_runnable_state(launches.startup_id) > launches.dur * 0.15 406 407 UNION ALL 408 SELECT 'Main Thread - Time spent in interruptible sleep state' 409 AS slow_cause 410 WHERE main_thread_time_for_launch_and_state(launches.startup_id, 'S') > 2900e6 411 412 UNION ALL 413 SELECT 'Main Thread - Time spent in Blocking I/O' 414 WHERE main_thread_time_for_launch_state_and_io_wait(launches.startup_id, 'D*', TRUE) > 450e6 415 416 UNION ALL 417 SELECT 'Main Thread - Time spent in OpenDexFilesFromOat*' 418 AS slow_cause 419 WHERE android_sum_dur_on_main_thread_for_startup_and_slice( 420 launches.startup_id, 'OpenDexFilesFromOat*') > launches.dur * 0.2 421 422 UNION ALL 423 SELECT 'Time spent in bindApplication' 424 AS slow_cause 425 WHERE android_sum_dur_for_startup_and_slice(launches.startup_id, 'bindApplication') > 1250e6 426 427 UNION ALL 428 SELECT 'Time spent in view inflation' 429 AS slow_cause 430 WHERE android_sum_dur_for_startup_and_slice(launches.startup_id, 'inflate') > 450e6 431 432 UNION ALL 433 SELECT 'Time spent in ResourcesManager#getResources' 434 AS slow_cause 435 WHERE android_sum_dur_for_startup_and_slice( 436 launches.startup_id, 'ResourcesManager#getResources') > 130e6 437 438 UNION ALL 439 SELECT 'Time spent verifying classes' 440 AS slow_cause 441 WHERE 442 android_sum_dur_for_startup_and_slice(launches.startup_id, 'VerifyClass*') 443 > launches.dur * 0.15 444 445 UNION ALL 446 SELECT 'Potential CPU contention with another process' AS slow_cause 447 WHERE 448 get_number_of_cpus() > 2 AND 449 main_thread_time_for_launch_in_runnable_state(launches.startup_id) > 100e6 AND 450 most_active_process_for_launch(launches.startup_id) IS NOT NULL 451 452 UNION ALL 453 SELECT 'JIT Activity' 454 AS slow_cause 455 WHERE thread_time_for_launch_state_and_thread( 456 launches.startup_id, 457 'Running', 458 'Jit thread pool' 459 ) > 100e6 460 461 UNION ALL 462 SELECT 'Main Thread - Lock contention' 463 AS slow_cause 464 WHERE android_sum_dur_on_main_thread_for_startup_and_slice( 465 launches.startup_id, 466 'Lock contention on*' 467 ) > launches.dur * 0.2 468 469 UNION ALL 470 SELECT 'Main Thread - Monitor contention' 471 AS slow_cause 472 WHERE android_sum_dur_on_main_thread_for_startup_and_slice( 473 launches.startup_id, 474 'Lock contention on a monitor*' 475 ) > launches.dur * 0.15 476 477 UNION ALL 478 SELECT 'JIT compiled methods' 479 WHERE ( 480 SELECT COUNT(1) 481 FROM ANDROID_SLICES_FOR_STARTUP_AND_SLICE_NAME(launches.startup_id, 'JIT compiling*') 482 WHERE thread_name = 'Jit thread pool' 483 ) > 65 484 485 UNION ALL 486 SELECT 'Broadcast dispatched count' 487 WHERE count_slices_concurrent_to_launch( 488 launches.startup_id, 489 'Broadcast dispatched*' 490 ) > 15 491 492 UNION ALL 493 SELECT 'Broadcast received count' 494 WHERE count_slices_concurrent_to_launch( 495 launches.startup_id, 496 'broadcastReceiveReg*' 497 ) > 50 498 499 UNION ALL 500 SELECT 'Startup running concurrent to launch' 501 WHERE EXISTS( 502 SELECT package 503 FROM android_startups l 504 WHERE l.startup_id != launches.startup_id 505 AND _is_spans_overlapping(l.ts, l.ts_end, launches.ts, launches.ts_end) 506 ) 507 508 UNION ALL 509 SELECT 'Main Thread - Binder transactions blocked' 510 WHERE ( 511 SELECT COUNT(1) 512 FROM binder_transaction_reply_slices_for_launch(launches.startup_id, 2e7) 513 ) > 0 514 515 ) 516 ), 517 'slow_start_reason_with_details', get_slow_start_reason_with_details(launches.startup_id) 518 ) AS startup 519FROM android_startups launches; 520 521DROP VIEW IF EXISTS android_startup_output; 522CREATE PERFETTO VIEW android_startup_output AS 523SELECT 524 AndroidStartupMetric( 525 'startup', ( 526 SELECT RepeatedField(startup) FROM startup_view 527 ) 528 ); 529