aboutsummaryrefslogtreecommitdiff
path: root/src/trace_processor/stdlib/android/monitor_contention.sql
blob: c1de58f444237cf876bd187f2891e2af60613c69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
--
-- 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 thread tid from a slice name
--
-- @arg slice_name STRING   Name of slice
-- @ret INT                 Blocking thread tid
SELECT
  CREATE_FUNCTION(
    'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_TID(slice_name STRING)',
    'INT',
    '
    SELECT CAST(STR_SPLIT(STR_SPLIT($slice_name, " (", 1), ")", 0) AS INT)
  '
);

-- 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.parent_id AS 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 is_blocked_main_thread Whether the blocked thread is the main thread.
-- @column is_blocking_main_thread Whether the blocking thread is the main thread.
-- @column binder_reply_id Slice id of binder reply slice if lock contention was part of a binder txn.
-- @column binder_reply_ts Timestamp of binder reply slice if lock contention was part of a binder txn.
-- @column binder_reply_tid Tid 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,
  ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_TID(slice.name) AS blocking_tid,
  thread.upid AS upid,
  process.name AS process_name,
  slice.id,
  slice.ts,
  slice.dur,
  slice.track_id,
  thread.is_main_thread AS is_blocked_thread_main,
  blocking_thread.is_main_thread AS is_blocking_thread_main,
  binder_reply.id AS binder_reply_id,
  binder_reply.ts AS binder_reply_ts,
  binder_reply_thread.tid AS binder_reply_tid
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'
LEFT JOIN thread_track binder_reply_thread_track ON binder_reply.track_id = binder_reply_thread_track.id
LEFT JOIN thread binder_reply_thread ON binder_reply_thread_track.utid = binder_reply_thread.utid
JOIN thread blocking_thread ON blocking_thread.tid = blocking_tid 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 is_blocked_main_thread Whether the blocked thread is the main thread.
-- @column is_blocking_main_thread Whether the blocking thread is the main thread.
-- @column binder_reply_id Slice id of binder reply slice if lock contention was part of a binder txn.
-- @column binder_reply_ts Timestamp of binder reply slice if lock contention was part of a binder txn.
-- @column binder_reply_tid Tid 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;

CREATE VIEW internal_blocking_thread_state
AS
SELECT utid AS blocking_utid, ts, dur, state, blocked_function
FROM thread_state;

-- Contains the span join of the |android_monitor_contention_chain| with their
-- blocking thread thread state.
--
-- @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 is_blocked_main_thread Whether the blocked thread is the main thread.
-- @column is_blocking_main_thread Whether the blocking thread is the main thread.
-- @column binder_reply_id Slice id of binder reply slice if lock contention was part of a binder txn.
-- @column binder_reply_ts Timestamp of binder reply slice if lock contention was part of a binder txn.
-- @column binder_reply_tid Tid of binder reply slice if lock contention was part of a binder txn.
-- @column blocking_utid Utid of the blocking |thread_state|.
-- @column ts Timestamp of the blocking |thread_state|.
-- @column state Thread state of the blocking thread.
-- @column blocked_function Blocked kernel function of the blocking thread.
CREATE VIRTUAL TABLE android_monitor_contention_chain_thread_state
USING
  SPAN_JOIN(android_monitor_contention_chain PARTITIONED blocking_utid,
            internal_blocking_thread_state PARTITIONED blocking_utid);

-- Aggregated blocked_functions on the 'blocking thread', the thread holding the lock.
-- This builds on the data from |android_monitor_contention_chain| and
-- for each contention slice, it returns the aggregated sum of all the thread states on the
-- blocking thread.
--
-- @column id Slice id of the monitor contention.
-- @column thread_state A |thread_state| that occurred in the blocking thread during the contention.
-- @column thread_state_dur Total time the blocking thread spent in the |thread_state| during
-- contention.
-- @column thread_state_count Count of all times the blocking thread entered |thread_state| during
-- the contention.
CREATE VIEW android_monitor_contention_chain_thread_state_by_txn
AS
SELECT
  id,
  state AS thread_state,
  SUM(dur) AS thread_state_dur,
  COUNT(dur) AS thread_state_count
FROM android_monitor_contention_chain_thread_state
GROUP BY id, thread_state;

-- Aggregated blocked_functions on the 'blocking thread', the thread holding the lock.
-- This builds on the data from |android_monitor_contention_chain| and
-- for each contention, it returns the aggregated sum of all the kernel
-- blocked function durations on the blocking thread.
--
-- @column id Slice id of the monitor contention.
-- @column blocked_function Blocked kernel function in a thread state in the blocking thread during
-- the contention.
-- @column blocked_function_dur Total time the blocking thread spent in the |blocked_function|
-- during the contention.
-- @column blocked_function_count Count of all times the blocking thread executed the
-- |blocked_function| during the contention.
CREATE VIEW android_monitor_contention_chain_blocked_functions_by_txn
AS
SELECT
  id,
  blocked_function,
  SUM(dur) AS blocked_function_dur,
  COUNT(dur) AS blocked_function_count
FROM android_monitor_contention_chain_thread_state
WHERE blocked_function IS NOT NULL
GROUP BY id, blocked_function;