Skip to content

Commit

Permalink
[stdlib] Add monitor contention helper functions
Browse files Browse the repository at this point in the history
Parsed all the monitor contention slices into two tables:
1. monitor_contention: Contains the raw parsed information with an
additional column |binder_reply_id| for correlating contention to
binder txns
2. monitor_contention_chain: Contains catapult-project#1 and an additional column
|parent_id| to represent the graph of contentions

In addition, exposed useful ANDROID_EXTRACT_MONITOR_CONTENTION_*
helper functions for extracting individual columns from a slice.

Test: tools/diff_test_trace_processor.py out/android/trace_processor_shell
Change-Id: I75f760d3a41887ee0bc90606c7cc064eff72b505
  • Loading branch information
zezeozue committed Mar 15, 2023
1 parent 1f4cb7e commit d6ee829
Show file tree
Hide file tree
Showing 5 changed files with 271 additions and 0 deletions.
1 change: 1 addition & 0 deletions Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -10012,6 +10012,7 @@ genrule {
srcs: [
"src/trace_processor/stdlib/android/battery.sql",
"src/trace_processor/stdlib/android/binder.sql",
"src/trace_processor/stdlib/android/monitor_contention.sql",
"src/trace_processor/stdlib/android/process_metadata.sql",
"src/trace_processor/stdlib/android/slices.sql",
"src/trace_processor/stdlib/android/startup/internal_startups_maxsdk28.sql",
Expand Down
1 change: 1 addition & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -1899,6 +1899,7 @@ perfetto_filegroup(
srcs = [
"src/trace_processor/stdlib/android/battery.sql",
"src/trace_processor/stdlib/android/binder.sql",
"src/trace_processor/stdlib/android/monitor_contention.sql",
"src/trace_processor/stdlib/android/process_metadata.sql",
"src/trace_processor/stdlib/android/slices.sql",
],
Expand Down
1 change: 1 addition & 0 deletions src/trace_processor/stdlib/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ perfetto_sql_source_set("android") {
sources = [
"battery.sql",
"binder.sql",
"monitor_contention.sql",
"process_metadata.sql",
"slices.sql",
]
Expand Down
217 changes: 217 additions & 0 deletions src/trace_processor/stdlib/android/monitor_contention.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
--
-- Copyright 2023 The Android Open Source Project
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- https://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

-- Extracts the blocking thread from a slice name
--
-- @arg slice_name STRING Name of slice
-- @ret STRING Blocking thread
SELECT
CREATE_FUNCTION(
'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_THREAD(slice_name STRING)',
'STRING',
'
SELECT STR_SPLIT(STR_SPLIT($slice_name, "with owner ", 1), " (", 0)
'
);

-- Extracts the blocking method from a slice name
--
-- @arg slice_name STRING Name of slice
-- @ret STRING Blocking thread
SELECT
CREATE_FUNCTION(
'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_METHOD(slice_name STRING)',
'STRING',
'
SELECT STR_SPLIT(STR_SPLIT($slice_name, ") at ", 1), "(", 0)
|| "("
|| STR_SPLIT(STR_SPLIT($slice_name, ") at ", 1), "(", 1)
'
);

-- Extracts a shortened form of the blocking method name from a slice name.
-- The shortened form discards the parameter and return
-- types.
--
-- @arg slice_name STRING Name of slice
-- @ret STRING Blocking thread
SELECT
CREATE_FUNCTION(
'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_SHORT_BLOCKING_METHOD(slice_name STRING)',
'STRING',
'
SELECT
STR_SPLIT(STR_SPLIT(ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_METHOD($slice_name), " ", 1), "(", 0)
'
);

-- Extracts the monitor contention blocked method from a slice name
--
-- @arg slice_name STRING Name of slice
-- @ret STRING Blocking thread
SELECT
CREATE_FUNCTION(
'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKED_METHOD(slice_name STRING)',
'STRING',
'
SELECT STR_SPLIT(STR_SPLIT($slice_name, "blocking from ", 1), "(", 0)
|| "("
|| STR_SPLIT(STR_SPLIT($slice_name, "blocking from ", 1), "(", 1)
'
);

-- Extracts a shortened form of the monitor contention blocked method name
-- from a slice name. The shortened form discards the parameter and return
-- types.
--
-- @arg slice_name STRING Name of slice
-- @ret STRING Blocking thread
SELECT
CREATE_FUNCTION(
'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_SHORT_BLOCKED_METHOD(slice_name STRING)',
'STRING',
'
SELECT
STR_SPLIT(STR_SPLIT(ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKED_METHOD($slice_name), " ", 1), "(", 0)
'
);

-- Extracts the number of waiters on the monitor from a slice name
--
-- @arg slice_name STRING Name of slice
-- @ret INT Count of waiters on the lock
SELECT
CREATE_FUNCTION(
'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_WAITER_COUNT(slice_name STRING)',
'INT',
'
SELECT CAST(STR_SPLIT(STR_SPLIT($slice_name, "waiters=", 1), " ", 0) AS INT)
'
);

-- Extracts the monitor contention blocking source location from a slice name
--
-- @arg slice_name STRING Name of slice
-- @ret STRING Blocking thread
SELECT
CREATE_FUNCTION(
'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_SRC(slice_name STRING)',
'STRING',
'
SELECT STR_SPLIT(STR_SPLIT($slice_name, ")(", 1), ")", 0)
'
);

-- Extracts the monitor contention blocked source location from a slice name
--
-- @arg slice_name STRING Name of slice
-- @ret STRING Blocking thread
SELECT
CREATE_FUNCTION(
'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKED_SRC(slice_name STRING)',
'STRING',
'
SELECT STR_SPLIT(STR_SPLIT($slice_name, ")(", 2), ")", 0)
'
);

CREATE TABLE internal_broken_android_monitor_contention
AS
SELECT ancestor.id FROM slice
JOIN slice ancestor ON ancestor.id = slice.parent_id
WHERE ancestor.name LIKE 'Lock contention on a monitor lock%'
GROUP BY ancestor.id;

-- Contains parsed monitor contention slices
--
-- @column blocking_method name of the method holding the lock
-- @column blocked_methhod name of the method trying to acquire the lock
-- @column short_blocking_method blocking_method without arguments and return types
-- @column short_blocked_method blocked_method without arguments and return types
-- @column blocking_src file location of blocking_method in form <filename:linenumber>
-- @column blocked_src file location of blocked_method in form <filename:linenumber>
-- @column waiter_count zero indexed number of threads trying to acquire the lock
-- @column blocking_utid utid of thread holding the lock
-- @column blocking_thread_name thread name of thread holding the lock
-- @column upid upid of process experiencing lock contention
-- @column process_name process name of process experiencing lock contention
-- @column id slice id of lock contention
-- @column ts timestamp of lock contention start
-- @column dur duration of lock contention
-- @column track_id thread track id of blocked thread
-- @column binder_reply_id slice id of binder reply slice if lock contention was part of a binder txn
CREATE TABLE android_monitor_contention
AS
SELECT
ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_METHOD(slice.name) AS blocking_method,
ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKED_METHOD(slice.name) AS blocked_method,
ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_SHORT_BLOCKING_METHOD(slice.name) AS short_blocking_method,
ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_SHORT_BLOCKED_METHOD(slice.name) AS short_blocked_method,
ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_SRC(slice.name) AS blocking_src,
ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKED_SRC(slice.name) AS blocked_src,
ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_WAITER_COUNT(slice.name) AS waiter_count,
thread.utid AS blocked_utid,
thread.name AS blocked_thread_name,
blocking_thread.utid AS blocking_utid,
ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_THREAD(slice.name) AS blocking_thread_name,
thread.upid AS upid,
process.name AS process_name,
slice.id,
slice.ts,
slice.dur,
slice.track_id,
binder_reply.id AS binder_reply_id
FROM slice
JOIN thread_track
ON thread_track.id = slice.track_id
LEFT JOIN thread
USING (utid)
LEFT JOIN process
USING (upid)
LEFT JOIN internal_broken_android_monitor_contention ON internal_broken_android_monitor_contention.id = slice.id
LEFT JOIN ANCESTOR_SLICE(slice.id) binder_reply ON binder_reply.name = 'binder reply'
JOIN thread blocking_thread ON blocking_thread.name = blocking_thread_name AND blocking_thread.upid = thread.upid
WHERE slice.name LIKE 'monitor contention%'
AND slice.dur != -1
AND internal_broken_android_monitor_contention.id IS NULL
AND short_blocking_method IS NOT NULL
AND short_blocked_method IS NOT NULL
GROUP BY slice.id;

-- Contains parsed monitor contention slices with the parent-child relationships
--
-- @column parent_id id of slice blocking the blocking_thread
-- @column blocking_method name of the method holding the lock
-- @column blocked_methhod name of the method trying to acquire the lock
-- @column short_blocking_method blocking_method without arguments and return types
-- @column short_blocked_method blocked_method without arguments and return types
-- @column blocking_src file location of blocking_method in form <filename:linenumber>
-- @column blocked_src file location of blocked_method in form <filename:linenumber>
-- @column waiter_count zero indexed number of threads trying to acquire the lock
-- @column blocking_utid utid of thread holding the lock
-- @column blocking_thread_name thread name of thread holding the lock
-- @column upid upid of process experiencing lock contention
-- @column process_name process name of process experiencing lock contention
-- @column id slice id of lock contention
-- @column ts timestamp of lock contention start
-- @column dur duration of lock contention
-- @column track_id thread track id of blocked thread
-- @column binder_reply_id slice id of binder reply slice if lock contention was part of a binder txn
CREATE TABLE android_monitor_contention_chain
AS
SELECT parent.id AS parent_id, child.* FROM android_monitor_contention child
LEFT JOIN android_monitor_contention parent ON child.blocked_utid = parent.blocking_utid
AND parent.ts BETWEEN child.ts AND child.ts + child.dur;
51 changes: 51 additions & 0 deletions test/trace_processor/diff_tests/android/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,54 @@ def test_android_slices_standardization_for_aggregation(self):
ORDER BY name;
""",
out=Path('android_slice_standardization.out'))

def test_monitor_contention_extraction(self):
return DiffTestBlueprint(
trace=DataPath('android_monitor_contention_trace.atr'),
query="""
SELECT IMPORT('android.monitor_contention');
SELECT
*
FROM monitor_contention
WHERE binder_reply_id IS NOT NULL
ORDER BY dur DESC
LIMIT 1;
""",
out=Csv("""
"blocking_method","blocked_method","short_blocking_method","short_blocked_method","blocking_src","blocked_src","waiter_count","blocked_utid","blocked_thread_name","blocking_utid","blocking_thread_name","upid","process_name","id","ts","dur","track_id","binder_reply_id"
"float com.android.server.wm.WindowManagerService.getCurrentAnimatorScale()","android.app.ActivityTaskManager$RootTaskInfo com.android.server.wm.ActivityTaskManagerService.getFocusedRootTaskInfo()","com.android.server.wm.WindowManagerService.getCurrentAnimatorScale","com.android.server.wm.ActivityTaskManagerService.getFocusedRootTaskInfo","WindowManagerService.java:3511","ActivityTaskManagerService.java:1977",2,555,"binder:642_3",527,"android.anim",279,"system_server",69099,146987786843,24888520,1317,69097
"""))

def test_monitor_contention_chain_extraction(self):
return DiffTestBlueprint(
trace=DataPath('android_monitor_contention_trace.atr'),
query="""
SELECT IMPORT('android.monitor_contention');
SELECT
IIF(parent_id IS NULL, "", parent_id) AS parent_id,
blocking_method,
blocked_method,
short_blocking_method,
short_blocked_method,
blocking_src,
blocked_src,
waiter_count,
blocked_utid,
blocked_thread_name,
blocking_utid,
blocking_thread_name,
upid,
process_name,
id,
ts,
dur,
track_id,
IIF(binder_reply_id IS NULL, "", binder_reply_id) AS binder_reply_id
FROM monitor_contention_chain
ORDER BY dur DESC
LIMIT 1;
""",
out=Csv("""
"parent_id","blocking_method","blocked_method","short_blocking_method","short_blocked_method","blocking_src","blocked_src","waiter_count","blocked_utid","blocked_thread_name","blocking_utid","blocking_thread_name","upid","process_name","id","ts","dur","track_id","binder_reply_id"
"","void java.lang.Object.wait(long, int)","void android.opengl.GLSurfaceView$GLThread.requestRenderAndNotify(java.lang.Runnable)","java.lang.Object.wait","android.opengl.GLSurfaceView$GLThread.requestRenderAndNotify","Object.java:-2","GLSurfaceView.java:1658",0,313,"droid.gallery3d",1769,"GLThread 33",313,"com.android.gallery3d",289064,155411562446,51012448,2036,""
"""))

0 comments on commit d6ee829

Please sign in to comment.