• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1-- Copyright 2023 The Chromium Authors
2-- Use of this source code is governed by a BSD-style license that can be
3-- found in the LICENSE file.
4
5INCLUDE PERFETTO MODULE common.slices;
6
7-- Hardware info is useful when using sql metrics for analysis
8-- in BTP.
9INCLUDE PERFETTO MODULE chrome.metadata;
10INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_v3_cause;
11
12-- Grabs all gesture updates with respective scroll ids and start/end
13-- timestamps, regardless of being coalesced.
14CREATE PERFETTO TABLE chrome_gesture_scroll_updates(
15  -- The start timestamp of the scroll.
16  ts INT,
17  -- The duration of the scroll.
18  dur INT,
19  -- Slice id for the scroll.
20  id INT,
21  -- The id of the scroll update event.
22  scroll_update_id INT,
23  -- The id of the scroll.
24  scroll_id INT,
25  -- Whether this input event was coalesced.
26  is_coalesced BOOL
27) AS
28SELECT
29  ts,
30  dur,
31  id,
32  -- TODO(b/250089570) Add trace_id to EventLatency and update this script to use it.
33  EXTRACT_ARG(arg_set_id, 'chrome_latency_info.trace_id') AS scroll_update_id,
34  EXTRACT_ARG(arg_set_id, 'chrome_latency_info.gesture_scroll_id') AS scroll_id,
35  EXTRACT_ARG(arg_set_id, 'chrome_latency_info.is_coalesced') AS is_coalesced
36FROM slice
37WHERE name = "InputLatency::GestureScrollUpdate" AND dur != -1;
38
39CREATE PERFETTO TABLE internal_non_coalesced_gesture_scrolls AS
40SELECT
41  id,
42  ts,
43  dur,
44  scroll_update_id,
45  scroll_id
46FROM  chrome_gesture_scroll_updates
47WHERE is_coalesced = false
48ORDER BY ts ASC;
49
50-- Scroll updates, corresponding to all input events that were converted to a
51-- presented scroll update.
52CREATE PERFETTO TABLE chrome_presented_gesture_scrolls(
53  -- Minimum slice id for input presented in this frame, the non coalesced input.
54  id INT,
55  -- The start timestamp for producing the frame.
56  ts INT,
57  -- The duration between producing and presenting the frame.
58  dur INT,
59  -- The timestamp of the last input that arrived and got coalesced into the frame.
60  last_coalesced_input_ts INT,
61  -- The id of the scroll update event, a unique identifier to the gesture.
62  scroll_update_id INT,
63  -- The id of the ongoing scroll.
64  scroll_id INT
65) AS
66WITH
67scroll_updates_with_coalesce_info as MATERIALIZED (
68  SELECT
69    id,
70    ts,
71    -- For each scroll update, find the latest non-coalesced update which
72    -- happened before it. For coalesced scroll updates, this will be the
73    -- presented scroll update they have been coalesced into.
74    (
75      SELECT id
76      FROM internal_non_coalesced_gesture_scrolls non_coalesced
77      WHERE non_coalesced.ts <= scroll_update.ts
78      ORDER BY ts DESC
79      LIMIT 1
80     ) as coalesced_to_scroll_update_slice_id
81  FROM chrome_gesture_scroll_updates scroll_update
82  ORDER BY coalesced_to_scroll_update_slice_id, ts
83)
84SELECT
85  id,
86  ts,
87  dur,
88  -- Find the latest input that was coalesced into this scroll update.
89  (
90    SELECT coalesce_info.ts
91    FROM scroll_updates_with_coalesce_info coalesce_info
92    WHERE
93      coalesce_info.coalesced_to_scroll_update_slice_id =
94        internal_non_coalesced_gesture_scrolls.id
95    ORDER BY ts DESC
96    LIMIT 1
97  ) as last_coalesced_input_ts,
98  scroll_update_id,
99  scroll_id
100FROM internal_non_coalesced_gesture_scrolls;
101
102-- Associate every trace_id with it's perceived delta_y on the screen after
103-- prediction.
104CREATE PERFETTO TABLE chrome_scroll_updates_with_deltas(
105  -- The id of the scroll update event.
106  scroll_update_id INT,
107  -- The perceived delta_y on the screen post prediction.
108  delta_y INT
109) AS
110SELECT
111  EXTRACT_ARG(arg_set_id, 'scroll_deltas.trace_id') AS scroll_update_id,
112  EXTRACT_ARG(arg_set_id, 'scroll_deltas.provided_to_compositor_delta_y') AS delta_y
113FROM slice
114WHERE name = "InputHandlerProxy::HandleGestureScrollUpdate_Result";
115
116-- Extract event latency timestamps, to later use it for joining
117-- with gesture scroll updates, as event latencies don't have trace
118-- ids associated with it.
119CREATE PERFETTO TABLE chrome_gesture_scroll_event_latencies(
120  -- Start timestamp for the EventLatency.
121  ts INT,
122  -- Slice id of the EventLatency.
123  event_latency_id INT,
124  -- Duration of the EventLatency.
125  dur INT,
126  -- End timestamp for input aka the timestamp of the LatchToSwapEnd substage.
127  input_latency_end_ts INT,
128  -- Frame presentation timestamp aka the timestamp of the
129  -- SwapEndToPresentationCompositorFrame substage.
130  presentation_timestamp INT,
131  -- EventLatency event type.
132  event_type INT
133) AS
134SELECT
135  slice.ts,
136  slice.id AS event_latency_id,
137  slice.dur AS dur,
138  descendant_slice_end(slice.id, "LatchToSwapEnd") AS input_latency_end_ts,
139  descendant_slice_end(slice.id, "SwapEndToPresentationCompositorFrame") AS presentation_timestamp,
140  EXTRACT_ARG(arg_set_id, 'event_latency.event_type') AS event_type
141FROM slice
142WHERE name = "EventLatency"
143      AND event_type in (
144          "GESTURE_SCROLL_UPDATE",
145          "FIRST_GESTURE_SCROLL_UPDATE",
146          "INERTIAL_GESTURE_SCROLL_UPDATE")
147      AND has_descendant_slice_with_name(slice.id, "SwapEndToPresentationCompositorFrame");
148
149-- Join presented gesture scrolls with their respective event
150-- latencies based on |LatchToSwapEnd| timestamp, as it's the
151-- end timestamp for both the gesture scroll update slice and
152-- the LatchToSwapEnd slice.
153CREATE PERFETTO TABLE chrome_full_frame_view(
154  -- ID of the frame.
155  id INT,
156  -- Start timestamp of the frame.
157  ts INT,
158  -- The timestamp of the last coalesced input.
159  last_coalesced_input_ts INT,
160  -- ID of the associated scroll.
161  scroll_id INT,
162  -- ID of the associated scroll update.
163  scroll_update_id INT,
164  -- ID of the associated EventLatency.
165  event_latency_id INT,
166  -- Duration of the associated EventLatency.
167  dur INT,
168  -- Frame presentation timestamp.
169  presentation_timestamp INT
170) AS
171SELECT
172  frames.id,
173  frames.ts,
174  frames.last_coalesced_input_ts,
175  frames.scroll_id,
176  frames.scroll_update_id,
177  events.event_latency_id,
178  events.dur,
179  events.presentation_timestamp
180FROM chrome_presented_gesture_scrolls frames
181JOIN chrome_gesture_scroll_event_latencies events
182  ON frames.ts = events.ts
183  AND events.input_latency_end_ts = (frames.ts + frames.dur);
184
185-- Join deltas with EventLatency data.
186CREATE PERFETTO TABLE chrome_full_frame_delta_view(
187  -- ID of the frame.
188  id INT,
189  -- Start timestamp of the frame.
190  ts INT,
191  -- ID of the associated scroll.
192  scroll_id INT,
193  -- ID of the associated scroll update.
194  scroll_update_id INT,
195  -- The timestamp of the last coalesced input.
196  last_coalesced_input_ts INT,
197  -- The perceived delta_y on the screen post prediction.
198  delta_y INT,
199  -- ID of the associated EventLatency.
200  event_latency_id INT,
201  -- Duration of the associated EventLatency.
202  dur INT,
203  -- Frame presentation timestamp.
204  presentation_timestamp INT
205) AS
206SELECT
207  frames.id,
208  frames.ts,
209  frames.scroll_id,
210  frames.scroll_update_id,
211  frames.last_coalesced_input_ts,
212  deltas.delta_y,
213  frames.event_latency_id,
214  frames.dur,
215  frames.presentation_timestamp
216FROM chrome_full_frame_view frames
217LEFT JOIN chrome_scroll_updates_with_deltas deltas
218  ON deltas.scroll_update_id = frames.scroll_update_id;
219
220-- Group all gestures presented at the same timestamp together in
221-- a single row.
222CREATE PERFETTO VIEW chrome_merged_frame_view(
223  -- ID of the frame.
224  id INT,
225  -- The timestamp of the last coalesced input.
226  max_start_ts INT,
227  -- The earliest frame start timestamp.
228  min_start_ts INT,
229  -- ID of the associated scroll.
230  scroll_id INT,
231  -- ID of the associated scroll update.
232  scroll_update_id INT,
233  -- All scroll updates associated with the frame presentation timestamp.
234  encapsulated_scroll_ids INT,
235  -- Sum of all perceived delta_y values at the frame presentation timestamp.
236  total_delta INT,
237  -- Lists all of the perceived delta_y values at the frame presentation timestamp.
238  segregated_delta_y INT,
239  -- ID of the associated EventLatency.
240  event_latency_id INT,
241  -- Maximum duration of the associated EventLatency.
242  dur INT,
243  -- Frame presentation timestamp.
244  presentation_timestamp INT
245) AS
246SELECT
247  id,
248  MAX(last_coalesced_input_ts) AS max_start_ts,
249  MIN(ts) AS min_start_ts,
250  scroll_id,
251  scroll_update_id,
252  GROUP_CONCAT(scroll_update_id,',') AS encapsulated_scroll_ids,
253  SUM(delta_y) AS total_delta,
254  GROUP_CONCAT(delta_y, ',') AS segregated_delta_y,
255  event_latency_id,
256  MAX(dur) AS dur,
257  presentation_timestamp
258FROM chrome_full_frame_delta_view
259GROUP BY presentation_timestamp
260ORDER BY presentation_timestamp;
261
262-- View contains all chrome presented frames during gesture updates
263-- while calculating delay since last presented which usually should
264-- equal to |VSYNC_INTERVAL| if no jank is present.
265CREATE PERFETTO VIEW chrome_frame_info_with_delay(
266  -- gesture scroll slice id.
267  id INT,
268  -- OS timestamp of the last touch move arrival within a frame.
269  max_start_ts INT,
270  -- OS timestamp of the first touch move arrival within a frame.
271  min_start_ts INT,
272  -- The scroll which the touch belongs to.
273  scroll_id INT,
274  -- ID of the associated scroll update.
275  scroll_update_id INT,
276  -- Trace ids of all frames presented in at this vsync.
277  encapsulated_scroll_ids INT,
278  -- Summation of all delta_y of all gesture scrolls in this frame.
279  total_delta INT,
280  -- All delta y of all gesture scrolls comma separated, summing those gives |total_delta|.
281  segregated_delta_y INT,
282  -- Event latency id of the presented frame.
283  event_latency_id INT,
284  -- Duration of the EventLatency.
285  dur INT,
286  -- Timestamp at which the frame was shown on the screen.
287  presentation_timestamp INT,
288  -- Time elapsed since the previous frame was presented, usually equals |VSYNC|
289  -- if no frame drops happened.
290  delay_since_last_frame INT,
291  -- Difference in OS timestamps of inputs in the current and the previous frame.
292  delay_since_last_input INT,
293  -- The event latency id that will be used as a reference to determine the
294  -- jank cause.
295  prev_event_latency_id INT
296) AS
297SELECT
298  *,
299  (presentation_timestamp -
300  LAG(presentation_timestamp, 1, presentation_timestamp)
301  OVER (PARTITION BY scroll_id ORDER BY presentation_timestamp)) / 1e6 AS delay_since_last_frame,
302  (min_start_ts -
303  LAG(max_start_ts, 1, min_start_ts)
304  OVER (PARTITION BY scroll_id ORDER BY min_start_ts)) / 1e6 AS delay_since_last_input,
305  LAG(event_latency_id, 1, -1) OVER (PARTITION BY scroll_id ORDER BY min_start_ts) AS prev_event_latency_id
306FROM chrome_merged_frame_view;
307
308-- Calculate |VSYNC_INTERVAL| as the lowest delay between frames larger than
309-- zero.
310-- TODO(b/286222128): Emit this data from Chrome instead of calculating it.
311CREATE PERFETTO VIEW chrome_vsyncs(
312  -- The lowest delay between frames larger than zero.
313  vsync_interval INT
314) AS
315SELECT
316  MIN(delay_since_last_frame) AS vsync_interval
317FROM chrome_frame_info_with_delay
318WHERE delay_since_last_frame > 0;
319
320-- Filter the frame view only to frames that had missed vsyncs.
321CREATE PERFETTO VIEW chrome_janky_frames_no_cause(
322  -- Time elapsed since the previous frame was presented, will be more than |VSYNC| in this view.
323  delay_since_last_frame INT,
324  -- Event latency id of the presented frame.
325  event_latency_id INT,
326  -- Vsync interval at the time of recording the trace.
327  vsync_interval INT,
328  -- Device brand and model.
329  hardware_class STRING,
330  -- The scroll corresponding to this frame.
331  scroll_id INT,
332  -- The event latency id that will be used as a reference to determine the jank cause.
333  prev_event_latency_id INT
334) AS
335SELECT
336  delay_since_last_frame,
337  event_latency_id,
338  (SELECT vsync_interval FROM chrome_vsyncs) AS vsync_interval,
339  chrome_hardware_class() AS hardware_class,
340  scroll_id,
341  prev_event_latency_id
342FROM chrome_frame_info_with_delay
343WHERE delay_since_last_frame > (select vsync_interval + vsync_interval / 2 from chrome_vsyncs)
344      AND delay_since_last_input < (select vsync_interval + vsync_interval / 2 from chrome_vsyncs);
345
346-- Janky frame information including the jank cause.
347CREATE PERFETTO VIEW chrome_janky_frames_no_subcause(
348  -- Time elapsed since the previous frame was presented, will be more than |VSYNC| in this view.
349  delay_since_last_frame INT,
350  -- Event latency id of the presented frame.
351  event_latency_id INT,
352  -- Vsync interval at the time of recording the trace.
353  vsync_interval INT,
354  -- Device brand and model.
355  hardware_class STRING,
356  -- The scroll corresponding to this frame.
357  scroll_id INT,
358  -- The event latency id that will be used as a reference to determine the jank cause.
359  prev_event_latency_id INT,
360  -- Id of the slice corresponding to the offending stage.
361  cause_id INT
362) AS
363SELECT
364  *,
365  chrome_get_v3_jank_cause_id(event_latency_id, prev_event_latency_id) AS cause_id
366FROM chrome_janky_frames_no_cause;
367
368-- Finds all causes of jank for all janky frames, and a cause of sub jank
369-- if the cause of jank was GPU related.
370CREATE PERFETTO VIEW chrome_janky_frames(
371  -- The reason the Vsync was missed.
372  cause_of_jank INT,
373  -- Further breakdown if the root cause was GPU related.
374  sub_cause_of_jank INT,
375  -- Time elapsed since the previous frame was presented, will be more than |VSYNC| in this view.
376  delay_since_last_frame INT,
377  -- Event latency id of the presented frame.
378  event_latency_id INT,
379  -- Vsync interval at the time of recording the trace.
380  vsync_interval INT,
381  -- Device brand and model.
382  hardware_class STRING,
383  -- The scroll corresponding to this frame.
384  scroll_id INT
385) AS
386SELECT
387  slice_name_from_id(cause_id) AS cause_of_jank,
388  slice_name_from_id(
389    -- Getting sub-cause
390    chrome_get_v3_jank_cause_id(
391      -- Here the cause itself is the parent.
392      cause_id,
393      -- Get the previous cause id as a child to the previous |EventLatency|.
394     (SELECT
395      id
396      FROM slice
397      WHERE name = slice_name_from_id(cause_id)
398        AND parent_id = prev_event_latency_id)
399    )) AS sub_cause_of_jank,
400  delay_since_last_frame,
401  event_latency_id,
402  vsync_interval,
403  hardware_class,
404  scroll_id
405FROM chrome_janky_frames_no_subcause;
406
407-- Counting all unique frame presentation timestamps.
408CREATE PERFETTO VIEW chrome_unique_frame_presentation_ts(
409  -- The unique frame presentation timestamp.
410  presentation_timestamp INT
411) AS
412SELECT DISTINCT
413presentation_timestamp
414FROM chrome_gesture_scroll_event_latencies;
415
416-- Dividing missed frames over total frames to get janky frame percentage.
417-- This represents the v3 scroll jank metrics.
418-- Reflects Event.Jank.DelayedFramesPercentage UMA metric.
419CREATE PERFETTO VIEW chrome_janky_frames_percentage(
420  -- The percent of missed frames relative to total frames - aka the percent of janky frames.
421  delayed_frame_percentage FLOAT
422) AS
423SELECT
424(SELECT
425  COUNT()
426 FROM chrome_janky_frames) * 1.0
427/ (SELECT
428    COUNT()
429  FROM chrome_unique_frame_presentation_ts) * 100 AS delayed_frame_percentage;
430
431-- Number of frames and janky frames per scroll.
432CREATE PERFETTO VIEW chrome_frames_per_scroll(
433  -- The ID of the scroll.
434  scroll_id INT,
435  -- The number of frames in the scroll.
436  num_frames INT,
437  -- The number of delayed/janky frames.
438  num_janky_frames INT,
439  -- The percentage of janky frames relative to total frames.
440  scroll_jank_percentage INT
441) AS
442WITH
443  frames AS (
444    SELECT scroll_id, COUNT(*) AS num_frames
445    FROM
446      chrome_frame_info_with_delay
447    GROUP BY scroll_id
448  ),
449  janky_frames AS (
450    SELECT scroll_id, COUNT(*) AS num_janky_frames
451    FROM
452      chrome_janky_frames
453    GROUP BY scroll_id
454  )
455SELECT
456  frames.scroll_id AS scroll_id,
457  frames.num_frames AS num_frames,
458  janky_frames.num_janky_frames AS num_janky_frames,
459  100.0 * janky_frames.num_janky_frames / frames.num_frames
460    AS scroll_jank_percentage
461FROM frames
462LEFT JOIN janky_frames
463  ON frames.scroll_id = janky_frames.scroll_id;
464
465-- Scroll jank causes per scroll.
466CREATE PERFETTO VIEW chrome_causes_per_scroll(
467  -- The ID of the scroll.
468  scroll_id INT,
469  -- The maximum time a frame was delayed after the presentation of the previous
470  -- frame.
471  max_delay_since_last_frame INT,
472  -- The expected vsync interval.
473  vsync_interval INT,
474  -- A proto amalgamation of each scroll jank cause including cause name, sub
475  -- cause and the duration of the delay since the previous frame was presented.
476  scroll_jank_causes BYTES
477) AS
478SELECT
479  scroll_id,
480  MAX(1.0 * delay_since_last_frame / vsync_interval)
481    AS max_delay_since_last_frame,
482  -- MAX does not matter, since `vsync_interval` is the computed as the
483  -- same value for a single trace.
484  MAX(vsync_interval) AS vsync_interval,
485  RepeatedField(
486    ChromeScrollJankV3_Scroll_ScrollJankCause(
487      'cause',
488      cause_of_jank,
489      'sub_cause',
490      sub_cause_of_jank,
491      'delay_since_last_frame',
492      1.0 * delay_since_last_frame / vsync_interval))
493    AS scroll_jank_causes
494FROM
495  chrome_janky_frames
496GROUP BY scroll_id;