1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
|
-- Copyright 2024 The Chromium Authors
-- Use of this source code is governed by a BSD-style license that can be
-- found in the LICENSE file.
-- Finds the start timestamp for a given slice's descendant with a given name.
-- If there are multiple descendants with a given name, the function will return
-- the first one, so it's most useful when working with a timeline broken down
-- into phases, where each subphase can happen only once.
CREATE PERFETTO FUNCTION _descendant_slice_begin(
-- Id of the parent slice.
parent_id LONG,
-- Name of the child with the desired start TS.
child_name STRING
)
-- Start timestamp of the child or NULL if it doesn't exist.
RETURNS LONG AS
SELECT
s.ts
FROM descendant_slice($parent_id) AS s
WHERE
s.name GLOB $child_name
LIMIT 1;
-- Finds the end timestamp for a given slice's descendant with a given name.
-- If there are multiple descendants with a given name, the function will return
-- the first one, so it's most useful when working with a timeline broken down
-- into phases, where each subphase can happen only once.
CREATE PERFETTO FUNCTION _descendant_slice_end(
-- Id of the parent slice.
parent_id LONG,
-- Name of the child with the desired end TS.
child_name STRING
)
-- End timestamp of the child or NULL if it doesn't exist.
RETURNS LONG AS
SELECT
CASE WHEN NOT s.dur IS -1 THEN s.ts + s.dur ELSE NULL END
FROM descendant_slice($parent_id) AS s
WHERE
s.name GLOB $child_name
LIMIT 1;
-- Checks if slice has a descendant with provided name.
CREATE PERFETTO FUNCTION _has_descendant_slice_with_name(
-- Id of the slice to check descendants of.
id LONG,
-- Name of potential descendant slice.
descendant_name STRING
)
-- Whether `descendant_name` is a name of an descendant slice.
RETURNS BOOL AS
SELECT
EXISTS(
SELECT
1
FROM descendant_slice($id)
WHERE
name = $descendant_name
LIMIT 1
);
-- Returns the presentation timestamp for a given EventLatency slice.
-- This is either the end of
-- SwapEndToPresentationCompositorFrame (if it exists),
-- the end of LatchToPresentation (if it exists),
-- the end of SwapStartToPresentation (if it exists),
-- or the end of LatchToSwapEnd (workaround in older Chrome versions).
CREATE PERFETTO FUNCTION _get_presentation_timestamp(
-- The slice id which we need the presentation timestamp for.
id LONG
)
RETURNS LONG AS
SELECT
coalesce(
_descendant_slice_end(id, 'SwapEndToPresentationCompositorFrame'),
_descendant_slice_end(id, '*ToPresentation'),
_descendant_slice_end(id, 'LatchToSwapEnd')
)
FROM slice
WHERE
$id = id;
-- All EventLatency slices.
CREATE PERFETTO TABLE chrome_event_latencies (
-- Slice Id for the EventLatency scroll event.
id LONG,
-- Slice name.
name STRING,
-- The start timestamp of the scroll.
ts TIMESTAMP,
-- The duration of the scroll.
dur DURATION,
-- The id of the scroll update event (aka LatencyInfo.ID).
scroll_update_id LONG,
-- The id of the first frame (pre-surface aggregation) which included the
-- scroll update and was presented. NULL if:
-- (1) the event is not a scroll update (`event_type` is NOT
-- GESTURE_SCROLL_UPDATE, FIRST_GESTURE_SCROLL_UPDATE, or
-- INERTIAL_GESTURE_SCROLL_UPDATE),
-- (2) the scroll update wasn't presented (e.g. it was an overscroll) or
-- (3) the trace comes from an old Chrome version (https://crrev.com/c/6185817
-- was first included in version 134.0.6977.0 and was cherry-picked in
-- version 133.0.6943.33).
surface_frame_trace_id LONG,
-- The id of the first frame (post-surface aggregation) which included the
-- scroll update and was presented. NULL if:
-- (1) the event is not a scroll update (`event_type` is NOT
-- GESTURE_SCROLL_UPDATE, FIRST_GESTURE_SCROLL_UPDATE, or
-- INERTIAL_GESTURE_SCROLL_UPDATE),
-- (2) the scroll update wasn't presented (e.g. it was an overscroll) or
-- (3) the trace comes from an old Chrome version (https://crrev.com/c/6185817
-- was first included in version 134.0.6977.0 and was cherry-picked in
-- version 133.0.6943.33).
display_trace_id LONG,
-- Whether this input event was presented.
is_presented BOOL,
-- EventLatency event type.
event_type STRING,
-- Perfetto track this slice is found on.
track_id LONG,
-- Vsync interval (in milliseconds).
vsync_interval_ms DOUBLE,
-- Whether the corresponding frame is janky based on the
-- Event.ScrollJank.DelayedFramesPercentage.FixedWindow metric.
is_janky_scrolled_frame BOOL,
-- Whether the corresponding frame is janky based on the
-- Event.ScrollJank.DelayedFramesPercentage.FixedWindow3 metric.
is_janky_scrolled_frame_v3 BOOL,
-- Timestamp of the BufferAvailableToBufferReady substage.
buffer_available_timestamp LONG,
-- Timestamp of the BufferReadyToLatch substage.
buffer_ready_timestamp LONG,
-- Timestamp of the LatchToSwapEnd substage (or LatchToPresentation as a
-- fallback).
latch_timestamp LONG,
-- Timestamp of the SwapEndToPresentationCompositorFrame substage.
swap_end_timestamp LONG,
-- Frame presentation timestamp aka the timestamp of the
-- SwapEndToPresentationCompositorFrame substage.
-- TODO(b/341047059): temporarily use LatchToSwapEnd as a workaround if
-- SwapEndToPresentationCompositorFrame is missing due to b/247542163.
presentation_timestamp LONG
) AS
SELECT
slice.id,
slice.name,
slice.ts,
slice.dur,
extract_arg(arg_set_id, 'event_latency.event_latency_id') AS scroll_update_id,
extract_arg(arg_set_id, 'event_latency.surface_frame_trace_id') AS surface_frame_trace_id,
extract_arg(arg_set_id, 'event_latency.display_trace_id') AS display_trace_id,
_has_descendant_slice_with_name(slice.id, 'SubmitCompositorFrameToPresentationCompositorFrame') AS is_presented,
extract_arg(arg_set_id, 'event_latency.event_type') AS event_type,
slice.track_id,
extract_arg(arg_set_id, 'event_latency.vsync_interval_ms') AS vsync_interval_ms,
coalesce(extract_arg(arg_set_id, 'event_latency.is_janky_scrolled_frame'), 0) AS is_janky_scrolled_frame,
coalesce(extract_arg(arg_set_id, 'event_latency.is_janky_scrolled_frame_v3'), 0) AS is_janky_scrolled_frame_v3,
_descendant_slice_begin(slice.id, 'BufferAvailableToBufferReady') AS buffer_available_timestamp,
_descendant_slice_begin(slice.id, 'BufferReadyToLatch') AS buffer_ready_timestamp,
coalesce(
_descendant_slice_begin(slice.id, 'LatchToSwapEnd'),
_descendant_slice_begin(slice.id, 'LatchToPresentation')
) AS latch_timestamp,
_descendant_slice_begin(slice.id, 'SwapEndToPresentationCompositorFrame') AS swap_end_timestamp,
_get_presentation_timestamp(slice.id) AS presentation_timestamp
FROM slice
WHERE
name = 'EventLatency';
-- All scroll-related events (frames) including gesture scroll updates, begins
-- and ends with respective scroll ids and start/end timestamps, regardless of
-- being presented. This includes pinches that were presented. See b/315761896
-- for context on pinches.
CREATE PERFETTO TABLE chrome_gesture_scroll_updates (
-- Slice Id for the EventLatency scroll event.
id LONG,
-- Slice name.
name STRING,
-- The start timestamp of the scroll.
ts TIMESTAMP,
-- The duration of the scroll.
dur DURATION,
-- The id of the scroll update event.
scroll_update_id LONG,
-- Whether this input event was presented.
is_presented BOOL,
-- EventLatency event type.
event_type STRING,
-- Perfetto track this slice is found on.
track_id LONG,
-- Vsync interval (in milliseconds).
vsync_interval_ms DOUBLE,
-- Whether the corresponding frame is janky based on the
-- Event.ScrollJank.DelayedFramesPercentage.FixedWindow metric.
is_janky BOOL,
-- Whether the corresponding frame is janky based on the
-- Event.ScrollJank.DelayedFramesPercentage.FixedWindow3 metric.
is_janky_v3 BOOL,
-- Timestamp of the BufferAvailableToBufferReady substage.
buffer_available_timestamp LONG,
-- Timestamp of the BufferReadyToLatch substage.
buffer_ready_timestamp LONG,
-- Timestamp of the LatchToSwapEnd substage (or LatchToPresentation as a
-- fallback).
latch_timestamp LONG,
-- Timestamp of the SwapEndToPresentationCompositorFrame substage.
swap_end_timestamp LONG,
-- Frame presentation timestamp aka the timestamp of the
-- SwapEndToPresentationCompositorFrame substage.
-- TODO(b/341047059): temporarily use LatchToSwapEnd as a workaround if
-- SwapEndToPresentationCompositorFrame is missing due to b/247542163.
presentation_timestamp LONG,
-- The id of the scroll.
scroll_id LONG
) AS
-- To compute scroll id, we first mark all of the FIRST_GESTURE_SCROLL_UPDATE events
-- (or the first scroll update in the trace) as the points where scroll id should be
-- incremented and then use the cumulative sum as the scroll id.
WITH
updates_without_scroll_ids AS (
SELECT
id,
name,
ts,
dur,
scroll_update_id,
is_presented,
event_type,
track_id,
vsync_interval_ms,
is_janky_scrolled_frame AS is_janky,
is_janky_scrolled_frame_v3 AS is_janky_v3,
buffer_available_timestamp,
buffer_ready_timestamp,
latch_timestamp,
swap_end_timestamp,
presentation_timestamp,
(
event_type = 'FIRST_GESTURE_SCROLL_UPDATE' OR row_number() OVER (ORDER BY ts) = 1
) AS is_first_update_in_scroll
FROM chrome_event_latencies
WHERE
event_type IN ('GESTURE_SCROLL_UPDATE', 'FIRST_GESTURE_SCROLL_UPDATE', 'INERTIAL_GESTURE_SCROLL_UPDATE')
OR (
-- Pinches are only relevant if the frame was presented.
event_type GLOB '*GESTURE_PINCH_UPDATE'
AND is_presented
)
)
SELECT
id,
name,
ts,
dur,
scroll_update_id,
is_presented,
event_type,
track_id,
vsync_interval_ms,
is_janky,
is_janky_v3,
buffer_available_timestamp,
buffer_ready_timestamp,
latch_timestamp,
swap_end_timestamp,
presentation_timestamp,
coalesce(
sum(cast_int!(is_first_update_in_scroll)) OVER (ORDER BY ts ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),
0
) AS scroll_id
FROM updates_without_scroll_ids;
|