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; 17INCLUDE PERFETTO MODULE android.frames.timeline; 18 19-- The amount by which each frame missed of hit its deadline. Positive if the 20-- deadline was not missed. Frames are considered janky if `overrun` is 21-- negative. 22-- Calculated as the difference between the end of the 23-- `expected_frame_timeline_slice` and `actual_frame_timeline_slice` for the 24-- frame. 25-- Availability: from S (API 31). 26-- For Googlers: more details in go/android-performance-metrics-glossary. 27CREATE PERFETTO TABLE android_frames_overrun( 28 -- Frame id. 29 frame_id INT, 30 -- Difference between `expected` and `actual` frame ends. Positive if frame 31 -- didn't miss deadline. 32 overrun INT 33) AS 34SELECT 35 frame_id, 36 (exp_slice.ts + exp_slice.dur) - (act_slice.ts + act_slice.dur) AS overrun 37FROM _distinct_from_actual_timeline_slice act 38JOIN _distinct_from_expected_timeline_slice exp USING (frame_id) 39JOIN slice act_slice ON (act.id = act_slice.id) 40JOIN slice exp_slice ON (exp.id = exp_slice.id); 41 42-- How much time did the frame's Choreographer callbacks take. 43CREATE PERFETTO TABLE android_frames_ui_time( 44 -- Frame id 45 frame_id INT, 46 -- UI time duration 47 ui_time INT 48) AS 49SELECT 50 frame_id, 51 dur AS ui_time 52FROM android_frames_choreographer_do_frame f 53JOIN slice USING (id); 54 55-- App Vsync delay for a frame. The time between the VSYNC-app signal and the 56-- start of Choreographer work. 57-- Calculated as time difference between the actual frame start (from 58-- `actual_frame_timeline_slice`) and start of the `Choreographer#doFrame` 59-- slice. 60-- NOTE: Sometimes because of data losses `app_vsync_delay` can be negative. 61-- The frames where it happens are filtered out. 62-- For Googlers: more details in go/android-performance-metrics-glossary. 63CREATE PERFETTO TABLE android_app_vsync_delay_per_frame( 64 -- Frame id 65 frame_id INT, 66 -- App VSYNC delay. 67 app_vsync_delay INT 68) AS 69-- As there can be multiple `DrawFrame` slices, the `frames_surface_slices` 70-- table contains multiple rows for the same `frame_id` which only differ on 71-- `draw_frame_id`. As we don't care about `draw_frame_id` we can just collapse 72-- them. 73WITH distinct_frames AS ( 74 SELECT 75 frame_id, 76 do_frame_id, 77 actual_frame_timeline_id 78 FROM android_frames 79 GROUP BY 1 80) 81SELECT 82 frame_id, 83 act.ts - do_frame.ts AS app_vsync_delay 84FROM distinct_frames f 85JOIN slice act ON (f.actual_frame_timeline_id = act.id) 86JOIN slice do_frame ON (f.do_frame_id = do_frame.id) 87WHERE act.ts >= do_frame.ts; 88 89-- How much time did the frame take across the UI Thread + RenderThread. 90-- Calculated as sum of `app VSYNC delay` `Choreographer#doFrame` slice 91-- duration and summed durations of all `DrawFrame` slices associated with this 92-- frame. 93-- Availability: from N (API 24). 94-- For Googlers: more details in go/android-performance-metrics-glossary. 95CREATE PERFETTO TABLE android_cpu_time_per_frame( 96 -- Frame id 97 frame_id INT, 98 -- Difference between actual timeline of the frame and 99 -- `Choreographer#doFrame`. See `android_app_vsync_delay_per_frame` table for more details. 100 app_vsync_delay INT, 101 -- Duration of `Choreographer#doFrame` slice. 102 do_frame_dur INT, 103 -- Duration of `DrawFrame` slice. Summed duration of all `DrawFrame` 104 -- slices, if more than one. See `android_frames_draw_frame` for more details. 105 draw_frame_dur INT, 106 -- CPU time across the UI Thread + RenderThread. 107 cpu_time INT 108) AS 109WITH all_draw_frames AS ( 110SELECT 111 frame_id, 112 SUM(dur) as draw_frame_dur 113FROM android_frames_draw_frame 114JOIN slice USING (id) 115GROUP BY frame_id 116), 117distinct_frames AS ( 118 SELECT 119 frame_id, 120 do_frame_id, 121 actual_frame_timeline_id 122 FROM android_frames 123 GROUP BY 1 124) 125SELECT 126 frame_id, 127 app_vsync_delay, 128 do_frame.dur AS do_frame_dur, 129 draw_frame_dur, 130 app_vsync_delay + do_frame.dur + draw_frame_dur AS cpu_time 131FROM android_app_vsync_delay_per_frame 132JOIN all_draw_frames USING (frame_id) 133JOIN distinct_frames f USING (frame_id) 134JOIN slice do_frame ON (f.do_frame_id = do_frame.id); 135 136-- CPU time of frames which don't have `android_cpu_time_per_frame` available. 137-- Calculated as UI time of the frame + 5ms. 138-- For Googlers: more details in go/android-performance-metrics-glossary. 139CREATE PERFETTO TABLE _cpu_time_per_frame_fallback( 140 -- Frame id. 141 frame_id INT, 142 -- Estimated cpu time. 143 estimated_cpu_time INT 144) AS 145SELECT 146 frame_id, 147 ui_time + time_from_ms(5) AS estimated_cpu_time 148FROM android_frames_ui_time; 149 150CREATE PERFETTO TABLE _estimated_cpu_time_per_frame( 151 frame_id INT, 152 cpu_time INT 153) AS 154SELECT 155 frame_id, 156 IIF(r.cpu_time IS NULL, f.estimated_cpu_time, r.cpu_time) AS cpu_time 157FROM _cpu_time_per_frame_fallback f 158LEFT JOIN android_cpu_time_per_frame r USING (frame_id); 159 160-- Aggregated stats of the frame. 161-- 162-- For Googlers: more details in go/android-performance-metrics-glossary. 163CREATE PERFETTO TABLE android_frame_stats( 164 -- Frame id. 165 frame_id INT, 166 -- The amount by which each frame missed of hit its deadline. See 167 -- `android_frames_overrun` for details. 168 overrun INT, 169 -- How much time did the frame take across the UI Thread + RenderThread. 170 cpu_time INT, 171 -- How much time did the frame's Choreographer callbacks take. 172 ui_time INT, 173 -- Was frame janky. 174 was_jank BOOL, 175 -- CPU time of the frame took over 20ms. 176 was_slow_frame BOOL, 177 -- CPU time of the frame took over 50ms. 178 was_big_jank BOOL, 179 -- CPU time of the frame took over 200ms. 180 was_huge_jank BOOL 181) AS 182SELECT 183 frame_id, 184 overrun, 185 cpu_time, 186 ui_time, 187 IIF(overrun < 0, 1, NULL) AS was_jank, 188 IIF(cpu_time > time_from_ms(20), 1, NULL) AS was_slow_frame, 189 IIF(cpu_time > time_from_ms(50), 1, NULL) AS was_big_jank, 190 IIF(cpu_time > time_from_ms(200), 1, NULL) AS was_huge_jank 191FROM android_frames_overrun 192JOIN android_frames_ui_time USING (frame_id) 193-- Because some frames might not have CPU time calculated properly (data loss 194-- or too old API), we will use fallback cpu time from 195-- `_cpu_time_per_frame_fallback`. 196JOIN _estimated_cpu_time_per_frame USING (frame_id); 197 198