blob: 531ebbc8655dddf521bd12494cf01513a8de7fe0 [file] [log] [blame]
--
-- Copyright 2020 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.
CREATE VIEW IF NOT EXISTS android_sysui_cuj_output AS
WITH last_cuj AS (
SELECT
process.name AS process_name,
process.upid AS upid,
main_thread.utid AS main_thread_utid,
main_thread.name AS main_thread_name,
thread_track.id AS main_thread_track_id,
slice.name AS slice_name,
ts AS ts_start,
ts + dur AS ts_end
FROM slice
JOIN process_track ON slice.track_id = process_track.id
JOIN process USING (upid)
JOIN thread AS main_thread ON main_thread.upid = process.upid AND main_thread.is_main_thread
JOIN thread_track USING (utid)
WHERE
slice.name LIKE 'Cuj<%>'
AND slice.dur > 0
AND process.name IN (
'com.android.systemui',
'com.google.android.apps.nexuslauncher')
ORDER BY ts desc
LIMIT 1
),
render_thread AS (
SELECT thread.*, last_cuj.ts_start as ts_cuj_start, last_cuj.ts_end as ts_cuj_end
FROM thread
JOIN last_cuj USING (upid)
WHERE thread.name = 'RenderThread'
),
gpu_completion_thread AS (
SELECT thread.*, last_cuj.ts_start as ts_cuj_start, last_cuj.ts_end as ts_cuj_end
FROM thread
JOIN last_cuj USING (upid)
WHERE thread.name = 'GPU completion'
),
main_thread_slices AS (
SELECT slice.*, ts + dur AS ts_end
FROM slice
JOIN last_cuj ON slice.track_id = last_cuj.main_thread_track_id
WHERE ts >= last_cuj.ts_start AND ts <= last_cuj.ts_end
),
render_thread_slices AS (
SELECT slice.*, ts + dur AS ts_end
FROM slice
JOIN thread_track ON slice.track_id = thread_track.id
JOIN render_thread USING (utid)
WHERE ts >= ts_cuj_start AND ts <= ts_cuj_end
),
gpu_completion_slices AS (
SELECT slice.*, ts + dur AS ts_end
FROM slice
JOIN thread_track ON slice.track_id = thread_track.id
JOIN gpu_completion_thread USING (utid)
WHERE
slice.name LIKE 'waiting for GPU completion %'
AND ts >= ts_cuj_start AND ts <= ts_cuj_end
),
frames AS (
SELECT
ROW_NUMBER() OVER (ORDER BY mts.ts) AS frame_number,
mts.ts AS ts_frame_start,
MIN(gcs.ts_end) AS ts_frame_end,
mts.ts AS ts_main_thread_start,
mts.ts_end AS ts_main_thread_end,
mts.dur AS dur_main_thread,
rts.ts AS ts_render_thread_start,
rts.ts_end AS ts_render_thread_end,
rts.dur AS dur_render_thread,
(MIN(gcs.ts_end) - mts.ts) AS dur
FROM main_thread_slices mts
JOIN render_thread_slices rts
ON mts.ts < rts.ts AND rts.name = 'DrawFrame'
JOIN gpu_completion_slices gcs ON rts.ts < gcs.ts
WHERE mts.name = 'Choreographer#doFrame'
GROUP BY mts.ts
),
main_thread_state AS (
SELECT
f.frame_number,
mts.state,
SUM(mts.dur) / 1000000 AS duration_millis,
SUM(mts.io_wait) AS io_wait
FROM frames f
JOIN thread_state mts
ON mts.ts >= f.ts_main_thread_start AND mts.ts < f.ts_main_thread_end
WHERE mts.utid = (SELECT main_thread_utid FROM last_cuj)
GROUP BY f.frame_number, mts.state
HAVING duration_millis > 0
),
render_thread_state AS (
SELECT
f.frame_number,
rts.state,
SUM(rts.dur) / 1000000 AS duration_millis,
SUM(rts.io_wait) AS io_wait
FROM frames f
JOIN thread_state rts
ON rts.ts >= f.ts_render_thread_start AND rts.ts < f.ts_render_thread_end
WHERE rts.utid in (SELECT utid FROM render_thread)
GROUP BY f.frame_number, rts.state
HAVING duration_millis > 0
),
main_thread_binder AS (
SELECT
f.frame_number,
SUM(mts.dur) / 1000000 AS duration_millis,
COUNT(*) AS call_count
FROM frames f
JOIN main_thread_slices mts
ON mts.ts >= f.ts_main_thread_start AND mts.ts < f.ts_main_thread_end
WHERE mts.name = 'binder transaction'
GROUP BY f.frame_number
),
jank_causes AS (
SELECT
frame_number,
'RenderThread - long shader_compile' AS jank_cause
FROM frames f
JOIN render_thread_slices rts
ON rts.ts >= f.ts_render_thread_start AND rts.ts < f.ts_render_thread_end
WHERE rts.name = 'shader_compile'
AND rts.dur / 1000000 > 8
UNION ALL
SELECT
frame_number,
'RenderThread - long flush layers' AS jank_cause
FROM frames f
JOIN render_thread_slices rts
ON rts.ts >= f.ts_render_thread_start AND rts.ts < f.ts_render_thread_end
WHERE rts.name = 'flush layers'
AND rts.dur / 1000000 > 8
UNION ALL
SELECT
frame_number,
'MainThread - IO wait time' AS jank_cause
FROM main_thread_state
WHERE state = 'DK' AND duration_millis > 8
UNION ALL
SELECT
frame_number,
'RenderThread - IO wait time' AS jank_cause
FROM render_thread_state
WHERE state = 'DK' AND duration_millis > 8
UNION ALL
SELECT
frame_number,
'MainThread - binder transaction time' AS jank_cause
FROM main_thread_binder
WHERE duration_millis > 8
UNION ALL
SELECT
frame_number,
'MainThread - binder calls count' AS jank_cause
FROM main_thread_binder
WHERE call_count > 8
)
SELECT
AndroidSysUiCujMetrics(
'frames',
(SELECT RepeatedField(
AndroidSysUiCujMetrics_Frame(
'number', f.frame_number,
'ts', f.ts_frame_start,
'dur', f.dur,
'jank_cause',
(SELECT RepeatedField(jc.jank_cause)
FROM jank_causes jc WHERE jc.frame_number = f.frame_number)))
FROM frames f
ORDER BY frame_number ASC))