| -- Copyright 2026 The Chromium Authors |
| -- Use of this source code is governed by a BSD-style license that can be |
| -- found in the LICENSE file. |
| |
| INCLUDE PERFETTO MODULE chrome.chrome_scrolls; |
| |
| INCLUDE PERFETTO MODULE chrome.scroll_jank_v4; |
| |
| -- A helper macro which evaluates to `expression` if the first scroll update in |
| -- a frame is real. Otherwise, evaluates to NULL. Should be only used in |
| -- `chrome_scroll_frame_info_v4`. |
| CREATE PERFETTO MACRO _if_real_first_scroll_update( |
| expression Expr |
| ) |
| RETURNS Expr AS |
| iif(results.first_scroll_update_type = 'REAL', $expression, NULL); |
| |
| -- A helper macro which evaluates to `expression` if a frame is damaging. |
| -- Otherwise, evaluates to NULL. Should be only used in |
| -- `chrome_scroll_frame_info_v4`. |
| CREATE PERFETTO MACRO _if_damaging_frame( |
| expression Expr |
| ) |
| RETURNS Expr AS |
| iif(results.damage_type = 'DAMAGING', $expression, NULL); |
| |
| -- Helper macro to compute the delta between the duration of this frame's and |
| -- previous frame's `stage`. Should be only used in |
| -- `chrome_scroll_frame_info_v4`. |
| CREATE PERFETTO MACRO _stage_dur_delta_v4( |
| stage ColumnName |
| ) |
| RETURNS Expr AS |
| $stage - lag($stage) OVER (PARTITION BY info.scroll_id ORDER BY results.ts); |
| |
| -- A list of all presented Chrome frames which contain scroll updates together |
| -- with additional metadata, pipeline stages breakdown and jank classification |
| -- according to the scroll model of Chrome's scroll jank v4 metric. |
| CREATE PERFETTO TABLE chrome_scroll_frame_info_v4 ( |
| -- Slice ID of the 'ScrollJankV4' slice, which represents a frame presented by |
| -- Chrome that contains at least one scroll update. Can be joined with |
| -- `chrome_scroll_jank_v4_results.id`. |
| id JOINID(slice.id), |
| -- Id of the `LatencyInfo.Flow` slices corresponding to the first scroll |
| -- update in this frame. Can be joined with |
| -- `chrome_gesture_scroll_updates.id`, `chrome_scroll_update_info.id`, |
| -- `chrome_scroll_update_refs.scroll_update_latency_id` and many other tables. |
| scroll_update_latency_id LONG, |
| -- Id of the scroll this frame belongs to. Can be joined with |
| -- `chrome_event_latency.scroll_id`. |
| scroll_id LONG, |
| -- The VSync interval that this frame was produced for according to the |
| -- BeginFrameArgs. |
| vsync_interval_dur DURATION, |
| -- Whether this frame is janky based on the |
| -- `Event.ScrollJank.DelayedFramesPercentage4.FixedWindow` metric. |
| is_janky BOOL, |
| -- Whether the corresponding scroll is inertial (fling). |
| is_inertial BOOL, |
| -- The position of the frame in a scroll (starting from 1). |
| frame_index_in_scroll LONG, |
| -- The absolute total raw (unpredicted) delta of all real scroll updates |
| -- included in this frame (in pixels). NULL if the first scroll update in this |
| -- frame is synthetic. |
| real_abs_total_raw_delta_pixels DOUBLE, |
| -- Duration from the start of the browser process to the input generation |
| -- timestamp of the first scroll update in this frame. NULL if the first |
| -- scroll update in this frame is synthetic. |
| browser_uptime_dur DURATION, |
| -- Input generation timestamp (from the Android system) for the first scroll |
| -- update in this frame. NULL if the first scroll update in this frame is |
| -- synthetic. |
| first_input_generation_ts TIMESTAMP, |
| -- Duration from the generation timestamp to the end of InputReader's work. |
| -- Only populated when atrace 'input' category is enabled. NULL if the first |
| -- scroll update is synthetic. |
| input_reader_dur DURATION, |
| -- Duration of InputDispatcher's work. Only populated when atrace 'input' |
| -- category is enabled. NULL if the first scroll update in this frame is |
| -- synthetic. |
| input_dispatcher_dur DURATION, |
| -- Duration from the previous input (last input that wasn't part of this |
| -- frame) to the first input in this frame. |
| previous_last_input_to_first_input_generation_dur DURATION, |
| -- Utid for the browser main thread, on which Chrome received the first scroll |
| -- update in this frame. NULL if the first scroll update in this frame is |
| -- synthetic. |
| browser_utid JOINID(thread.id), |
| -- Duration from input generation to when the browser received the first |
| -- scroll update in this frame. NULL if the first scroll update in this frame |
| -- is synthetic. |
| first_input_generation_to_browser_main_dur DURATION, |
| -- Difference between `first_input_generation_to_browser_main_dur` for this |
| -- frame and the previous frame in the same scroll. NULL if the first scroll |
| -- update in either frame is synthetic. |
| first_input_generation_to_browser_main_delta_dur DURATION, |
| -- Slice id for the `STEP_SEND_INPUT_EVENT_UI` slice for the `TouchMove` event |
| -- associated with the first scroll update in this frame. NULL if the first |
| -- scroll update in this frame is synthetic. |
| first_input_touch_move_received_slice_id JOINID(slice.id), |
| -- Timestamp for the `STEP_SEND_INPUT_EVENT_UI` slice for the `TouchMove` |
| -- event associated with the first scroll update in this frame. NULL if the |
| -- first scroll update in this frame is synthetic. |
| first_input_touch_move_received_ts TIMESTAMP, |
| -- Duration for processing the `TouchMove` event associated with the first |
| -- scroll update in this frame. NULL if the first scroll update in this frame |
| -- is synthetic. |
| first_input_touch_move_processing_dur DURATION, |
| -- Difference between `first_input_touch_move_processing_dur` for this frame |
| -- and the previous frame in the same scroll. NULL if the first scroll update |
| -- in either frame is synthetic. |
| first_input_touch_move_processing_delta_dur DURATION, |
| -- Slice id for the `STEP_SEND_INPUT_EVENT_UI` slice which created the |
| -- `GestureScrollUpdate` event from the `TouchMove` event for the first scroll |
| -- update in this frame. NULL if the first scroll update in this frame is |
| -- synthetic. |
| first_input_scroll_update_created_slice_id JOINID(slice.id), |
| -- Timestamp for the `STEP_SEND_INPUT_EVENT_UI` slice which created the |
| -- `GestureScrollUpdate` event from the `TouchMove` event for the first scroll |
| -- update in this frame. NULL if the first scroll update in this frame is |
| -- synthetic. |
| first_input_scroll_update_created_ts TIMESTAMP, |
| -- Duration for creating the `GestureScrollUpdate` event from the `TouchMove` |
| -- event for the first scroll update in this frame. NULL if the first scroll |
| -- update in this frame is synthetic. |
| first_input_scroll_update_processing_dur DURATION, |
| -- Difference between `first_input_scroll_update_processing_dur` for this |
| -- frame and the previous frame in the same scroll. NULL if the first scroll |
| -- update in either frame is synthetic. |
| first_input_scroll_update_processing_delta_dur DURATION, |
| -- End timestamp for the `STEP_SEND_INPUT_EVENT_UI` slice which created the |
| -- `GestureScrollUpdate` event from the `TouchMove` event for the first scroll |
| -- update in this frame. NULL if the first scroll update in this frame is |
| -- synthetic. |
| first_input_scroll_update_created_end_ts TIMESTAMP, |
| -- Duration between the browser and compositor dispatch for the first scroll |
| -- update in this frame. NULL if the first scroll update in this frame is |
| -- synthetic. |
| first_input_browser_to_compositor_delay_dur DURATION, |
| -- Difference between `first_input_browser_to_compositor_delay_dur` for this |
| -- frame and the previous frame in the same scroll. NULL if either scroll |
| -- update in this frame is synthetic. |
| first_input_browser_to_compositor_delay_delta_dur DURATION, |
| -- Utid for the renderer compositor thread. |
| compositor_utid JOINID(thread.id), |
| -- Slice id for the `STEP_HANDLE_INPUT_EVENT_IMPL` slice associated with the |
| -- first scroll update in this frame. |
| first_input_compositor_dispatch_slice_id JOINID(slice.id), |
| -- Timestamp for the `STEP_HANDLE_INPUT_EVENT_IMPL` slice associated with the |
| -- first scroll update in this frame or the containing task (if available). |
| first_input_compositor_dispatch_ts TIMESTAMP, |
| -- Duration for the compositor dispatch for the first scroll update in this |
| -- frame. |
| first_input_compositor_dispatch_dur DURATION, |
| -- Difference between `first_input_compositor_dispatch_dur` for this frame and |
| -- the previous frame in the same scroll. |
| first_input_compositor_dispatch_delta_dur DURATION, |
| -- End timestamp for the `STEP_HANDLE_INPUT_EVENT_IMPL` slice associated with |
| -- the first scroll update in this frame. |
| first_input_compositor_dispatch_end_ts TIMESTAMP, |
| -- Duration between the compositor dispatch and the "OnBeginFrame" work for |
| -- the first input in this frame. NULL if this frame is non-damaging. |
| first_input_compositor_dispatch_to_on_begin_frame_delay_dur DURATION, |
| -- Difference between |
| -- `first_input_compositor_dispatch_to_on_begin_frame_delay_dur` for this |
| -- frame and the previous frame in the same scroll. NULL if either frame is |
| -- non-damaging. |
| first_input_compositor_dispatch_to_on_begin_frame_delay_delta_dur DURATION, |
| -- Slice id for the `STEP_RESAMPLE_SCROLL_EVENTS` slice. NULL if this frame is |
| -- non-damaging. |
| compositor_resample_slice_id JOINID(slice.id), |
| -- Slice id for the `STEP_DID_HANDLE_INPUT_AND_OVERSCROLL` slice. NULL if this |
| -- frame is non-damaging. |
| compositor_coalesced_input_handled_slice_id JOINID(slice.id), |
| -- Start timestamp for work done on the input during "OnBeginFrame". NULL if |
| -- this frame is non-damaging. |
| compositor_on_begin_frame_ts TIMESTAMP, |
| -- Duration of the "OnBeginFrame" work for this frame. NULL if this frame is |
| -- non-damaging. |
| compositor_on_begin_frame_dur DURATION, |
| -- Difference between `compositor_on_begin_frame_dur` for this frame and the |
| -- previous frame in the same scroll. NULL if either frame is non-damaging. |
| compositor_on_begin_frame_delta_dur DURATION, |
| -- End timestamp for work done on the input during "OnBeginFrame". NULL if |
| -- this frame is non-damaging. |
| compositor_on_begin_frame_end_ts TIMESTAMP, |
| -- Duration between the "OnBeginFrame" work and the generation of this frame. |
| -- NULL if this frame is non-damaging. |
| compositor_on_begin_frame_to_generation_delay_dur DURATION, |
| -- Difference between `compositor_on_begin_frame_to_generation_delay_dur` for |
| -- this frame and the previous frame in the same scroll. NULL if either frame |
| -- is non-damaging. |
| compositor_on_begin_frame_to_generation_delay_delta_dur DURATION, |
| -- Slice id for the `STEP_GENERATE_COMPOSITOR_FRAME` slice. NULL if this frame |
| -- is non-damaging. |
| compositor_generate_compositor_frame_slice_id JOINID(slice.id), |
| -- Timestamp for the `STEP_GENERATE_COMPOSITOR_FRAME` slice or the containing |
| -- task (if available). NULL if this frame is non-damaging. |
| compositor_generate_compositor_frame_ts TIMESTAMP, |
| -- Duration between the generation and submission of this frame. NULL if this |
| -- frame is non-damaging. |
| compositor_generate_frame_to_submit_frame_dur DURATION, |
| -- Difference between `compositor_generate_frame_to_submit_frame_dur` for this |
| -- frame and the previous frame in the same scroll. NULL if either frame is |
| -- non-damaging. |
| compositor_generate_frame_to_submit_frame_delta_dur DURATION, |
| -- Slice id for the `STEP_SUBMIT_COMPOSITOR_FRAME` slice. NULL if this frame |
| -- is non-damaging. |
| compositor_submit_compositor_frame_slice_id JOINID(slice.id), |
| -- Timestamp for the `STEP_SUBMIT_COMPOSITOR_FRAME` slice. NULL if this frame |
| -- is non-damaging. |
| compositor_submit_compositor_frame_ts TIMESTAMP, |
| -- Duration for submitting this frame. NULL if this frame is non-damaging. |
| compositor_submit_frame_dur DURATION, |
| -- Difference between `compositor_submit_frame_dur` for this frame and the |
| -- previous frame in the same scroll. NULL if either frame is non-damaging. |
| compositor_submit_frame_delta_dur DURATION, |
| -- End timestamp for the `STEP_SUBMIT_COMPOSITOR_FRAME` slice. NULL if this |
| -- frame is non-damaging. |
| compositor_submit_compositor_frame_end_ts TIMESTAMP, |
| -- Utid for the viz compositor thread. NULL if this frame is non-damaging. |
| viz_compositor_utid JOINID(thread.id), |
| -- Delay when a compositor frame is sent from the renderer to viz. NULL if |
| -- this frame is non-damaging. |
| compositor_to_viz_delay_dur DURATION, |
| -- Difference between `compositor_to_viz_delay_dur` for this frame and the |
| -- previous frame in the same scroll. NULL if either frame is non-damaging. |
| compositor_to_viz_delay_delta_dur DURATION, |
| -- Slice id for the `STEP_RECEIVE_COMPOSITOR_FRAME` slice. NULL if this frame |
| -- is non-damaging. |
| viz_receive_compositor_frame_slice_id JOINID(slice.id), |
| -- Timestamp for the `STEP_RECEIVE_COMPOSITOR_FRAME` slice or the containing |
| -- task (if available). NULL if this frame is non-damaging. |
| viz_receive_compositor_frame_ts TIMESTAMP, |
| -- Duration of the viz work done on receiving the compositor frame. NULL if |
| -- this frame is non-damaging. |
| viz_receive_compositor_frame_dur DURATION, |
| -- Difference between `viz_receive_compositor_frame_dur` for this frame and |
| -- the previous frame in the same scroll. NULL if either frame is |
| -- non-damaging. |
| viz_receive_compositor_frame_delta_dur DURATION, |
| -- End timestamp for the `STEP_RECEIVE_COMPOSITOR_FRAME` slice. NULL if this |
| -- frame is non-damaging. |
| viz_receive_compositor_frame_end_ts TIMESTAMP, |
| -- Duration between viz receiving the compositor frame to frame draw. NULL if |
| -- this frame is non-damaging. |
| viz_wait_for_draw_dur DURATION, |
| -- Difference between `viz_wait_for_draw_dur` for this frame and the previous |
| -- frame in the same scroll. NULL if either frame is non-damaging. |
| viz_wait_for_draw_delta_dur DURATION, |
| -- Slice id for the `STEP_DRAW_AND_SWAP` slice. NULL if this frame is |
| -- non-damaging. |
| viz_draw_and_swap_slice_id JOINID(slice.id), |
| -- Timestamp for the `STEP_DRAW_AND_SWAP` slice or the containing task (if |
| -- available). NULL if this frame is non-damaging. |
| viz_draw_and_swap_ts TIMESTAMP, |
| -- Duration of the viz drawing/swapping work for this frame. NULL if this |
| -- frame is non-damaging. |
| viz_draw_and_swap_dur DURATION, |
| -- Difference between `viz_draw_and_swap_dur` for this frame and the previous |
| -- frame in the same scroll. NULL if either frame is non-damaging. |
| viz_draw_and_swap_delta_dur DURATION, |
| -- Slice id for the `STEP_SEND_BUFFER_SWAP` slice. NULL if this frame is |
| -- non-damaging. |
| viz_send_buffer_swap_slice_id JOINID(slice.id), |
| -- End timestamp for the `STEP_SEND_BUFFER_SWAP` slice. NULL if this frame is |
| -- non-damaging. |
| viz_send_buffer_swap_end_ts TIMESTAMP, |
| -- Utid for the viz `CompositorGpuThread`. NULL if this frame is non-damaging. |
| viz_gpu_thread_utid JOINID(thread.id), |
| -- Delay between viz work on compositor thread and `CompositorGpuThread`. NULL |
| -- if this frame is non-damaging. |
| viz_to_gpu_delay_dur DURATION, |
| -- Difference between `viz_to_gpu_delay_dur` for this frame and the previous |
| -- frame in the same scroll. NULL if either frame is non-damaging. |
| viz_to_gpu_delay_delta_dur DURATION, |
| -- Slice id for the `STEP_BUFFER_SWAP_POST_SUBMIT` slice. NULL if this frame |
| -- is non-damaging. |
| viz_swap_buffers_slice_id JOINID(slice.id), |
| -- Timestamp for the `STEP_BUFFER_SWAP_POST_SUBMIT` slice or the containing |
| -- task (if available). NULL if this frame is non-damaging. |
| viz_swap_buffers_ts TIMESTAMP, |
| -- Duration of frame buffer swapping work on viz. NULL if this frame is |
| -- non-damaging. |
| viz_swap_buffers_dur DURATION, |
| -- Difference between `viz_swap_buffers_dur` for this frame and the previous |
| -- frame in the same scroll. NULL if either frame is non-damaging. |
| viz_swap_buffers_delta_dur DURATION, |
| -- End timestamp for the `STEP_BUFFER_SWAP_POST_SUBMIT` slice. NULL if this |
| -- frame is non-damaging. |
| viz_swap_buffers_end_ts TIMESTAMP, |
| -- Time between buffers ready until Choreographer's latch. NULL if this frame |
| -- is non-damaging. |
| viz_swap_buffers_to_latch_dur DURATION, |
| -- Difference between `viz_swap_buffers_to_latch_dur` for this frame and the |
| -- previous frame in the same scroll. NULL if either frame is non-damaging. |
| viz_swap_buffers_to_latch_delta_dur DURATION, |
| -- Timestamp of `EventLatency`'s `BufferAvailableToBufferReady` step. NULL if |
| -- this frame is non-damaging. |
| buffer_available_timestamp TIMESTAMP, |
| -- Duration of `EventLatency`'s `BufferAvailableToBufferReady` step. NULL if |
| -- this frame is non-damaging. |
| buffer_available_to_ready_dur DURATION, |
| -- Difference between `buffer_available_to_ready_dur` for this frame and the |
| -- previous frame in the same scroll. NULL if either frame is non-damaging. |
| buffer_available_to_ready_delta_dur DURATION, |
| -- Timestamp for `EventLatency`'s `BufferReadyToLatch` step. NULL if this |
| -- frame is non-damaging. |
| buffer_ready_timestamp TIMESTAMP, |
| -- Timestamp for `EventLatency`'s `LatchToSwapEnd` step. NULL if this frame is |
| -- non-damaging. |
| latch_timestamp TIMESTAMP, |
| -- Duration between Choreographer's latch and presentation. NULL if this frame |
| -- is non-damaging. |
| viz_latch_to_presentation_dur DURATION, |
| -- Difference between `viz_latch_to_presentation_dur` for this frame and the |
| -- previous frame in the same scroll. NULL if either frame is non-damaging. |
| viz_latch_to_presentation_delta_dur DURATION, |
| -- Presentation timestamp for the frame. NULL if this frame is non-damaging. |
| presentation_ts TIMESTAMP |
| ) AS |
| SELECT |
| results.id, |
| results.first_event_latency_id AS scroll_update_latency_id, |
| info.scroll_id, |
| results.vsync_interval AS vsync_interval_dur, |
| results.is_janky, |
| NOT results.real_max_abs_inertial_raw_delta_pixels IS NULL AS is_inertial, |
| row_number() OVER (PARTITION BY info.scroll_id ORDER BY results.ts) AS frame_index_in_scroll, |
| -- Columns which are only relevant frames whose first scroll update is REAL. |
| _if_real_first_scroll_update!(results.real_abs_total_raw_delta_pixels) AS real_abs_total_raw_delta_pixels, |
| _if_real_first_scroll_update!(info.browser_uptime_dur) AS browser_uptime_dur, |
| _if_real_first_scroll_update!(info.generation_ts) AS first_input_generation_ts, |
| _if_real_first_scroll_update!(info.input_reader_dur) AS input_reader_dur, |
| _if_real_first_scroll_update!(info.input_dispatcher_dur) AS input_dispatcher_dur, |
| _if_real_first_scroll_update!(info.generation_ts - MAX(results.real_last_input_generation_ts) OVER (PARTITION BY info.scroll_id ORDER BY results.ts ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)) AS previous_last_input_to_first_input_generation_dur, |
| _if_real_first_scroll_update!(info.browser_utid) AS browser_utid, |
| _if_real_first_scroll_update!(info.generation_to_browser_main_dur) AS first_input_generation_to_browser_main_dur, |
| _if_real_first_scroll_update!(_stage_dur_delta_v4!(info.generation_to_browser_main_dur)) AS first_input_generation_to_browser_main_delta_dur, |
| _if_real_first_scroll_update!(info.touch_move_received_slice_id) AS first_input_touch_move_received_slice_id, |
| _if_real_first_scroll_update!(info.touch_move_received_ts) AS first_input_touch_move_received_ts, |
| _if_real_first_scroll_update!(info.touch_move_processing_dur) AS first_input_touch_move_processing_dur, |
| _if_real_first_scroll_update!(_stage_dur_delta_v4!(info.touch_move_processing_dur)) AS first_input_touch_move_processing_delta_dur, |
| _if_real_first_scroll_update!(info.scroll_update_created_slice_id) AS first_input_scroll_update_created_slice_id, |
| _if_real_first_scroll_update!(info.scroll_update_created_ts) AS first_input_scroll_update_created_ts, |
| _if_real_first_scroll_update!(info.scroll_update_processing_dur) AS first_input_scroll_update_processing_dur, |
| _if_real_first_scroll_update!(_stage_dur_delta_v4!(info.scroll_update_processing_dur)) AS first_input_scroll_update_processing_delta_dur, |
| _if_real_first_scroll_update!(info.scroll_update_created_end_ts) AS first_input_scroll_update_created_end_ts, |
| _if_real_first_scroll_update!(info.browser_to_compositor_delay_dur) AS first_input_browser_to_compositor_delay_dur, |
| _if_real_first_scroll_update!(_stage_dur_delta_v4!(info.browser_to_compositor_delay_dur)) AS first_input_browser_to_compositor_delay_delta_dur, |
| -- A few columns which are relevant to ALL scroll frames. |
| info.compositor_utid, |
| info.compositor_dispatch_slice_id AS first_input_compositor_dispatch_slice_id, |
| info.compositor_dispatch_ts AS first_input_compositor_dispatch_ts, |
| info.compositor_dispatch_dur AS first_input_compositor_dispatch_dur, |
| _stage_dur_delta_v4!(info.compositor_dispatch_dur) AS first_input_compositor_dispatch_delta_dur, |
| info.compositor_dispatch_end_ts AS first_input_compositor_dispatch_end_ts, |
| -- The remaining columns below are only relevant to DAMAGING frames. |
| _if_damaging_frame!(info.compositor_dispatch_to_on_begin_frame_delay_dur) AS first_input_compositor_dispatch_to_on_begin_frame_delay_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.compositor_dispatch_to_on_begin_frame_delay_dur)) AS first_input_compositor_dispatch_to_on_begin_frame_delay_delta_dur, |
| _if_damaging_frame!(info.compositor_resample_slice_id) AS compositor_resample_slice_id, |
| _if_damaging_frame!(info.compositor_coalesced_input_handled_slice_id) AS compositor_coalesced_input_handled_slice_id, |
| _if_damaging_frame!(info.compositor_on_begin_frame_ts) AS compositor_on_begin_frame_ts, |
| _if_damaging_frame!(info.compositor_on_begin_frame_dur) AS compositor_on_begin_frame_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.compositor_on_begin_frame_dur)) AS compositor_on_begin_frame_delta_dur, |
| _if_damaging_frame!(info.compositor_on_begin_frame_end_ts) AS compositor_on_begin_frame_end_ts, |
| _if_damaging_frame!(info.compositor_on_begin_frame_to_generation_delay_dur) AS compositor_on_begin_frame_to_generation_delay_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.compositor_on_begin_frame_to_generation_delay_dur)) AS compositor_on_begin_frame_to_generation_delay_delta_dur, |
| _if_damaging_frame!(info.compositor_generate_compositor_frame_slice_id) AS compositor_generate_compositor_frame_slice_id, |
| _if_damaging_frame!(info.compositor_generate_compositor_frame_ts) AS compositor_generate_compositor_frame_ts, |
| _if_damaging_frame!(info.compositor_generate_frame_to_submit_frame_dur) AS compositor_generate_frame_to_submit_frame_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.compositor_generate_frame_to_submit_frame_dur)) AS compositor_generate_frame_to_submit_frame_delta_dur, |
| _if_damaging_frame!(compositor_submit_compositor_frame_slice_id) AS compositor_submit_compositor_frame_slice_id, |
| _if_damaging_frame!(compositor_submit_compositor_frame_ts) AS compositor_submit_compositor_frame_ts, |
| _if_damaging_frame!(info.compositor_submit_frame_dur) AS compositor_submit_frame_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.compositor_submit_frame_dur)) AS compositor_submit_frame_delta_dur, |
| _if_damaging_frame!(info.compositor_submit_compositor_frame_end_ts) AS compositor_submit_compositor_frame_end_ts, |
| _if_damaging_frame!(info.viz_compositor_utid) AS viz_compositor_utid, |
| _if_damaging_frame!(info.compositor_to_viz_delay_dur) AS compositor_to_viz_delay_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.compositor_to_viz_delay_dur)) AS compositor_to_viz_delay_delta_dur, |
| _if_damaging_frame!(info.viz_receive_compositor_frame_slice_id) AS viz_receive_compositor_frame_slice_id, |
| _if_damaging_frame!(info.viz_receive_compositor_frame_ts) AS viz_receive_compositor_frame_ts, |
| _if_damaging_frame!(info.viz_receive_compositor_frame_dur) AS viz_receive_compositor_frame_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.viz_receive_compositor_frame_dur)) AS viz_receive_compositor_frame_delta_dur, |
| _if_damaging_frame!(info.viz_receive_compositor_frame_end_ts) AS viz_receive_compositor_frame_end_ts, |
| _if_damaging_frame!(info.viz_wait_for_draw_dur) AS viz_wait_for_draw_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.viz_wait_for_draw_dur)) AS viz_wait_for_draw_delta_dur, |
| _if_damaging_frame!(info.viz_draw_and_swap_slice_id) AS viz_draw_and_swap_slice_id, |
| _if_damaging_frame!(info.viz_draw_and_swap_ts) AS viz_draw_and_swap_ts, |
| _if_damaging_frame!(info.viz_draw_and_swap_dur) AS viz_draw_and_swap_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.viz_draw_and_swap_dur)) AS viz_draw_and_swap_delta_dur, |
| _if_damaging_frame!(info.viz_send_buffer_swap_slice_id) AS viz_send_buffer_swap_slice_id, |
| _if_damaging_frame!(info.viz_send_buffer_swap_end_ts) AS viz_send_buffer_swap_end_ts, |
| _if_damaging_frame!(info.viz_gpu_thread_utid) AS viz_gpu_thread_utid, |
| _if_damaging_frame!(info.viz_to_gpu_delay_dur) AS viz_to_gpu_delay_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.viz_to_gpu_delay_dur)) AS viz_to_gpu_delay_delta_dur, |
| _if_damaging_frame!(info.viz_swap_buffers_slice_id) AS viz_swap_buffers_slice_id, |
| _if_damaging_frame!(info.viz_swap_buffers_ts) AS viz_swap_buffers_ts, |
| _if_damaging_frame!(info.viz_swap_buffers_dur) AS viz_swap_buffers_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.viz_swap_buffers_dur)) AS viz_swap_buffers_delta_dur, |
| _if_damaging_frame!(info.viz_swap_buffers_end_ts) AS viz_swap_buffers_end_ts, |
| _if_damaging_frame!(info.viz_swap_buffers_to_latch_dur) AS viz_swap_buffers_to_latch_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.viz_swap_buffers_to_latch_dur)) AS viz_swap_buffers_to_latch_delta_dur, |
| _if_damaging_frame!(info.buffer_available_timestamp) AS buffer_available_timestamp, |
| _if_damaging_frame!(info.buffer_available_to_ready_dur) AS buffer_available_to_ready_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.buffer_available_to_ready_dur)) AS buffer_available_to_ready_delta_dur, |
| _if_damaging_frame!(info.buffer_ready_timestamp) AS buffer_ready_timestamp, |
| _if_damaging_frame!(info.latch_timestamp) AS latch_timestamp, |
| _if_damaging_frame!(info.viz_latch_to_presentation_dur) AS viz_latch_to_presentation_dur, |
| _if_damaging_frame!(_stage_dur_delta_v4!(info.viz_latch_to_presentation_dur)) AS viz_latch_to_presentation_delta_dur, |
| _if_damaging_frame!(info.presentation_timestamp) AS presentation_ts |
| FROM chrome_scroll_jank_v4_results AS results |
| LEFT JOIN chrome_scroll_update_info AS info |
| ON info.id = results.first_event_latency_id |
| ORDER BY |
| results.ts; |