1-- 2-- Copyright 2024 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 16INCLUDE PERFETTO MODULE time.conversion; 17 18INCLUDE PERFETTO MODULE android.frames.timeline; 19 20-- `actual_frame_timeline_slice` returns the same slice name for different layer IDs or tracks. 21-- This happens because there can be multiple slices associated with a single frame_id. 22-- We are interested in unique names(frame_id) and the respective counts. 23-- This is a legacy table which is moved to this file because the android_frames_overrun table depends on it. 24CREATE PERFETTO TABLE _frame_id_count_in_actual_timeline AS 25SELECT 26 cast_int!(name) AS frame_id, 27 min(id) AS id, 28 min(ts) AS ts, 29 max(dur) AS dur, 30 max(ts + dur) AS ts_end, 31 count() AS count 32FROM actual_frame_timeline_slice 33GROUP BY 34 1; 35 36-- `expected_frame_timeline_slice` returns the same slice name for different tracks. 37-- This happens because there can be multiple slices associated with a single frame_id. 38-- We are interested in unique names(frame_id) and the respective counts. 39-- This is a legacy table which is moved to this file because the android_frames_overrun table depends on it. 40CREATE PERFETTO TABLE _frame_id_count_in_expected_timeline AS 41SELECT 42 cast_int!(name) AS frame_id, 43 id, 44 count() AS count 45FROM expected_frame_timeline_slice 46GROUP BY 47 1; 48 49-- The amount by which each frame missed of hit its deadline. Negative if the 50-- deadline was not missed. Frames are considered janky if `overrun` is 51-- positive. 52-- Calculated as the difference between the end of the 53-- `expected_frame_timeline_slice` and `actual_frame_timeline_slice` for the 54-- frame. 55-- Availability: from S (API 31). 56-- For Googlers: more details in go/android-performance-metrics-glossary. 57CREATE PERFETTO TABLE android_frames_overrun ( 58 -- Frame id. 59 frame_id LONG, 60 -- Difference between `expected` and `actual` frame ends. Negative if frame 61 -- didn't miss deadline. 62 overrun LONG 63) AS 64SELECT 65 frame_id, 66 ( 67 act_slice.ts + act_slice.dur 68 ) - ( 69 exp_slice.ts + exp_slice.dur 70 ) AS overrun 71FROM _frame_id_count_in_actual_timeline AS act 72JOIN _frame_id_count_in_expected_timeline AS exp 73 USING (frame_id) 74JOIN slice AS act_slice 75 ON ( 76 act.id = act_slice.id 77 ) 78JOIN slice AS exp_slice 79 ON ( 80 exp.id = exp_slice.id 81 ); 82 83-- How much time did the frame's Choreographer callbacks take. 84CREATE PERFETTO TABLE android_frames_ui_time ( 85 -- Frame id 86 frame_id LONG, 87 -- UI time duration 88 ui_time LONG 89) AS 90SELECT 91 frame_id, 92 dur AS ui_time 93FROM android_frames_choreographer_do_frame AS f 94JOIN slice 95 USING (id); 96 97-- App Vsync delay for a frame. The time between the VSYNC-app signal and the 98-- start of Choreographer work. 99-- Calculated as time difference between the actual frame start (from 100-- `actual_frame_timeline_slice`) and start of the `Choreographer#doFrame` 101-- slice. 102-- For Googlers: more details in go/android-performance-metrics-glossary. 103CREATE PERFETTO TABLE android_app_vsync_delay_per_frame ( 104 -- Frame id 105 frame_id LONG, 106 -- App VSYNC delay. 107 app_vsync_delay LONG 108) AS 109-- As there can be multiple `DrawFrame` slices, the `frames_surface_slices` 110-- table contains multiple rows for the same `frame_id` which only differ on 111-- `draw_frame_id`. As we don't care about `draw_frame_id` we can just collapse 112-- them. 113WITH 114 distinct_frames AS ( 115 SELECT 116 frame_id, 117 do_frame_id, 118 actual_frame_timeline_id, 119 expected_frame_timeline_id 120 FROM android_frames 121 GROUP BY 122 1 123 ) 124SELECT 125 frame_id, 126 act.ts - exp.ts AS app_vsync_delay 127FROM distinct_frames AS f 128JOIN slice AS exp 129 ON ( 130 f.expected_frame_timeline_id = exp.id 131 ) 132JOIN slice AS act 133 ON ( 134 f.actual_frame_timeline_id = act.id 135 ); 136 137-- How much time did the frame take across the UI Thread + RenderThread. 138-- Calculated as sum of `app VSYNC delay` `Choreographer#doFrame` slice 139-- duration and summed durations of all `DrawFrame` slices associated with this 140-- frame. 141-- Availability: from N (API 24). 142-- For Googlers: more details in go/android-performance-metrics-glossary. 143CREATE PERFETTO TABLE android_cpu_time_per_frame ( 144 -- Frame id 145 frame_id LONG, 146 -- Difference between actual timeline of the frame and 147 -- `Choreographer#doFrame`. See `android_app_vsync_delay_per_frame` table for more details. 148 app_vsync_delay LONG, 149 -- Duration of `Choreographer#doFrame` slice. 150 do_frame_dur DURATION, 151 -- Duration of `DrawFrame` slice. Summed duration of all `DrawFrame` 152 -- slices, if more than one. See `android_frames_draw_frame` for more details. 153 draw_frame_dur DURATION, 154 -- CPU time across the UI Thread + RenderThread. 155 cpu_time LONG 156) AS 157WITH 158 all_draw_frames AS ( 159 SELECT 160 frame_id, 161 sum(dur) AS draw_frame_dur 162 FROM android_frames_draw_frame 163 JOIN slice 164 USING (id) 165 GROUP BY 166 frame_id 167 ), 168 distinct_frames AS ( 169 SELECT 170 frame_id, 171 do_frame_id, 172 actual_frame_timeline_id 173 FROM android_frames 174 GROUP BY 175 1 176 ) 177SELECT 178 frame_id, 179 app_vsync_delay, 180 do_frame.dur AS do_frame_dur, 181 draw_frame_dur, 182 app_vsync_delay + do_frame.dur + draw_frame_dur AS cpu_time 183FROM android_app_vsync_delay_per_frame 184JOIN all_draw_frames 185 USING (frame_id) 186JOIN distinct_frames AS f 187 USING (frame_id) 188JOIN slice AS do_frame 189 ON ( 190 f.do_frame_id = do_frame.id 191 ); 192 193-- CPU time of frames which don't have `android_cpu_time_per_frame` available. 194-- Calculated as UI time of the frame + 5ms. 195-- For Googlers: more details in go/android-performance-metrics-glossary. 196CREATE PERFETTO TABLE _cpu_time_per_frame_fallback ( 197 -- Frame id. 198 frame_id LONG, 199 -- Estimated cpu time. 200 estimated_cpu_time LONG 201) AS 202SELECT 203 frame_id, 204 ui_time + time_from_ms(5) AS estimated_cpu_time 205FROM android_frames_ui_time; 206 207CREATE PERFETTO TABLE _estimated_cpu_time_per_frame ( 208 frame_id LONG, 209 cpu_time LONG 210) AS 211SELECT 212 frame_id, 213 iif(r.cpu_time IS NULL, f.estimated_cpu_time, r.cpu_time) AS cpu_time 214FROM _cpu_time_per_frame_fallback AS f 215LEFT JOIN android_cpu_time_per_frame AS r 216 USING (frame_id); 217 218-- Aggregated stats of the frame. 219-- 220-- For Googlers: more details in go/android-performance-metrics-glossary. 221CREATE PERFETTO TABLE android_frame_stats ( 222 -- Frame id. 223 frame_id LONG, 224 -- The amount by which each frame missed of hit its deadline. See 225 -- `android_frames_overrun` for details. 226 overrun LONG, 227 -- How much time did the frame take across the UI Thread + RenderThread. 228 cpu_time LONG, 229 -- How much time did the frame's Choreographer callbacks take. 230 ui_time LONG, 231 -- Was frame janky. 232 was_jank BOOL, 233 -- CPU time of the frame took over 20ms. 234 was_slow_frame BOOL, 235 -- CPU time of the frame took over 50ms. 236 was_big_jank BOOL, 237 -- CPU time of the frame took over 200ms. 238 was_huge_jank BOOL 239) AS 240SELECT 241 frame_id, 242 overrun, 243 cpu_time, 244 ui_time, 245 iif(overrun > 0, 1, NULL) AS was_jank, 246 iif(cpu_time > time_from_ms(20), 1, NULL) AS was_slow_frame, 247 iif(cpu_time > time_from_ms(50), 1, NULL) AS was_big_jank, 248 iif(cpu_time > time_from_ms(200), 1, NULL) AS was_huge_jank 249FROM android_frames_overrun 250JOIN android_frames_ui_time 251 USING (frame_id) 252JOIN _estimated_cpu_time_per_frame 253 USING (frame_id); 254