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;