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 chrome.chrome_scrolls; 6INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_v3; 7INCLUDE PERFETTO MODULE common.slices; 8 9-- Selects EventLatency slices that correspond with janks in a scroll. This is 10-- based on the V3 version of scroll jank metrics. 11CREATE PERFETTO TABLE chrome_janky_event_latencies_v3( 12 -- The slice id. 13 id INT, 14 -- The start timestamp of the slice. 15 ts INT, 16 -- The duration of the slice. 17 dur INT, 18 -- The track_id for the slice. 19 track_id INT, 20 -- The name of the slice (EventLatency). 21 name STRING, 22 -- The stage of EventLatency that the caused the jank. 23 cause_of_jank STRING, 24 -- The stage of cause_of_jank that caused the jank. 25 sub_cause_of_jank STRING, 26 -- How many vsyncs this frame missed its deadline by. 27 delayed_frame_count INT, 28 -- The start timestamp where frame presentation was delayed. 29 frame_jank_ts INT, 30 -- The duration in ms of the delay in frame presentation. 31 frame_jank_dur INT 32) AS 33SELECT 34 s.id, 35 s.ts, 36 s.dur, 37 s.track_id, 38 s.name, 39 e.cause_of_jank, 40 e.sub_cause_of_jank, 41 CAST((e.delay_since_last_frame/e.vsync_interval) - 1 AS INT) AS delayed_frame_count, 42 CAST(s.ts + s.dur - ((e.delay_since_last_frame - e.vsync_interval) * 1e6) AS INT) AS frame_jank_ts, 43 CAST((e.delay_since_last_frame - e.vsync_interval) * 1e6 AS INT) AS frame_jank_dur 44FROM slice s 45JOIN chrome_janky_frames e 46 ON s.id = e. event_latency_id; 47 48-- Frame presentation interval is the delta between when the frame was supposed 49-- to be presented and when it was actually presented. 50CREATE PERFETTO VIEW chrome_janky_frame_presentation_intervals( 51 -- Unique id. 52 id INT, 53 -- The start timestamp of the slice. 54 ts INT, 55 -- The duration of the slice. 56 dur INT, 57 -- How many vsyncs this frame missed its deadline by. 58 delayed_frame_count INT, 59 -- The stage of EventLatency that the caused the jank. 60 cause_of_jank INT, 61 -- The stage of cause_of_jank that caused the jank. 62 sub_cause_of_jank INT, 63 -- The id of the associated event latency in the slice table. 64 event_latency_id INT 65) AS 66SELECT 67 ROW_NUMBER() OVER(ORDER BY frame_jank_ts) AS id, 68 frame_jank_ts AS ts, 69 frame_jank_dur AS dur, 70 delayed_frame_count, 71 cause_of_jank, 72 sub_cause_of_jank, 73 id AS event_latency_id 74FROM chrome_janky_event_latencies_v3; 75 76-- Scroll jank frame presentation stats for individual scrolls. 77CREATE PERFETTO VIEW chrome_scroll_stats( 78 -- Id of the individual scroll. 79 scroll_id INT, 80 -- The number of frames in the scroll. 81 frame_count INT, 82 -- The number of missed vsyncs in the scroll. 83 missed_vsyncs INT, 84 -- The number presented frames in the scroll. 85 presented_frame_count INT, 86 -- The number of janky frames in the scroll. 87 janky_frame_count INT, 88 -- The % of frames that janked in the scroll. 89 janky_frame_percent FLOAT 90) AS 91WITH vsyncs AS ( 92 SELECT 93 COUNT() AS presented_vsync_count, 94 scroll.id AS scroll_id 95 FROM chrome_unique_frame_presentation_ts frame 96 JOIN chrome_scrolls scroll 97 ON frame.presentation_timestamp >= scroll.ts 98 AND frame.presentation_timestamp <= scroll.ts + scroll.dur 99 GROUP BY scroll_id), 100missed_vsyncs AS ( 101 SELECT 102 CAST(SUM((delay_since_last_frame / vsync_interval) - 1) AS INT) AS total_missed_vsyncs, 103 scroll_id 104 FROM chrome_janky_frames 105 GROUP BY scroll_id), 106frame_stats AS ( 107 SELECT 108 scroll_id, 109 num_frames AS presented_frame_count, 110 IFNULL(num_janky_frames, 0) AS janky_frame_count, 111 ROUND(IFNULL(scroll_jank_percentage, 0), 2) AS janky_frame_percent 112 FROM chrome_frames_per_scroll 113) 114SELECT 115 vsyncs.scroll_id, 116 presented_vsync_count + IFNULL(total_missed_vsyncs, 0) AS frame_count, 117 total_missed_vsyncs AS missed_vsyncs, 118 presented_frame_count, 119 janky_frame_count, 120 janky_frame_percent 121FROM vsyncs 122LEFT JOIN missed_vsyncs 123 USING (scroll_id) 124LEFT JOIN frame_stats 125 USING (scroll_id); 126 127-- Defines slices for all of janky scrolling intervals in a trace. 128CREATE PERFETTO TABLE chrome_scroll_jank_intervals_v3( 129 -- The unique identifier of the janky interval. 130 id INT, 131 -- The start timestamp of the janky interval. 132 ts INT, 133 -- The duration of the janky interval. 134 dur INT 135) AS 136-- Sub-table to retrieve all janky slice timestamps. Ordering calculations are 137-- based on timestamps rather than durations. 138WITH janky_latencies AS ( 139 SELECT 140 s.frame_jank_ts AS start_ts, 141 s.frame_jank_ts + s.frame_jank_dur AS end_ts 142 FROM chrome_janky_event_latencies_v3 s), 143-- Determine the local maximum timestamp for janks thus far; this will allow 144-- us to coalesce all earlier events up to the maximum. 145ordered_jank_end_ts AS ( 146 SELECT 147 *, 148 MAX(end_ts) OVER ( 149 ORDER BY start_ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 150 AS max_end_ts_so_far 151 FROM janky_latencies), 152-- Determine the local minimum timestamp for janks thus far; this will allow 153-- us to coalesce all later events up to the nearest local maximum. 154range_starts AS ( 155 SELECT 156 *, 157 CASE 158 -- This is a two-pass calculation to calculate the first event in the 159 -- group. An event is considered the first event in a group if all events 160 -- which started before it also finished the current one started. 161 WHEN start_ts <= 1 + LAG(max_end_ts_so_far) OVER (ORDER BY start_ts) THEN 0 162 ELSE 1 163 END AS range_start 164 FROM ordered_jank_end_ts), 165-- Assign an id to allow coalescing of individual slices. 166range_groups AS ( 167 SELECT 168 *, 169 SUM(range_start) OVER (ORDER BY start_ts) AS range_group 170 FROM range_starts) 171-- Coalesce all slices within an interval. 172SELECT 173 range_group AS id, 174 MIN(start_ts) AS ts, 175 MAX(end_ts) - MIN(start_ts) AS dur 176FROM range_groups 177GROUP BY range_group; 178