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-- Create the base table (`android_jank_cuj`) containing all completed CUJs 17-- found in the trace. 18-- This script will use the `android_jank_cuj_main_thread_cuj_boundary`, 19-- containing bounds of jank CUJs. 20SELECT RUN_METRIC('android/android_jank_cuj.sql'); 21 22INCLUDE PERFETTO MODULE android.slices; 23INCLUDE PERFETTO MODULE android.binder; 24INCLUDE PERFETTO MODULE android.critical_blocking_calls; 25 26-- Jank "J<*>" and latency "L<*>" cujs are put together in android_cujs table. 27-- They are computed separately as latency ones are slightly different, don't 28-- currently have the same way to be cancelled, and are not anchored to vsyncs. 29DROP TABLE IF EXISTS android_cujs; 30CREATE TABLE android_cujs AS 31WITH latency_cujs AS ( 32 SELECT 33 ROW_NUMBER() OVER (ORDER BY ts) AS cuj_id, 34 process.upid AS upid, 35 process.name AS process_name, 36 process_metadata.metadata AS process_metadata, 37 -- Extracts "CUJ_NAME" from "L<CUJ_NAME>" 38 SUBSTR(slice.name, 3, LENGTH(slice.name) - 3) AS cuj_name, 39 ts, 40 dur, 41 ts + dur AS ts_end, 42 'completed' AS state 43 FROM slice 44 JOIN process_track 45 ON slice.track_id = process_track.id 46 JOIN process USING (upid) 47 JOIN process_metadata USING (upid) 48 WHERE 49 slice.name GLOB 'L<*>' 50 AND dur > 0 51), 52all_cujs AS ( 53 SELECT 54 cuj_id, 55 upid, 56 process_name, 57 process_metadata, 58 cuj_name, 59 tb.ts, 60 tb.dur, 61 tb.ts_end 62 FROM android_jank_cuj_main_thread_cuj_boundary tb 63 JOIN android_jank_cuj using (cuj_id) 64UNION 65 SELECT 66 cuj_id, 67 upid, 68 process_name, 69 process_metadata, 70 cuj_name, 71 ts, 72 dur, 73 ts_end 74 FROM latency_cujs 75) 76SELECT ROW_NUMBER() OVER (ORDER BY ts) AS cuj_id, * 77FROM all_cujs; 78 79-- We have: 80-- (1) a list of slices from the main thread of each process from the 81-- all_main_thread_relevant_slices table. 82-- (2) a list of android cuj with beginning, end, and process 83-- It's needed to: 84-- (1) assign a cuj to each slice. If there are multiple cujs going on during a 85-- slice, there needs to be 2 entries for that slice, one for each cuj id. 86-- (2) each slice needs to be trimmed to be fully inside the cuj associated 87-- (as we don't care about what's outside cujs) 88DROP TABLE IF EXISTS android_blocking_calls_cuj_calls; 89CREATE TABLE android_blocking_calls_cuj_calls AS 90WITH 91main_thread_slices_scoped_to_cujs AS ( 92SELECT 93 s.id, 94 s.id AS slice_id, 95 s.name, 96 max(s.ts, cuj.ts) AS ts, 97 min(s.ts + s.dur, cuj.ts_end) as ts_end, 98 min(s.ts + s.dur, cuj.ts_end) - max(s.ts, cuj.ts) AS dur, 99 cuj.cuj_id, 100 cuj.cuj_name, 101 s.process_name, 102 s.upid, 103 s.utid 104FROM _android_critical_blocking_calls s 105 JOIN android_cujs cuj 106 -- only when there is an overlap 107 ON s.ts + s.dur > cuj.ts AND s.ts < cuj.ts_end 108 -- and are from the same process 109 AND s.upid = cuj.upid 110) 111SELECT 112 name, 113 COUNT(*) AS occurrences, 114 MAX(dur) AS max_dur_ns, 115 MIN(dur) AS min_dur_ns, 116 SUM(dur) AS total_dur_ns, 117 upid, 118 cuj_id, 119 cuj_name, 120 process_name 121FROM 122 main_thread_slices_scoped_to_cujs 123GROUP BY name, upid, cuj_id, cuj_name, process_name 124ORDER BY cuj_id; 125 126 127DROP VIEW IF EXISTS android_blocking_calls_cuj_metric_output; 128CREATE PERFETTO VIEW android_blocking_calls_cuj_metric_output AS 129SELECT AndroidBlockingCallsCujMetric('cuj', ( 130 SELECT RepeatedField( 131 AndroidBlockingCallsCujMetric_Cuj( 132 'id', cuj_id, 133 'name', cuj_name, 134 'process', process_metadata, 135 'ts', cuj.ts, 136 'dur', cuj.dur, 137 'blocking_calls', ( 138 SELECT RepeatedField( 139 AndroidBlockingCall( 140 'name', b.name, 141 'cnt', b.occurrences, 142 'total_dur_ms', CAST(total_dur_ns / 1e6 AS INT), 143 'max_dur_ms', CAST(max_dur_ns / 1e6 AS INT), 144 'min_dur_ms', CAST(min_dur_ns / 1e6 AS INT), 145 'total_dur_ns', b.total_dur_ns, 146 'max_dur_ns', b.max_dur_ns, 147 'min_dur_ns', b.min_dur_ns 148 ) 149 ) 150 FROM android_blocking_calls_cuj_calls b 151 WHERE b.cuj_id = cuj.cuj_id and b.upid = cuj.upid 152 ORDER BY total_dur_ns DESC 153 ) 154 ) 155 ) 156 FROM android_cujs cuj 157 ORDER BY cuj.cuj_id ASC 158)); 159