• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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