1-- 2-- Copyright 2022 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-- A scroll jank metric based on EventLatency slices. 17-- 18-- We define an update to be janky if comparing forwards or backwards (ignoring 19-- coalesced and not shown on the screen updates) a given updates exceeds the duration 20-- of its predecessor or successor by 50% of a vsync interval (defaulted to 60 FPS). 21-- 22-- WARNING: This metric should not be used as a source of truth. It is under 23-- active development and the values & meaning might change without 24-- notice. 25 26SELECT RUN_METRIC('chrome/jank_utilities.sql'); 27SELECT RUN_METRIC('chrome/event_latency_to_breakdowns.sql'); 28SELECT RUN_METRIC('chrome/vsync_intervals.sql'); 29 30-- Creates table view where each EventLatency event has its upid. 31DROP VIEW IF EXISTS event_latency_with_track; 32CREATE VIEW event_latency_with_track 33AS 34SELECT 35 slice.*, 36 process_track.upid AS upid 37FROM slice JOIN process_track 38 ON slice.track_id = process_track.id 39WHERE slice.name = "EventLatency"; 40 41-- Select scroll EventLatency events that were shown on the screen. 42-- An update event was shown on the screen if and only if 43-- it has a "SubmitCompositorFrameToPresentationCompositorFrame" breakdown. 44-- But this logic is not applied for begin events, because a begin event is an artifical marker 45-- and never gets shown to the screen because it doesn't contain any update. 46-- Also it automaticly only includes non-coalesced EventLatency events, 47-- because coalesced ones are not shown on the screen. 48DROP VIEW IF EXISTS filtered_scroll_event_latency; 49CREATE VIEW filtered_scroll_event_latency 50AS 51WITH shown_on_display_event_latency_ids AS ( 52 SELECT 53 event_latency_id 54 FROM event_latency_breakdowns 55 WHERE name = "SubmitCompositorFrameToPresentationCompositorFrame" OR event_type = "GESTURE_SCROLL_BEGIN" 56) 57SELECT 58 event_latency_with_track.id, 59 event_latency_with_track.track_id, 60 event_latency_with_track.upid, 61 event_latency_with_track.ts, 62 event_latency_with_track.dur, 63 EXTRACT_ARG(event_latency_with_track.arg_set_id, "event_latency.event_type") AS event_type 64FROM event_latency_with_track JOIN shown_on_display_event_latency_ids 65 ON event_latency_with_track.id = shown_on_display_event_latency_ids.event_latency_id 66WHERE 67 event_type IN ( 68 "GESTURE_SCROLL_BEGIN", "GESTURE_SCROLL_UPDATE", 69 "INERTIAL_GESTURE_SCROLL_UPDATE", "FIRST_GESTURE_SCROLL_UPDATE"); 70 71-- Select begin events and it's next begin event witin the same process (same upid). 72-- 73-- Note: Must be a TABLE because it uses a window function which can behave 74-- strangely in views. 75DROP TABLE IF EXISTS scroll_event_latency_begins; 76CREATE TABLE scroll_event_latency_begins 77AS 78SELECT 79 *, 80 LEAD(ts) OVER sorted_begins AS next_gesture_begin_ts 81FROM filtered_scroll_event_latency 82WHERE event_type = "GESTURE_SCROLL_BEGIN" 83WINDOW sorted_begins AS (PARTITION BY upid ORDER BY ts ASC); 84 85-- For each scroll update event finds it's begin event. 86-- Pair [upid, next_gesture_begin_ts] represent a gesture key. 87-- We need to know the gesture key of gesture scroll to calculate a jank only within this gesture scroll. 88-- Because different gesture scrolls can have different properties. 89DROP VIEW IF EXISTS scroll_event_latency_updates; 90CREATE VIEW scroll_event_latency_updates 91AS 92SELECT 93 filtered_scroll_event_latency.*, 94 scroll_event_latency_begins.ts AS gesture_begin_ts, 95 scroll_event_latency_begins.next_gesture_begin_ts AS next_gesture_begin_ts 96FROM filtered_scroll_event_latency LEFT JOIN scroll_event_latency_begins 97 ON filtered_scroll_event_latency.ts >= scroll_event_latency_begins.ts 98 AND (filtered_scroll_event_latency.ts < next_gesture_begin_ts OR next_gesture_begin_ts IS NULL) 99 AND filtered_scroll_event_latency.upid = scroll_event_latency_begins.upid 100WHERE filtered_scroll_event_latency.id != scroll_event_latency_begins.id 101 AND filtered_scroll_event_latency.event_type != "GESTURE_SCROLL_BEGIN"; 102 103-- Find the last EventLatency scroll update event in the scroll. 104-- We will use the last EventLatency event insted of "InputLatency::GestureScrollEnd" event. 105-- We need to know when the scroll gesture ends so that we can later calculate 106-- the average vsync interval just up to the end of the gesture. 107DROP VIEW IF EXISTS scroll_event_latency_updates_ends; 108CREATE VIEW scroll_event_latency_updates_ends 109AS 110SELECT 111 id, 112 upid, 113 gesture_begin_ts, 114 ts, 115 dur, 116 MAX(ts + dur) AS gesture_end_ts 117FROM scroll_event_latency_updates 118GROUP BY upid, gesture_begin_ts; 119 120DROP VIEW IF EXISTS scroll_event_latency_updates_with_ends; 121CREATE VIEW scroll_event_latency_updates_with_ends 122AS 123SELECT 124 scroll_event_latency_updates.*, 125 scroll_event_latency_updates_ends.gesture_end_ts AS gesture_end_ts 126FROM scroll_event_latency_updates LEFT JOIN scroll_event_latency_updates_ends 127 ON scroll_event_latency_updates.upid = scroll_event_latency_updates_ends.upid 128 AND scroll_event_latency_updates.gesture_begin_ts = scroll_event_latency_updates_ends.gesture_begin_ts; 129 130-- Creates table where each event contains info about it's previous and next events. 131-- We consider only previous and next events from the same scroll id 132-- to don't calculate a jank between different scrolls. 133-- 134-- Note: Must be a TABLE because it uses a window function which can behave 135-- strangely in views. 136DROP TABLE IF EXISTS scroll_event_latency_with_neighbours; 137CREATE TABLE scroll_event_latency_with_neighbours 138AS 139SELECT 140 *, 141 LEAD(id) OVER sorted_events AS next_id, 142 LEAD(ts) OVER sorted_events AS next_ts, 143 LEAD(dur) OVER sorted_events AS next_dur, 144 LAG(id) OVER sorted_events AS prev_id, 145 LAG(ts) OVER sorted_events AS prev_ts, 146 LAG(dur) OVER sorted_events AS prev_dur, 147 CalculateAvgVsyncInterval(gesture_begin_ts, gesture_end_ts) AS avg_vsync_interval 148FROM scroll_event_latency_updates_with_ends 149WINDOW sorted_events AS (PARTITION BY upid, next_gesture_begin_ts ORDER BY id ASC, ts ASC); 150 151DROP VIEW IF EXISTS scroll_event_latency_neighbors_jank; 152CREATE VIEW scroll_event_latency_neighbors_jank 153AS 154SELECT 155 IsJankyFrame(gesture_begin_ts, gesture_begin_ts, next_ts, 156 gesture_begin_ts, gesture_end_ts, dur / avg_vsync_interval, next_dur / avg_vsync_interval) AS next_jank, 157 IsJankyFrame(gesture_begin_ts, gesture_begin_ts, prev_ts, 158 gesture_begin_ts, gesture_end_ts, dur / avg_vsync_interval, prev_dur / avg_vsync_interval) AS prev_jank, 159 scroll_event_latency_with_neighbours.* 160FROM scroll_event_latency_with_neighbours; 161 162-- Creates a view where each event contains information about whether it is janky 163-- with respect to previous and next events within the same scroll. 164DROP VIEW IF EXISTS scroll_event_latency_jank; 165CREATE VIEW scroll_event_latency_jank 166AS 167SELECT 168 (next_jank IS NOT NULL AND next_jank) OR (prev_jank IS NOT NULL AND prev_jank) AS jank, 169 * 170FROM scroll_event_latency_neighbors_jank; 171