-
Notifications
You must be signed in to change notification settings - Fork 731
Expand file tree
/
Copy pathsurfaceflinger.sql
More file actions
316 lines (303 loc) · 10.3 KB
/
surfaceflinger.sql
File metadata and controls
316 lines (303 loc) · 10.3 KB
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
--
-- Copyright 2025 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.
INCLUDE PERFETTO MODULE android.cujs.base;
CREATE PERFETTO TABLE _android_sf_process AS
SELECT
*
FROM process
WHERE
process.name = '/system/bin/surfaceflinger'
LIMIT 1;
CREATE PERFETTO TABLE _android_sf_main_thread AS
SELECT
upid,
utid,
thread.name,
thread_track.id AS track_id
FROM thread
JOIN _android_sf_process AS sf_process
USING (upid)
JOIN thread_track
USING (utid)
WHERE
thread.is_main_thread;
-- Extract thread and track information for a given thread in the surfaceflinger process.
CREATE PERFETTO FUNCTION _android_sf_thread(
-- thread_name to fetch information for.
thread_name STRING
)
RETURNS TABLE (
-- upid of the process.
upid JOINID(process.id),
-- utid of the process.
utid JOINID(thread.id),
-- name of the thread.
name STRING,
-- track_id for the thread.
track_id JOINID(track.id)
) AS
SELECT
upid,
utid,
thread.name,
thread_track.id AS track_id
FROM thread
JOIN _android_sf_process AS sf_process
USING (upid)
JOIN thread_track
USING (utid)
WHERE
thread.name = $thread_name;
-- Match the frame timeline on the app side with the frame timeline on the SF side.
-- In cases where there are multiple layers drawn, there would be separate frame timeline
-- slice for each of the layers. GROUP BY is used to deduplicate these rows.
CREATE PERFETTO TABLE android_app_to_sf_frame_timeline_match (
-- upid of the app.
app_upid JOINID(process.upid),
-- vsync id of the app.
app_vsync LONG,
-- upid of surfaceflinger process.
sf_upid JOINID(process.upid),
-- vsync id for surfaceflinger.
sf_vsync LONG
) AS
SELECT
app_timeline.upid AS app_upid,
CAST(app_timeline.name AS INTEGER) AS app_vsync,
sf_process.upid AS sf_upid,
CAST(sf_timeline.name AS INTEGER) AS sf_vsync
FROM actual_frame_timeline_slice AS app_timeline
JOIN flow
ON flow.slice_out = app_timeline.id
JOIN actual_frame_timeline_slice AS sf_timeline
ON flow.slice_in = sf_timeline.id
JOIN _android_sf_process AS sf_process
ON sf_timeline.upid = sf_process.upid
GROUP BY
app_upid,
app_vsync,
sf_upid,
sf_vsync;
-- Extract app and SF frame vsync scoped to CUJs.
CREATE PERFETTO TABLE _android_jank_cuj_app_sf_frame_timeline_match AS
SELECT
cuj_id,
do_frame.upid AS app_upid,
app_vsync,
app_sf_match.sf_upid,
app_sf_match.sf_vsync
FROM _android_jank_cuj_do_frames AS do_frame
JOIN android_app_to_sf_frame_timeline_match AS app_sf_match
ON do_frame.vsync = app_sf_match.app_vsync AND do_frame.upid = app_sf_match.app_upid;
-- Extract ts and dur for a given slice name from the SF process main thread track.
CREATE PERFETTO FUNCTION _find_android_jank_cuj_sf_main_thread_slice(
slice_name_glob STRING
)
RETURNS TABLE (
cuj_id LONG,
utid JOINID(thread.id),
vsync LONG,
id ID(slice.id),
name STRING,
ts TIMESTAMP,
dur LONG,
ts_end TIMESTAMP
) AS
WITH
sf_vsync AS (
SELECT DISTINCT
cuj_id,
sf_vsync AS vsync
FROM _android_jank_cuj_app_sf_frame_timeline_match
)
SELECT
cuj_id,
utid,
sf_vsync.vsync,
slice.id,
slice.name,
slice.ts,
slice.dur,
slice.ts + slice.dur AS ts_end
FROM slice
JOIN _android_sf_main_thread AS main_thread
USING (track_id)
JOIN sf_vsync
ON CAST(str_split(slice.name, " ", 1) AS INTEGER) = sf_vsync.vsync
WHERE
slice.name GLOB $slice_name_glob AND slice.dur > 0
ORDER BY
cuj_id,
vsync;
CREATE PERFETTO TABLE _android_jank_cuj_sf_commit_slice AS
SELECT
*
FROM _find_android_jank_cuj_sf_main_thread_slice('commit *');
CREATE PERFETTO TABLE _android_jank_cuj_sf_composite_slice AS
SELECT
*
FROM _find_android_jank_cuj_sf_main_thread_slice('composite *');
CREATE PERFETTO TABLE _android_jank_cuj_sf_on_message_invalidate_slice AS
SELECT
*
FROM _find_android_jank_cuj_sf_main_thread_slice('onMessageInvalidate *');
-- Calculates the frame boundaries based on when we *expected* the work to
-- start and we use the end of the `composite` slice as the end of the work
-- on the frame.
CREATE PERFETTO TABLE _android_jank_cuj_sf_main_thread_frame_boundary AS
-- Join `commit` and `composite` slices using vsync IDs.
-- We treat the two slices as a single "fake slice" that starts when `commit` starts, and ends
-- when `composite` ends.
WITH
combined_commit_composite_slice AS (
SELECT
cuj_id,
commit_slice.utid,
vsync,
commit_slice.ts,
composite_slice.ts_end,
composite_slice.ts_end - commit_slice.ts AS dur
FROM _android_jank_cuj_sf_commit_slice AS commit_slice
JOIN _android_jank_cuj_sf_composite_slice AS composite_slice
USING (cuj_id, vsync)
),
-- As older builds will not have separate commit/composite slices for each frame, but instead
-- a single `onMessageInvalidate`, we UNION ALL the two tables. Exactly one of them should
-- have data.
main_thread_slice AS (
SELECT
utid,
cuj_id,
vsync,
ts,
dur,
ts_end
FROM combined_commit_composite_slice
UNION ALL
SELECT
utid,
cuj_id,
vsync,
ts,
dur,
ts_end
FROM _android_jank_cuj_sf_on_message_invalidate_slice
)
SELECT
cuj_id,
utid,
vsync,
expected_timeline.ts,
main_thread_slice.ts AS ts_main_thread_start,
main_thread_slice.ts_end,
main_thread_slice.ts_end - expected_timeline.ts AS dur
FROM expected_frame_timeline_slice AS expected_timeline
JOIN _android_sf_process
USING (upid)
JOIN main_thread_slice
ON main_thread_slice.vsync = CAST(expected_timeline.name AS INTEGER);
-- Workloads that are submitted to SurfaceFlinger to do compositing work
CREATE PERFETTO TABLE android_surfaceflinger_workloads (
-- Identifier for the workload, for joining with other tables
workload_id LONG,
-- Timestamp of the workload
ts TIMESTAMP,
-- Source of the workload
source STRING,
-- Name of the output the workload is compositing for
output_name STRING,
-- SF vsync ID that the workload was scheduled for
sf_vsync LONG,
-- CPU time of the frame_signal slice in SF
sf_cpu_frame_signal_nanos LONG,
-- CPU time of the commit slice in SF
sf_cpu_commit_nanos LONG,
-- CPU time of the composite slice in SF
sf_cpu_composite_nanos LONG,
-- CPU time of the present call in HWC, observed from SF
hwc_present_nanos LONG,
-- CPU time of the validate call in HWC, observed from SF
hwc_validate_nanos LONG,
-- CPU time of the presentOrValidate call in HWC, observed from SF
hwc_present_or_validate_nanos LONG,
-- CPU time of the drawLayers slice in RenderEngine
re_draw_layers_nanos LONG,
-- GPU time of work submitted to RenderEngine
re_gpu_completion_nanos LONG,
-- CPU time of the flush call sent to Skia, observed from SF
skia_flush_nanos LONG,
-- CPU time of the submit call sent to Skia, observed from SF
skia_submit_nanos LONG,
-- Number of GPU composited layers for the workload
gpu_composited_layers LONG,
-- Number of DPU composited layers for the workload
dpu_composited_layers LONG
) AS
SELECT
extract_arg(arg_set_id, 'surfaceflinger_workload.workload_id') AS workload_id,
ts,
extract_arg(arg_set_id, 'surfaceflinger_workload.source') AS source,
extract_arg(arg_set_id, 'surfaceflinger_workload.output_name') AS output_name,
extract_arg(arg_set_id, 'surfaceflinger_workload.vsync_id') AS sf_vsync,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.timings.sf_cpu.frame_signal_nanos') AS sf_cpu_frame_signal_nanos,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.timings.sf_cpu.commit_nanos') AS sf_cpu_commit_nanos,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.timings.sf_cpu.composite_nanos') AS sf_cpu_composite_nanos,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.timings.hwc.present_nanos') AS hwc_present_nanos,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.timings.hwc.validate_nanos') AS hwc_validate_nanos,
extract_arg(
arg_set_id,
'surfaceflinger_workload.summary.timings.hwc.present_or_validate_nanos'
) AS hwc_present_or_validate_nanos,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.timings.re.draw_layers_nanos') AS re_draw_layers_nanos,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.timings.re.gpu_completion_nanos') AS re_gpu_completion_nanos,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.timings.skia.flush_nanos') AS skia_flush_nanos,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.timings.skia.submit_nanos') AS skia_submit_nanos,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.stats.gpu_composited_layers') AS gpu_composited_layers,
extract_arg(arg_set_id, 'surfaceflinger_workload.summary.stats.dpu_composited_layers') AS dpu_composited_layers
FROM slice
WHERE
category = 'rendering' AND name = 'WorkloadSummary';
-- Skia pipelines used in SurfaceFlinger workloads.
-- As there can be many skia pipelines used in a workload, this table is flattened.
CREATE PERFETTO TABLE android_surfaceflinger_workload_pipelines (
-- Identifier for the workload, matches android_surfaceflinger_workloads.workload_id
workload_id JOINID(android_surfaceflinger_workloads.workload_id),
-- Key that identifies the shader
shader_key STRING,
-- Operation that the caching pipeline used
caching_op STRING
) AS
SELECT
extract_arg(s.arg_set_id, 'surfaceflinger_workload.workload_id') AS workload_id,
extract_arg(
s.arg_set_id,
'surfaceflinger_workload.summary.stats.skia_pipelines[' || i.value || '].shader_key'
) AS shader_key,
extract_arg(
s.arg_set_id,
'surfaceflinger_workload.summary.stats.skia_pipelines[' || i.value || '].caching_op'
) AS caching_op
FROM slice AS s
JOIN (
SELECT
arg_set_id,
cast_int!(str_split(str_split(key, '[', 1), ']', 0)) AS value
FROM args
WHERE
key GLOB 'surfaceflinger_workload.summary.stats.skia_pipelines[[]*[]].shader_key'
) AS i
ON s.arg_set_id = i.arg_set_id
WHERE
s.category = 'rendering' AND s.name = 'WorkloadSummary';