1-- 2-- Copyright 2023 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.suspend; 18 19-- Extracts the blocking thread from a slice name 20CREATE PERFETTO FUNCTION android_extract_android_monitor_contention_blocking_thread( 21 -- Name of slice 22 slice_name STRING 23) 24-- Blocking thread 25RETURNS STRING AS 26SELECT 27 str_split(str_split($slice_name, "with owner ", 1), " (", 0); 28 29-- Extracts the blocking thread tid from a slice name 30CREATE PERFETTO FUNCTION android_extract_android_monitor_contention_blocking_tid( 31 -- Name of slice 32 slice_name STRING 33) 34-- Blocking thread tid 35RETURNS LONG AS 36SELECT 37 cast_int!(STR_SPLIT(STR_SPLIT($slice_name, " (", 1), ")", 0)); 38 39-- Extracts the blocking method from a slice name 40CREATE PERFETTO FUNCTION android_extract_android_monitor_contention_blocking_method( 41 -- Name of slice 42 slice_name STRING 43) 44-- Blocking thread 45RETURNS STRING AS 46SELECT 47 str_split(str_split($slice_name, ") at ", 1), "(", 0) || "(" || str_split(str_split($slice_name, ") at ", 1), "(", 1); 48 49-- Extracts a shortened form of the blocking method name from a slice name. 50-- The shortened form discards the parameter and return 51-- types. 52CREATE PERFETTO FUNCTION android_extract_android_monitor_contention_short_blocking_method( 53 -- Name of slice 54 slice_name STRING 55) 56-- Blocking thread 57RETURNS STRING AS 58SELECT 59 str_split( 60 str_split(android_extract_android_monitor_contention_blocking_method($slice_name), " ", 1), 61 "(", 62 0 63 ); 64 65-- Extracts the monitor contention blocked method from a slice name 66CREATE PERFETTO FUNCTION android_extract_android_monitor_contention_blocked_method( 67 -- Name of slice 68 slice_name STRING 69) 70-- Blocking thread 71RETURNS STRING AS 72SELECT 73 str_split(str_split($slice_name, "blocking from ", 1), "(", 0) || "(" || str_split(str_split($slice_name, "blocking from ", 1), "(", 1); 74 75-- Extracts a shortened form of the monitor contention blocked method name 76-- from a slice name. The shortened form discards the parameter and return 77-- types. 78CREATE PERFETTO FUNCTION android_extract_android_monitor_contention_short_blocked_method( 79 -- Name of slice 80 slice_name STRING 81) 82-- Blocking thread 83RETURNS STRING AS 84SELECT 85 str_split( 86 str_split(android_extract_android_monitor_contention_blocked_method($slice_name), " ", 1), 87 "(", 88 0 89 ); 90 91-- Extracts the number of waiters on the monitor from a slice name 92CREATE PERFETTO FUNCTION android_extract_android_monitor_contention_waiter_count( 93 -- Name of slice 94 slice_name STRING 95) 96-- Count of waiters on the lock 97RETURNS LONG AS 98SELECT 99 cast_int!(STR_SPLIT(STR_SPLIT($slice_name, "waiters=", 1), " ", 0)); 100 101-- Extracts the monitor contention blocking source location from a slice name 102CREATE PERFETTO FUNCTION android_extract_android_monitor_contention_blocking_src( 103 -- Name of slice 104 slice_name STRING 105) 106-- Blocking thread 107RETURNS STRING AS 108SELECT 109 str_split(str_split($slice_name, ")(", 1), ")", 0); 110 111-- Extracts the monitor contention blocked source location from a slice name 112CREATE PERFETTO FUNCTION android_extract_android_monitor_contention_blocked_src( 113 -- Name of slice 114 slice_name STRING 115) 116-- Blocking thread 117RETURNS STRING AS 118SELECT 119 str_split(str_split($slice_name, ")(", 2), ")", 0); 120 121CREATE PERFETTO TABLE _valid_android_monitor_contention AS 122SELECT 123 slice.id AS id 124FROM slice 125LEFT JOIN slice AS child 126 ON child.parent_id = slice.id 127LEFT JOIN slice AS grand_child 128 ON grand_child.parent_id = child.id 129WHERE 130 slice.name GLOB 'monitor contention*' 131 AND ( 132 child.name GLOB 'Lock contention*' OR child.name IS NULL 133 ) 134 AND ( 135 grand_child.name IS NULL 136 ) 137GROUP BY 138 slice.id; 139 140-- Contains parsed monitor contention slices. 141CREATE PERFETTO TABLE android_monitor_contention ( 142 -- Name of the method holding the lock. 143 blocking_method STRING, 144 -- Blocked_method without arguments and return types. 145 blocked_method STRING, 146 -- Blocking_method without arguments and return types. 147 short_blocking_method STRING, 148 -- Blocked_method without arguments and return types. 149 short_blocked_method STRING, 150 -- File location of blocking_method in form <filename:linenumber>. 151 blocking_src STRING, 152 -- File location of blocked_method in form <filename:linenumber>. 153 blocked_src STRING, 154 -- Zero indexed number of threads trying to acquire the lock. 155 waiter_count LONG, 156 -- Utid of thread holding the lock. 157 blocked_utid JOINID(thread.id), 158 -- Thread name of thread holding the lock. 159 blocked_thread_name STRING, 160 -- Utid of thread holding the lock. 161 blocking_utid JOINID(thread.id), 162 -- Thread name of thread holding the lock. 163 blocking_thread_name STRING, 164 -- Tid of thread holding the lock. 165 blocking_tid LONG, 166 -- Upid of process experiencing lock contention. 167 upid JOINID(process.id), 168 -- Process name of process experiencing lock contention. 169 process_name STRING, 170 -- Slice id of lock contention. 171 id LONG, 172 -- Timestamp of lock contention start. 173 ts TIMESTAMP, 174 -- Wall clock duration of lock contention. 175 dur DURATION, 176 -- Monotonic clock duration of lock contention. 177 monotonic_dur DURATION, 178 -- Thread track id of blocked thread. 179 track_id JOINID(track.id), 180 -- Whether the blocked thread is the main thread. 181 is_blocked_thread_main LONG, 182 -- Tid of the blocked thread 183 blocked_thread_tid LONG, 184 -- Whether the blocking thread is the main thread. 185 is_blocking_thread_main LONG, 186 -- Tid of thread holding the lock. 187 blocking_thread_tid LONG, 188 -- Slice id of binder reply slice if lock contention was part of a binder txn. 189 binder_reply_id LONG, 190 -- Timestamp of binder reply slice if lock contention was part of a binder txn. 191 binder_reply_ts TIMESTAMP, 192 -- Tid of binder reply slice if lock contention was part of a binder txn. 193 binder_reply_tid LONG, 194 -- Pid of process experiencing lock contention. 195 pid LONG 196) AS 197SELECT 198 android_extract_android_monitor_contention_blocking_method(slice.name) AS blocking_method, 199 android_extract_android_monitor_contention_blocked_method(slice.name) AS blocked_method, 200 android_extract_android_monitor_contention_short_blocking_method(slice.name) AS short_blocking_method, 201 android_extract_android_monitor_contention_short_blocked_method(slice.name) AS short_blocked_method, 202 android_extract_android_monitor_contention_blocking_src(slice.name) AS blocking_src, 203 android_extract_android_monitor_contention_blocked_src(slice.name) AS blocked_src, 204 android_extract_android_monitor_contention_waiter_count(slice.name) AS waiter_count, 205 thread.utid AS blocked_utid, 206 thread.name AS blocked_thread_name, 207 blocking_thread.utid AS blocking_utid, 208 android_extract_android_monitor_contention_blocking_thread(slice.name) AS blocking_thread_name, 209 android_extract_android_monitor_contention_blocking_tid(slice.name) AS blocking_tid, 210 thread.upid AS upid, 211 process.name AS process_name, 212 slice.id, 213 slice.ts, 214 slice.dur, 215 _extract_duration_without_suspend(slice.ts, slice.dur) AS monotonic_dur, 216 slice.track_id, 217 thread.is_main_thread AS is_blocked_thread_main, 218 thread.tid AS blocked_thread_tid, 219 blocking_thread.is_main_thread AS is_blocking_thread_main, 220 blocking_thread.tid AS blocking_thread_tid, 221 binder_reply.id AS binder_reply_id, 222 binder_reply.ts AS binder_reply_ts, 223 binder_reply_thread.tid AS binder_reply_tid, 224 process.pid 225FROM slice 226JOIN thread_track 227 ON thread_track.id = slice.track_id 228LEFT JOIN thread 229 USING (utid) 230LEFT JOIN process 231 USING (upid) 232LEFT JOIN ancestor_slice(slice.id) AS binder_reply 233 ON binder_reply.name = 'binder reply' 234LEFT JOIN thread_track AS binder_reply_thread_track 235 ON binder_reply.track_id = binder_reply_thread_track.id 236LEFT JOIN thread AS binder_reply_thread 237 ON binder_reply_thread_track.utid = binder_reply_thread.utid 238-- Before Android U, we didn't have blocking_thread tid (aosp/3000578). We do a LEFT JOIN instead 239-- of JOIN so that on older devices we can at least capture the list of contentions without edges. 240LEFT JOIN thread AS blocking_thread 241 ON blocking_thread.tid = blocking_tid AND blocking_thread.upid = thread.upid 242JOIN _valid_android_monitor_contention 243 ON _valid_android_monitor_contention.id = slice.id 244WHERE 245 slice.name GLOB 'monitor contention*' 246 AND slice.dur != -1 247 AND NOT short_blocking_method IS NULL AND short_blocked_method IS NOT NULL 248GROUP BY 249 slice.id; 250 251CREATE PERFETTO INDEX _android_monitor_contention_blocking_utid_idx ON android_monitor_contention(blocking_utid, ts); 252 253CREATE PERFETTO INDEX _android_monitor_contention_id_idx ON android_monitor_contention(id); 254 255-- Monitor contention slices that are blocked by another monitor contention slice. 256-- They will have a |parent_id| field which is the id of the slice they are blocked by. 257CREATE PERFETTO TABLE _children AS 258SELECT 259 parent.id AS parent_id, 260 child.* 261FROM android_monitor_contention AS child 262JOIN android_monitor_contention AS parent 263 ON parent.blocked_utid = child.blocking_utid 264 AND child.ts BETWEEN parent.ts AND parent.ts + parent.dur; 265 266-- Monitor contention slices that are blocking another monitor contention slice. 267-- They will have a |child_id| field which is the id of the slice they are blocking. 268CREATE PERFETTO TABLE _parents AS 269SELECT 270 parent.*, 271 child.id AS child_id 272FROM android_monitor_contention AS parent 273JOIN android_monitor_contention AS child 274 ON parent.blocked_utid = child.blocking_utid 275 AND child.ts BETWEEN parent.ts AND parent.ts + parent.dur; 276 277-- Monitor contention slices that are neither blocking nor blocked by another monitor contention 278-- slice. They neither have |parent_id| nor |child_id| fields. 279CREATE PERFETTO TABLE _isolated AS 280WITH 281 parents_and_children AS ( 282 SELECT 283 id 284 FROM _children 285 UNION ALL 286 SELECT 287 id 288 FROM _parents 289 ), 290 isolated AS ( 291 SELECT 292 id 293 FROM android_monitor_contention 294 EXCEPT 295 SELECT 296 id 297 FROM parents_and_children 298 ) 299SELECT 300 * 301FROM android_monitor_contention 302JOIN isolated 303 USING (id); 304 305-- Contains parsed monitor contention slices with the parent-child relationships. 306CREATE PERFETTO TABLE android_monitor_contention_chain ( 307 -- Id of monitor contention slice blocking this contention. 308 parent_id LONG, 309 -- Name of the method holding the lock. 310 blocking_method STRING, 311 -- Blocked_method without arguments and return types. 312 blocked_method STRING, 313 -- Blocking_method without arguments and return types. 314 short_blocking_method STRING, 315 -- Blocked_method without arguments and return types. 316 short_blocked_method STRING, 317 -- File location of blocking_method in form <filename:linenumber>. 318 blocking_src STRING, 319 -- File location of blocked_method in form <filename:linenumber>. 320 blocked_src STRING, 321 -- Zero indexed number of threads trying to acquire the lock. 322 waiter_count LONG, 323 -- Utid of thread holding the lock. 324 blocked_utid JOINID(thread.id), 325 -- Thread name of thread holding the lock. 326 blocked_thread_name STRING, 327 -- Utid of thread holding the lock. 328 blocking_utid JOINID(thread.id), 329 -- Thread name of thread holding the lock. 330 blocking_thread_name STRING, 331 -- Tid of thread holding the lock. 332 blocking_tid LONG, 333 -- Upid of process experiencing lock contention. 334 upid JOINID(process.id), 335 -- Process name of process experiencing lock contention. 336 process_name STRING, 337 -- Slice id of lock contention. 338 id LONG, 339 -- Timestamp of lock contention start. 340 ts TIMESTAMP, 341 -- Wall clock duration of lock contention. 342 dur DURATION, 343 -- Monotonic clock duration of lock contention. 344 monotonic_dur DURATION, 345 -- Thread track id of blocked thread. 346 track_id JOINID(track.id), 347 -- Whether the blocked thread is the main thread. 348 is_blocked_thread_main LONG, 349 -- Tid of the blocked thread 350 blocked_thread_tid LONG, 351 -- Whether the blocking thread is the main thread. 352 is_blocking_thread_main LONG, 353 -- Tid of thread holding the lock. 354 blocking_thread_tid LONG, 355 -- Slice id of binder reply slice if lock contention was part of a binder txn. 356 binder_reply_id LONG, 357 -- Timestamp of binder reply slice if lock contention was part of a binder txn. 358 binder_reply_ts TIMESTAMP, 359 -- Tid of binder reply slice if lock contention was part of a binder txn. 360 binder_reply_tid LONG, 361 -- Pid of process experiencing lock contention. 362 pid LONG, 363 -- Id of monitor contention slice blocked by this contention. 364 child_id LONG 365) AS 366SELECT 367 NULL AS parent_id, 368 *, 369 NULL AS child_id 370FROM _isolated 371UNION ALL 372SELECT 373 c.*, 374 p.child_id 375FROM _children AS c 376LEFT JOIN _parents AS p 377 USING (id) 378UNION 379SELECT 380 c.parent_id, 381 p.* 382FROM _parents AS p 383LEFT JOIN _children AS c 384 USING (id); 385 386CREATE PERFETTO INDEX _android_monitor_contention_chain_idx ON android_monitor_contention_chain(blocking_method, blocking_utid, ts); 387 388-- First blocked node on a lock, i.e nodes with |waiter_count| = 0. The |dur| here is adjusted 389-- to only account for the time between the first thread waiting and the first thread to acquire 390-- the lock. That way, the thread state span joins below only compute the thread states where 391-- the blocking thread is actually holding the lock. This avoids counting the time when another 392-- waiter acquired the lock before the first waiter. 393CREATE PERFETTO VIEW _first_blocked_contention AS 394SELECT 395 start.id, 396 start.blocking_utid, 397 start.ts, 398 min(end.ts + end.dur) - start.ts AS dur 399FROM android_monitor_contention_chain AS start 400JOIN android_monitor_contention_chain AS end 401 ON start.blocking_utid = end.blocking_utid 402 AND start.blocking_method = end.blocking_method 403 AND end.ts BETWEEN start.ts AND start.ts + start.dur 404WHERE 405 start.waiter_count = 0 406GROUP BY 407 start.id; 408 409CREATE PERFETTO VIEW _blocking_thread_state AS 410SELECT 411 utid AS blocking_utid, 412 ts, 413 dur, 414 state, 415 blocked_function 416FROM thread_state; 417 418CREATE VIRTUAL TABLE _android_monitor_contention_chain_thread_state USING SPAN_JOIN (_first_blocked_contention PARTITIONED blocking_utid, 419 _blocking_thread_state PARTITIONED blocking_utid); 420 421-- Contains the span join of the first waiters in the |android_monitor_contention_chain| with their 422-- blocking_thread thread state. 423-- 424-- Note that we only span join the duration where the lock was actually held and contended. 425-- This can be less than the duration the lock was 'waited on' when a different waiter acquired the 426-- lock earlier than the first waiter. 427CREATE PERFETTO TABLE android_monitor_contention_chain_thread_state ( 428 -- Slice id of lock contention. 429 id LONG, 430 -- Timestamp of lock contention start. 431 ts TIMESTAMP, 432 -- Wall clock duration of lock contention. 433 dur DURATION, 434 -- Utid of the blocking |thread_state|. 435 blocking_utid JOINID(thread.id), 436 -- Blocked kernel function of the blocking thread. 437 blocked_function STRING, 438 -- Thread state of the blocking thread. 439 state STRING 440) AS 441SELECT 442 id, 443 ts, 444 dur, 445 blocking_utid, 446 blocked_function, 447 state 448FROM _android_monitor_contention_chain_thread_state; 449 450-- Aggregated thread_states on the 'blocking thread', the thread holding the lock. 451-- This builds on the data from |android_monitor_contention_chain| and 452-- for each contention slice, it returns the aggregated sum of all the thread states on the 453-- blocking thread. 454-- 455-- Note that this data is only available for the first waiter on a lock. 456-- 457CREATE PERFETTO VIEW android_monitor_contention_chain_thread_state_by_txn ( 458 -- Slice id of the monitor contention. 459 id LONG, 460 -- A |thread_state| that occurred in the blocking thread during the contention. 461 thread_state STRING, 462 -- Total time the blocking thread spent in the |thread_state| during contention. 463 thread_state_dur DURATION, 464 -- Count of all times the blocking thread entered |thread_state| during the contention. 465 thread_state_count LONG 466) AS 467SELECT 468 id, 469 state AS thread_state, 470 sum(dur) AS thread_state_dur, 471 count(dur) AS thread_state_count 472FROM android_monitor_contention_chain_thread_state 473GROUP BY 474 id, 475 thread_state; 476 477-- Aggregated blocked_functions on the 'blocking thread', the thread holding the lock. 478-- This builds on the data from |android_monitor_contention_chain| and 479-- for each contention, it returns the aggregated sum of all the kernel 480-- blocked function durations on the blocking thread. 481-- 482-- Note that this data is only available for the first waiter on a lock. 483CREATE PERFETTO VIEW android_monitor_contention_chain_blocked_functions_by_txn ( 484 -- Slice id of the monitor contention. 485 id LONG, 486 -- Blocked kernel function in a thread state in the blocking thread during the contention. 487 blocked_function STRING, 488 -- Total time the blocking thread spent in the |blocked_function| during the contention. 489 blocked_function_dur DURATION, 490 -- Count of all times the blocking thread executed the |blocked_function| during the contention. 491 blocked_function_count LONG 492) AS 493SELECT 494 id, 495 blocked_function, 496 sum(dur) AS blocked_function_dur, 497 count(dur) AS blocked_function_count 498FROM android_monitor_contention_chain_thread_state 499WHERE 500 blocked_function IS NOT NULL 501GROUP BY 502 id, 503 blocked_function; 504 505-- Returns a DAG of all Java lock contentions in a process. 506-- Each node in the graph is a <thread:Java method> pair. 507-- Each edge connects from a node waiting on a lock to a node holding a lock. 508-- The weights of each node represent the cumulative wall time the node blocked 509-- other nodes connected to it. 510CREATE PERFETTO FUNCTION android_monitor_contention_graph( 511 -- Upid of process to generate a lock graph for. 512 upid JOINID(process.id) 513) 514RETURNS TABLE ( 515 -- Pprof of lock graph. 516 pprof BYTES 517) AS 518WITH 519 contention_chain AS ( 520 SELECT 521 *, 522 iif(blocked_thread_name GLOB 'binder:*', 'binder', blocked_thread_name) AS blocked_thread_name_norm, 523 iif(blocking_thread_name GLOB 'binder:*', 'binder', blocking_thread_name) AS blocking_thread_name_norm 524 FROM android_monitor_contention_chain 525 WHERE 526 upid = $upid 527 GROUP BY 528 id, 529 parent_id 530 ), 531 graph AS ( 532 SELECT 533 id, 534 dur, 535 cat_stacks( 536 blocked_thread_name_norm || ':' || short_blocked_method, 537 blocking_thread_name_norm || ':' || short_blocking_method 538 ) AS stack 539 FROM contention_chain 540 WHERE 541 parent_id IS NULL 542 UNION ALL 543 SELECT 544 c.id, 545 c.dur AS dur, 546 cat_stacks( 547 blocked_thread_name_norm || ':' || short_blocked_method, 548 blocking_thread_name_norm || ':' || short_blocking_method, 549 stack 550 ) AS stack 551 FROM contention_chain AS c, graph AS p 552 WHERE 553 p.id = c.parent_id 554 ) 555SELECT 556 experimental_profile(stack, 'duration', 'ns', dur) AS pprof 557FROM graph; 558