blob: 33199abdfe894f9c18e68ac6f35d41c60eadf97b [file] [log] [blame]
-- Copyright 2023 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.event_latency;
INCLUDE PERFETTO MODULE chrome.graphics_pipeline;
INCLUDE PERFETTO MODULE chrome.input;
INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_offsets;
INCLUDE PERFETTO MODULE chrome.scroll_jank.utils;
-- Ties together input (`LatencyInfo.Flow`) and frame (`Graphics.Pipeline`)
-- trace events. Only covers input events of the `GESTURE_SCROLL_UPDATE_EVENT`
-- type.
CREATE PERFETTO TABLE chrome_scroll_update_refs (
-- Id of the Chrome input pipeline (`LatencyInfo.Flow`).
scroll_update_latency_id LONG,
-- Id of the touch move input corresponding to this scroll update.
touch_move_latency_id LONG,
-- Id of the `EventLatency` of the frame that the input was presented in.
presentation_latency_id LONG,
-- Id of the frame pipeline (`Graphics.Pipeline`), pre-surface aggregation.
surface_frame_id LONG,
-- Id of the frame pipeline (`Graphics.Pipeline`), post-surface aggregation.
display_trace_id LONG
) AS
SELECT
scroll_update.latency_id AS scroll_update_latency_id,
chrome_touch_move_to_scroll_update.touch_move_latency_id,
coalesce(chrome_coalesced_inputs.presented_latency_id, scroll_update.latency_id) AS presentation_latency_id,
chrome_graphics_pipeline_inputs_to_surface_frames.surface_frame_trace_id AS surface_frame_id,
chrome_surface_frame_id_to_first_display_id.display_trace_id
FROM chrome_inputs AS scroll_update
LEFT JOIN chrome_graphics_pipeline_inputs_to_surface_frames
USING (latency_id)
LEFT JOIN chrome_surface_frame_id_to_first_display_id
ON chrome_surface_frame_id_to_first_display_id.surface_frame_trace_id = chrome_graphics_pipeline_inputs_to_surface_frames.surface_frame_trace_id
LEFT JOIN chrome_touch_move_to_scroll_update
ON chrome_touch_move_to_scroll_update.scroll_update_latency_id = scroll_update.latency_id
LEFT JOIN chrome_coalesced_inputs
ON chrome_coalesced_inputs.coalesced_latency_id = scroll_update.latency_id
WHERE
scroll_update.input_type = 'GESTURE_SCROLL_UPDATE_EVENT';
-- Timestamps and other related information for events during the
-- input-associated (before inputs are coalesced into a frame) stages of a
-- scroll.
CREATE PERFETTO TABLE _scroll_update_input_timestamps_and_metadata AS
SELECT
refs.scroll_update_latency_id AS id,
refs.presentation_latency_id AS presented_in_frame_id,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
chrome_event_latency.scroll_id,
chrome_event_latency.is_presented,
chrome_event_latency.is_janky,
chrome_event_latency.is_janky_v3,
chrome_event_latency.event_type = 'INERTIAL_GESTURE_SCROLL_UPDATE' AS is_inertial,
chrome_event_latency.event_type = 'FIRST_GESTURE_SCROLL_UPDATE' AS is_first_scroll_update_in_scroll,
chrome_event_latency.ts AS generation_ts,
chrome_android_input.input_reader_processing_end_ts,
chrome_android_input.input_dispatcher_processing_end_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
touch_move_received_step.slice_id AS touch_move_received_slice_id,
touch_move_received_step.ts AS touch_move_received_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
touch_move_processed_step.slice_id AS touch_move_processed_slice_id,
touch_move_processed_step.ts AS touch_move_processed_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
scroll_update_created_step.slice_id AS scroll_update_created_slice_id,
scroll_update_created_step.utid AS browser_utid,
scroll_update_created_step.ts AS scroll_update_created_ts,
scroll_update_created_step.ts + scroll_update_created_step.dur AS scroll_update_created_end_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
compositor_dispatch_step.slice_id AS compositor_dispatch_slice_id,
compositor_dispatch_step.task_start_time_ts AS compositor_dispatch_task_ts,
compositor_dispatch_step.ts AS compositor_dispatch_ts,
compositor_dispatch_step.ts + compositor_dispatch_step.dur AS compositor_dispatch_end_ts,
compositor_dispatch_step.utid AS compositor_utid,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
compositor_coalesced_input_handled_step.slice_id AS compositor_coalesced_input_handled_slice_id,
compositor_coalesced_input_handled_step.ts AS compositor_coalesced_input_handled_ts,
compositor_coalesced_input_handled_step.ts + compositor_coalesced_input_handled_step.dur AS compositor_coalesced_input_handled_end_ts
FROM chrome_scroll_update_refs AS refs
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_gesture_scroll_updates AS chrome_event_latency
ON chrome_event_latency.scroll_update_id = refs.scroll_update_latency_id
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_dispatch_android_input_event_to_touch_move
ON refs.touch_move_latency_id = chrome_dispatch_android_input_event_to_touch_move.touch_move_latency_id
LEFT JOIN chrome_android_input
ON chrome_android_input.android_input_id = chrome_dispatch_android_input_event_to_touch_move.android_input_id
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_input_pipeline_steps AS touch_move_received_step
ON refs.touch_move_latency_id = touch_move_received_step.latency_id
AND touch_move_received_step.step = 'STEP_SEND_INPUT_EVENT_UI'
AND touch_move_received_step.input_type = 'TOUCH_MOVE_EVENT'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_input_pipeline_steps AS touch_move_processed_step
ON touch_move_processed_step.latency_id = refs.touch_move_latency_id
AND touch_move_processed_step.step = 'STEP_TOUCH_EVENT_HANDLED'
AND touch_move_processed_step.input_type = 'TOUCH_MOVE_EVENT'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_input_pipeline_steps AS scroll_update_created_step
ON scroll_update_created_step.latency_id = refs.scroll_update_latency_id
AND scroll_update_created_step.step = 'STEP_SEND_INPUT_EVENT_UI'
AND scroll_update_created_step.input_type = 'GESTURE_SCROLL_UPDATE_EVENT'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_input_pipeline_steps AS compositor_dispatch_step
ON compositor_dispatch_step.latency_id = refs.scroll_update_latency_id
AND compositor_dispatch_step.step = 'STEP_HANDLE_INPUT_EVENT_IMPL'
AND compositor_dispatch_step.input_type = 'GESTURE_SCROLL_UPDATE_EVENT'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_input_pipeline_steps AS compositor_coalesced_input_handled_step
ON compositor_coalesced_input_handled_step.latency_id = refs.scroll_update_latency_id
AND compositor_coalesced_input_handled_step.step = 'STEP_DID_HANDLE_INPUT_AND_OVERSCROLL'
AND compositor_coalesced_input_handled_step.input_type = 'GESTURE_SCROLL_UPDATE_EVENT';
-- Timestamps and durations for the input-associated (before coalescing inputs
-- into a frame) stages of a scroll.
CREATE PERFETTO TABLE chrome_scroll_update_input_pipeline (
-- Id of the `LatencyInfo.Flow` slices corresponding to this scroll event.
id LONG,
-- Id of the scroll this scroll update belongs to.
scroll_id LONG,
-- Id of the frame that this input was presented in. Can be joined with
-- `chrome_scroll_update_frame_pipeline.id`.
presented_in_frame_id LONG,
-- Whether this input event was presented.
is_presented BOOL,
-- Whether the corresponding frame is janky based on the
-- Event.ScrollJank.DelayedFramesPercentage.FixedWindow metric. This comes
-- directly from `perfetto.protos.EventLatency.is_janky_scrolled_frame`.
is_janky BOOL,
-- Whether the corresponding frame is janky based on the
-- Event.ScrollJank.DelayedFramesPercentage.FixedWindow3 metric. This comes
-- directly from `perfetto.protos.EventLatency.is_janky_scrolled_frame_v3`.
is_janky_v3 BOOL,
-- Whether the corresponding scroll is inertial (fling).
-- If this is `true`, "generation" and "touch_move" related timestamps and
-- durations will be null.
is_inertial BOOL,
-- Whether this is the first update in a scroll.
-- First scroll update can never be janky.
is_first_scroll_update_in_scroll BOOL,
-- Whether this is the first input that was presented in frame
-- `presented_in_frame_id`.
is_first_scroll_update_in_frame BOOL,
-- Input generation timestamp (from the Android system).
generation_ts TIMESTAMP,
-- End timestamp for the InputReader step (see android_input.sql).
-- Only populated when atrace 'input' category is enabled.
input_reader_processing_end_ts TIMESTAMP,
-- End timestamp for the InputDispatcher step (see android_input.sql).
-- Only populated when atrace 'input' category is enabled.
input_dispatcher_processing_end_ts TIMESTAMP,
-- Duration from input generation to when the browser received the input.
generation_to_browser_main_dur DURATION,
-- Utid for the browser main thread.
browser_utid LONG,
-- Slice id for the `STEP_SEND_INPUT_EVENT_UI` slice for the touch move.
touch_move_received_slice_id LONG,
-- Timestamp for the `STEP_SEND_INPUT_EVENT_UI` slice for the touch move.
touch_move_received_ts TIMESTAMP,
-- Duration for processing a `TouchMove` event.
touch_move_processing_dur DURATION,
-- Slice id for the `STEP_SEND_INPUT_EVENT_UI` slice for the gesture scroll.
scroll_update_created_slice_id LONG,
-- Timestamp for the `STEP_SEND_INPUT_EVENT_UI` slice for the gesture scroll.
scroll_update_created_ts TIMESTAMP,
-- Duration for creating a `GestureScrollUpdate` from a `TouchMove` event.
scroll_update_processing_dur DURATION,
-- End timestamp for the `STEP_SEND_INPUT_EVENT_UI` slice for the above.
scroll_update_created_end_ts TIMESTAMP,
-- Duration between the browser and compositor dispatch.
browser_to_compositor_delay_dur DURATION,
-- Utid for the renderer compositor thread.
compositor_utid LONG,
-- Slice id for the `STEP_HANDLE_INPUT_EVENT_IMPL` slice.
compositor_dispatch_slice_id LONG,
-- Timestamp for the `STEP_HANDLE_INPUT_EVENT_IMPL` slice or the
-- containing task (if available).
compositor_dispatch_ts TIMESTAMP,
-- Duration for the compositor dispatch itself.
compositor_dispatch_dur DURATION,
-- End timestamp for the `STEP_HANDLE_INPUT_EVENT_IMPL` slice.
compositor_dispatch_end_ts TIMESTAMP,
-- Duration between compositor dispatch and coalescing input.
compositor_dispatch_to_coalesced_input_handled_dur DURATION,
-- Slice id for the `STEP_DID_HANDLE_INPUT_AND_OVERSCROLL` slice.
compositor_coalesced_input_handled_slice_id LONG,
-- Timestamp for the `STEP_DID_HANDLE_INPUT_AND_OVERSCROLL` slice.
compositor_coalesced_input_handled_ts TIMESTAMP,
-- Duration for the `STEP_DID_HANDLE_INPUT_AND_OVERSCROLL` slice.
compositor_coalesced_input_handled_dur DURATION,
-- End timestamp for the `STEP_DID_HANDLE_INPUT_AND_OVERSCROLL` slice.
compositor_coalesced_input_handled_end_ts TIMESTAMP
) AS
WITH
processed_timestamps_and_metadata AS (
SELECT
id,
scroll_id,
presented_in_frame_id,
is_presented,
is_janky,
is_janky_v3,
is_inertial,
is_first_scroll_update_in_scroll,
row_number() OVER (PARTITION BY presented_in_frame_id ORDER BY generation_ts ASC) = 1 AS is_first_scroll_update_in_frame,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
browser_utid,
touch_move_received_slice_id,
-- Timestamps
generation_ts,
input_reader_processing_end_ts,
input_dispatcher_processing_end_ts,
touch_move_received_ts,
-- TODO(b:385160424): this is a workaround for cases when
-- generation time is later than the input time.
max(
iif(
is_inertial AND touch_move_received_ts IS NULL,
scroll_update_created_ts,
touch_move_received_ts
),
generation_ts
) AS browser_main_received_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
scroll_update_created_slice_id,
-- Timestamps
scroll_update_created_ts,
scroll_update_created_end_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
compositor_utid,
compositor_dispatch_slice_id,
-- Timestamps
coalesce(compositor_dispatch_task_ts, compositor_dispatch_ts) AS compositor_dispatch_ts,
compositor_dispatch_end_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
compositor_coalesced_input_handled_slice_id,
-- Timestamps
compositor_coalesced_input_handled_ts,
compositor_coalesced_input_handled_end_ts
FROM _scroll_update_input_timestamps_and_metadata
)
SELECT
id,
scroll_id,
presented_in_frame_id,
is_presented,
is_janky,
is_janky_v3,
is_inertial,
is_first_scroll_update_in_scroll,
is_first_scroll_update_in_frame,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- No applicable utid (duration between two threads).
-- No applicable slice id (duration between two threads).
generation_ts,
input_reader_processing_end_ts,
input_dispatcher_processing_end_ts,
-- Flings don't have a touch move event so make GenerationToBrowserMain span
-- all the way to the creation of the gesture scroll update.
browser_main_received_ts - generation_ts AS generation_to_browser_main_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
browser_utid,
touch_move_received_slice_id,
touch_move_received_ts,
scroll_update_created_ts - max(touch_move_received_ts, generation_ts) AS touch_move_processing_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `browser_utid`.
scroll_update_created_slice_id,
scroll_update_created_ts,
scroll_update_created_end_ts - scroll_update_created_ts AS scroll_update_processing_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- No applicable utid (duration between two threads).
-- No applicable slice id (duration between two threads).
scroll_update_created_end_ts,
-- TODO(b:385161677): use the start
-- of the STEP_SEND_DISPATCH_EVENT_MOJO_MESSAGE step
-- instead of scroll_update_created_end_ts.
max(compositor_dispatch_ts, scroll_update_created_end_ts) - scroll_update_created_end_ts AS browser_to_compositor_delay_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
compositor_utid,
compositor_dispatch_slice_id,
compositor_dispatch_ts,
compositor_dispatch_end_ts - compositor_dispatch_ts AS compositor_dispatch_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
-- No applicable slice id (duration between two slices).
compositor_dispatch_end_ts,
-- TODO(b:380868337): This is sometimes negative; check/fix this.
compositor_coalesced_input_handled_ts - compositor_dispatch_end_ts AS compositor_dispatch_to_coalesced_input_handled_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
compositor_coalesced_input_handled_slice_id,
compositor_coalesced_input_handled_ts,
compositor_coalesced_input_handled_end_ts - compositor_coalesced_input_handled_ts AS compositor_coalesced_input_handled_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
compositor_coalesced_input_handled_end_ts
FROM processed_timestamps_and_metadata;
-- Timestamps and other related information for events during the
-- frame-associated (after inputs are coalesced into a frame) stages of a
-- scroll.
CREATE PERFETTO TABLE _scroll_update_frame_timestamps_and_metadata AS
SELECT
refs.scroll_update_latency_id AS id,
refs.display_trace_id,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
chrome_event_latency.vsync_interval_ms AS vsync_interval_ms,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
compositor_resample_step.slice_id AS compositor_resample_slice_id,
compositor_resample_step.task_start_time_ts AS compositor_resample_task_ts,
compositor_resample_step.ts AS compositor_resample_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
compositor_receive_begin_frame_step.id AS compositor_receive_begin_frame_slice_id,
compositor_receive_begin_frame_step.task_start_time_ts AS compositor_receive_begin_frame_task_ts,
compositor_receive_begin_frame_step.ts AS compositor_receive_begin_frame_ts,
--
compositor_generate_compositor_frame_step.id AS compositor_generate_compositor_frame_slice_id,
compositor_generate_compositor_frame_step.task_start_time_ts AS compositor_generate_compositor_frame_task_ts,
compositor_generate_compositor_frame_step.ts AS compositor_generate_compositor_frame_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
compositor_submit_compositor_frame_step.id AS compositor_submit_compositor_frame_slice_id,
compositor_submit_compositor_frame_step.ts AS compositor_submit_compositor_frame_ts,
compositor_submit_compositor_frame_step.ts + compositor_submit_compositor_frame_step.dur AS compositor_submit_compositor_frame_end_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
viz_receive_compositor_frame_step.id AS viz_receive_compositor_frame_slice_id,
viz_receive_compositor_frame_step.task_start_time_ts AS viz_receive_compositor_frame_task_ts,
viz_receive_compositor_frame_step.ts AS viz_receive_compositor_frame_ts,
viz_receive_compositor_frame_step.ts + viz_receive_compositor_frame_step.dur AS viz_receive_compositor_frame_end_ts,
viz_receive_compositor_frame_step.utid AS viz_compositor_utid,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
viz_draw_and_swap_step.id AS viz_draw_and_swap_slice_id,
viz_draw_and_swap_step.task_start_time_ts AS viz_draw_and_swap_task_ts,
viz_draw_and_swap_step.ts AS viz_draw_and_swap_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
viz_send_buffer_swap_step.id AS viz_send_buffer_swap_slice_id,
viz_send_buffer_swap_step.ts + viz_send_buffer_swap_step.dur AS viz_send_buffer_swap_end_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
viz_swap_buffers_step.id AS viz_swap_buffers_slice_id,
viz_swap_buffers_step.task_start_time_ts AS viz_swap_buffers_task_ts,
viz_swap_buffers_step.ts AS viz_swap_buffers_ts,
viz_swap_buffers_step.ts + viz_swap_buffers_step.dur AS viz_swap_buffers_end_ts,
viz_swap_buffers_step.utid AS viz_gpu_thread_utid,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
chrome_event_latency.buffer_available_timestamp,
chrome_event_latency.buffer_ready_timestamp,
chrome_event_latency.latch_timestamp,
chrome_event_latency.presentation_timestamp
FROM chrome_scroll_update_refs AS refs
LEFT JOIN chrome_event_latencies AS chrome_event_latency
ON chrome_event_latency.scroll_update_id = refs.presentation_latency_id
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_input_pipeline_steps AS compositor_resample_step
ON compositor_resample_step.latency_id = refs.presentation_latency_id
AND compositor_resample_step.step = 'STEP_RESAMPLE_SCROLL_EVENTS'
AND compositor_resample_step.input_type = 'GESTURE_SCROLL_UPDATE_EVENT'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_graphics_pipeline_surface_frame_steps AS compositor_receive_begin_frame_step
ON compositor_receive_begin_frame_step.surface_frame_trace_id = refs.surface_frame_id
AND compositor_receive_begin_frame_step.step = 'STEP_RECEIVE_BEGIN_FRAME'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_graphics_pipeline_surface_frame_steps AS compositor_generate_compositor_frame_step
ON compositor_generate_compositor_frame_step.surface_frame_trace_id = refs.surface_frame_id
AND compositor_generate_compositor_frame_step.step = 'STEP_GENERATE_COMPOSITOR_FRAME'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_graphics_pipeline_surface_frame_steps AS compositor_submit_compositor_frame_step
ON compositor_submit_compositor_frame_step.surface_frame_trace_id = refs.surface_frame_id
AND compositor_submit_compositor_frame_step.step = 'STEP_SUBMIT_COMPOSITOR_FRAME'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_graphics_pipeline_surface_frame_steps AS viz_receive_compositor_frame_step
ON viz_receive_compositor_frame_step.surface_frame_trace_id = refs.surface_frame_id
AND viz_receive_compositor_frame_step.step = 'STEP_RECEIVE_COMPOSITOR_FRAME'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_graphics_pipeline_display_frame_steps AS viz_draw_and_swap_step
ON viz_draw_and_swap_step.display_trace_id = refs.display_trace_id
AND viz_draw_and_swap_step.step = 'STEP_DRAW_AND_SWAP'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_graphics_pipeline_display_frame_steps AS viz_send_buffer_swap_step
ON viz_send_buffer_swap_step.display_trace_id = refs.display_trace_id
AND viz_send_buffer_swap_step.step = 'STEP_SEND_BUFFER_SWAP'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
LEFT JOIN chrome_graphics_pipeline_display_frame_steps AS viz_swap_buffers_step
ON viz_swap_buffers_step.display_trace_id = refs.display_trace_id
AND viz_swap_buffers_step.step = 'STEP_BUFFER_SWAP_POST_SUBMIT'
-- Filter out inputs which were coalesced into a different frame (so that rows
-- of this table correspond to frames).
WHERE
refs.scroll_update_latency_id = refs.presentation_latency_id;
-- Timestamps and durations for the frame-associated (after coalescing inputs
-- into a frame) stages of a scroll.
CREATE PERFETTO TABLE chrome_scroll_update_frame_pipeline (
-- Id of the `LatencyInfo.Flow` slices corresponding to this scroll event.
id LONG,
-- Id of the aggregated frame this scroll update was presented in.
display_trace_id LONG,
-- Vsync interval (in milliseconds).
vsync_interval_ms DOUBLE,
-- Slice id for the `STEP_RESAMPLE_SCROLL_EVENTS` slice.
compositor_resample_slice_id LONG,
-- Timestamp for the `STEP_RESAMPLE_SCROLL_EVENTS` slice.
compositor_resample_ts TIMESTAMP,
-- Timestamp for the `STEP_RECEIVE_BEGIN_FRAME` slice or the
-- containing task (if available).
compositor_receive_begin_frame_ts TIMESTAMP,
-- Slice id for the `STEP_GENERATE_COMPOSITOR_FRAME` slice.
compositor_generate_compositor_frame_slice_id LONG,
-- Timestamp for the `STEP_GENERATE_COMPOSITOR_FRAME` slice or the
-- containing task (if available).
compositor_generate_compositor_frame_ts TIMESTAMP,
-- Duration between generating and submitting the compositor frame.
compositor_generate_frame_to_submit_frame_dur DURATION,
-- Slice id for the `STEP_SUBMIT_COMPOSITOR_FRAME` slice.
compositor_submit_compositor_frame_slice_id LONG,
-- Timestamp for the `STEP_SUBMIT_COMPOSITOR_FRAME` slice.
compositor_submit_compositor_frame_ts TIMESTAMP,
-- Duration for submitting the compositor frame (to viz).
compositor_submit_frame_dur DURATION,
-- End timestamp for the `STEP_SUBMIT_COMPOSITOR_FRAME` slice.
compositor_submit_compositor_frame_end_ts TIMESTAMP,
-- Delay when a compositor frame is sent from the renderer to viz.
compositor_to_viz_delay_dur DURATION,
-- Utid for the viz compositor thread.
viz_compositor_utid LONG,
-- Slice id for the `STEP_RECEIVE_COMPOSITOR_FRAME` slice.
viz_receive_compositor_frame_slice_id LONG,
-- Timestamp for the `STEP_RECEIVE_COMPOSITOR_FRAME` slice or the
-- containing task (if available).
viz_receive_compositor_frame_ts TIMESTAMP,
-- Duration of the viz work done on receiving the compositor frame.
viz_receive_compositor_frame_dur DURATION,
-- End timestamp for the `STEP_RECEIVE_COMPOSITOR_FRAME` slice.
viz_receive_compositor_frame_end_ts TIMESTAMP,
-- Duration between viz receiving the compositor frame to frame draw.
viz_wait_for_draw_dur DURATION,
-- Slice id for the `STEP_DRAW_AND_SWAP` slice.
viz_draw_and_swap_slice_id LONG,
-- Timestamp for the `STEP_DRAW_AND_SWAP` slice or the
-- containing task (if available).
viz_draw_and_swap_ts TIMESTAMP,
-- Duration for the viz drawing/swapping work for this frame.
viz_draw_and_swap_dur DURATION,
-- Slice id for the `STEP_SEND_BUFFER_SWAP` slice.
viz_send_buffer_swap_slice_id LONG,
-- End timestamp for the `STEP_SEND_BUFFER_SWAP` slice.
viz_send_buffer_swap_end_ts TIMESTAMP,
-- Delay between viz work on compositor thread and `CompositorGpuThread`.
viz_to_gpu_delay_dur DURATION,
-- Utid for the viz `CompositorGpuThread`.
viz_gpu_thread_utid LONG,
-- Slice id for the `STEP_BUFFER_SWAP_POST_SUBMIT` slice.
viz_swap_buffers_slice_id LONG,
-- Timestamp for the `STEP_BUFFER_SWAP_POST_SUBMIT` slice or the
-- containing task (if available).
viz_swap_buffers_ts TIMESTAMP,
-- Duration of frame buffer swapping work on viz.
viz_swap_buffers_dur DURATION,
-- End timestamp for the `STEP_BUFFER_SWAP_POST_SUBMIT` slice.
viz_swap_buffers_end_ts TIMESTAMP,
-- Duration of `EventLatency`'s `BufferReadyToLatch` step.
viz_swap_buffers_to_latch_dur DURATION,
-- Timestamp for `EventLatency`'s `LatchToSwapEnd` step.
latch_timestamp TIMESTAMP,
-- Duration of either `EventLatency`'s `LatchToSwapEnd` +
-- `SwapEndToPresentationCompositorFrame` steps or its `LatchToPresentation`
-- step.
viz_latch_to_presentation_dur DURATION,
-- Presentation timestamp for the frame.
presentation_timestamp TIMESTAMP
) AS
WITH
processed_timestamps_and_metadata AS (
SELECT
id,
display_trace_id,
vsync_interval_ms,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
compositor_resample_slice_id,
-- Timestamps
coalesce(compositor_resample_task_ts, compositor_resample_ts) AS compositor_resample_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
compositor_receive_begin_frame_slice_id,
-- Timestamps
coalesce(compositor_receive_begin_frame_task_ts, compositor_receive_begin_frame_ts) AS compositor_receive_begin_frame_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
compositor_generate_compositor_frame_slice_id,
-- Timestamps
coalesce(
compositor_generate_compositor_frame_task_ts,
compositor_generate_compositor_frame_ts
) AS compositor_generate_compositor_frame_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
compositor_submit_compositor_frame_slice_id,
-- Timestamps
compositor_submit_compositor_frame_ts,
compositor_submit_compositor_frame_end_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
viz_compositor_utid,
viz_receive_compositor_frame_slice_id,
-- Timestamps
coalesce(viz_receive_compositor_frame_task_ts, viz_receive_compositor_frame_ts) AS viz_receive_compositor_frame_ts,
viz_receive_compositor_frame_end_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
viz_draw_and_swap_slice_id,
-- Timestamps
coalesce(viz_draw_and_swap_task_ts, viz_draw_and_swap_ts) AS viz_draw_and_swap_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
viz_send_buffer_swap_slice_id,
-- Timestamps
viz_send_buffer_swap_end_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Ids
viz_gpu_thread_utid,
viz_swap_buffers_slice_id,
-- Timestamps
coalesce(viz_swap_buffers_task_ts, viz_swap_buffers_ts) AS viz_swap_buffers_ts,
viz_swap_buffers_end_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Timestamps
latch_timestamp,
presentation_timestamp
FROM _scroll_update_frame_timestamps_and_metadata
)
SELECT
id,
display_trace_id,
-- TODO(b:381062412): This is sometimes unexpectedly 0; check/fix this.
vsync_interval_ms,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
compositor_resample_slice_id,
compositor_resample_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
compositor_receive_begin_frame_ts,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
compositor_generate_compositor_frame_slice_id,
-- TODO(b:380868337): This is sometimes unexpectedly null; check/fix this.
compositor_generate_compositor_frame_ts,
compositor_submit_compositor_frame_ts - compositor_generate_compositor_frame_ts AS compositor_generate_frame_to_submit_frame_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
compositor_submit_compositor_frame_slice_id,
compositor_submit_compositor_frame_ts,
compositor_submit_compositor_frame_end_ts - compositor_submit_compositor_frame_ts AS compositor_submit_frame_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- No applicable utid (duration between two threads).
-- No applicable slice id (duration between two threads).
compositor_submit_compositor_frame_end_ts,
-- TODO(b:380868337): This is sometimes negative; check/fix this.
viz_receive_compositor_frame_ts - compositor_submit_compositor_frame_end_ts AS compositor_to_viz_delay_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
viz_compositor_utid,
viz_receive_compositor_frame_slice_id,
viz_receive_compositor_frame_ts,
viz_receive_compositor_frame_end_ts - viz_receive_compositor_frame_ts AS viz_receive_compositor_frame_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `viz_compositor_utid`.
-- No applicable slice id (duration between two slices).
viz_receive_compositor_frame_end_ts,
viz_draw_and_swap_ts - viz_receive_compositor_frame_end_ts AS viz_wait_for_draw_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `viz_compositor_utid`.
viz_draw_and_swap_slice_id,
viz_draw_and_swap_ts,
viz_send_buffer_swap_end_ts - viz_draw_and_swap_ts AS viz_draw_and_swap_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- No applicable utid (duration between two threads).
viz_send_buffer_swap_slice_id,
viz_send_buffer_swap_end_ts,
viz_swap_buffers_ts - viz_send_buffer_swap_end_ts AS viz_to_gpu_delay_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
viz_gpu_thread_utid,
viz_swap_buffers_slice_id,
viz_swap_buffers_ts,
viz_swap_buffers_end_ts - viz_swap_buffers_ts AS viz_swap_buffers_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
viz_swap_buffers_end_ts,
latch_timestamp - viz_swap_buffers_end_ts AS viz_swap_buffers_to_latch_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
latch_timestamp,
presentation_timestamp - latch_timestamp AS viz_latch_to_presentation_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
presentation_timestamp
FROM processed_timestamps_and_metadata;
-- Defines slices for all of the individual scrolls in a trace based on the
-- LatencyInfo-based scroll definition.
--
-- NOTE: this view of top level scrolls is based on the LatencyInfo definition
-- of a scroll, which differs subtly from the definition based on
-- EventLatencies.
-- TODO(b/278684408): add support for tracking scrolls across multiple Chrome/
-- WebView instances. Currently gesture_scroll_id unique within an instance, but
-- is not unique across multiple instances. Switching to an EventLatency based
-- definition of scrolls should resolve this.
CREATE PERFETTO TABLE chrome_scrolls (
-- The unique identifier of the scroll.
id LONG,
-- The start timestamp of the scroll.
ts TIMESTAMP,
-- The duration of the scroll.
dur DURATION,
-- The earliest timestamp of the EventLatency slice of the GESTURE_SCROLL_BEGIN type for the
-- corresponding scroll id.
gesture_scroll_begin_ts TIMESTAMP,
-- The earliest timestamp of the EventLatency slice of the GESTURE_SCROLL_END type /
-- the latest timestamp of the EventLatency slice of the GESTURE_SCROLL_UPDATE type for the
-- corresponding scroll id.
gesture_scroll_end_ts TIMESTAMP
) AS
SELECT
scroll_id AS id,
min(ts) AS ts,
cast_int!(MAX(ts + dur) - MIN(ts)) AS dur,
-- TODO(b:389055670): Remove this once the UI doesn't rely on it.
NULL AS gesture_scroll_begin_ts,
NULL AS gesture_scroll_end_ts
FROM chrome_gesture_scroll_updates
GROUP BY
scroll_id;
-- Timestamps and durations for the critical path stages during scrolling.
-- This table covers both the input-associated (before coalescing inputs into a
-- frame) and frame-associated (after coalescing inputs into a frame) stages of
-- a scroll:
--
-- ...
-- |
-- +--------------+--------------+
-- | |
-- V V
-- +-------------------------+ +-------------------------+
-- | _scroll_update_INPUT_ | | _scroll_update_FRAME_ |
-- | timestamps_and_metadata | | timestamps_and_metadata |
-- +------------+------------+ +------------+------------+
-- | |
-- V V
-- +-----------------------+ +-----------------------+
-- | chrome_scroll_update_ | | chrome_scroll_update_ |
-- | INPUT_pipeline | | FRAME_pipeline |
-- +-----------+-----------+ +-----------+-----------+
-- | |
-- +--------------+--------------+
-- |
-- V
-- +---------------------------+
-- | chrome_scroll_update_info |
-- +---------------------------+
CREATE PERFETTO TABLE chrome_scroll_update_info (
-- Id of the `LatencyInfo.Flow` slices corresponding to this scroll event.
id LONG,
-- Id of the scroll this scroll update belongs to.
scroll_id LONG,
-- Id (`LatencyInfo.ID`) of the previous input in this scroll.
previous_input_id LONG,
-- Id (`display_trace_id`) of the aggregated frame which this scroll update
-- was presented in.
frame_display_id LONG,
-- Vsync interval (in milliseconds).
vsync_interval_ms DOUBLE,
-- Whether this input event was presented.
is_presented BOOL,
-- Whether the corresponding frame is janky based on the
-- Event.ScrollJank.DelayedFramesPercentage.FixedWindow metric. This comes
-- directly from `perfetto.protos.EventLatency.is_janky_scrolled_frame`.
is_janky BOOL,
-- Whether the corresponding frame is janky based on the
-- Event.ScrollJank.DelayedFramesPercentage.FixedWindow3 metric. This comes
-- directly from `perfetto.protos.EventLatency.is_janky_scrolled_frame_v3`.
is_janky_v3 BOOL,
-- Whether the corresponding scroll is inertial (fling).
-- If this is `true`, "generation" and "touch_move" related timestamps and
-- durations will be null.
is_inertial BOOL,
-- Whether this is the first update in a scroll.
-- First scroll update can never be janky.
is_first_scroll_update_in_scroll BOOL,
-- Whether this is the first input that was presented in the frame.
is_first_scroll_update_in_frame BOOL,
-- Duration from the start of the browser process to the first
-- input generation timestamp.
browser_uptime_dur DURATION,
-- Input generation timestamp (from the Android system).
generation_ts TIMESTAMP,
-- Duration from the generation timestamp to the end of InputReader's work.
-- Only populated when atrace 'input' category is enabled.
input_reader_dur DURATION,
-- Duration of InputDispatcher's work.
-- Only populated when atrace 'input' category is enabled.
input_dispatcher_dur DURATION,
-- Duration from the generation timestamp for the previous input to
-- this input's generation timestamp.
since_previous_generation_dur DURATION,
-- Duration from input generation to when the browser received the input.
generation_to_browser_main_dur DURATION,
-- Utid for the browser main thread.
browser_utid LONG,
-- Slice id for the `STEP_SEND_INPUT_EVENT_UI` slice for the touch move.
touch_move_received_slice_id LONG,
-- Timestamp for the `STEP_SEND_INPUT_EVENT_UI` slice for the touch move.
touch_move_received_ts TIMESTAMP,
-- Duration for processing a `TouchMove` event.
touch_move_processing_dur DURATION,
-- Slice id for the `STEP_SEND_INPUT_EVENT_UI` slice for the gesture scroll.
scroll_update_created_slice_id LONG,
-- Timestamp for the `STEP_SEND_INPUT_EVENT_UI` slice for the gesture scroll.
scroll_update_created_ts TIMESTAMP,
-- Duration for creating a `GestureScrollUpdate` from a `TouchMove` event.
scroll_update_processing_dur DURATION,
-- End timestamp for the `STEP_SEND_INPUT_EVENT_UI` slice for the above.
scroll_update_created_end_ts TIMESTAMP,
-- Duration between the browser and compositor dispatch.
browser_to_compositor_delay_dur DURATION,
-- Utid for the renderer compositor thread.
compositor_utid LONG,
-- Slice id for the `STEP_HANDLE_INPUT_EVENT_IMPL` slice.
compositor_dispatch_slice_id LONG,
-- Timestamp for the `STEP_HANDLE_INPUT_EVENT_IMPL` slice or the
-- containing task (if available).
compositor_dispatch_ts TIMESTAMP,
-- Duration for the compositor dispatch itself.
compositor_dispatch_dur DURATION,
-- End timestamp for the `STEP_HANDLE_INPUT_EVENT_IMPL` slice.
compositor_dispatch_end_ts TIMESTAMP,
-- Duration between compositor dispatch and input resampling work.
compositor_dispatch_to_on_begin_frame_delay_dur DURATION,
-- Slice id for the `STEP_RESAMPLE_SCROLL_EVENTS` slice.
compositor_resample_slice_id LONG,
-- Slice id for the `STEP_DID_HANDLE_INPUT_AND_OVERSCROLL` slice.
compositor_coalesced_input_handled_slice_id LONG,
-- Start timestamp for work done on the input during "OnBeginFrame".
compositor_on_begin_frame_ts TIMESTAMP,
-- Duration of the "OnBeginFrame" work for this input.
compositor_on_begin_frame_dur DURATION,
-- End timestamp for work done on the input during "OnBeginFrame".
compositor_on_begin_frame_end_ts TIMESTAMP,
-- Delay until the compositor work for generating the frame begins.
compositor_on_begin_frame_to_generation_delay_dur DURATION,
-- Slice id for the `STEP_GENERATE_COMPOSITOR_FRAME` slice.
compositor_generate_compositor_frame_slice_id LONG,
-- Timestamp for the `STEP_GENERATE_COMPOSITOR_FRAME` slice or the
-- containing task (if available).
compositor_generate_compositor_frame_ts TIMESTAMP,
-- Duration between generating and submitting the compositor frame.
compositor_generate_frame_to_submit_frame_dur DURATION,
-- Slice id for the `STEP_SUBMIT_COMPOSITOR_FRAME` slice.
compositor_submit_compositor_frame_slice_id LONG,
-- Timestamp for the `STEP_SUBMIT_COMPOSITOR_FRAME` slice.
compositor_submit_compositor_frame_ts TIMESTAMP,
-- Duration for submitting the compositor frame (to viz).
compositor_submit_frame_dur DURATION,
-- End timestamp for the `STEP_SUBMIT_COMPOSITOR_FRAME` slice.
compositor_submit_compositor_frame_end_ts TIMESTAMP,
-- Delay when a compositor frame is sent from the renderer to viz.
compositor_to_viz_delay_dur DURATION,
-- Utid for the viz compositor thread.
viz_compositor_utid LONG,
-- Slice id for the `STEP_RECEIVE_COMPOSITOR_FRAME` slice.
viz_receive_compositor_frame_slice_id LONG,
-- Timestamp for the `STEP_RECEIVE_COMPOSITOR_FRAME` slice or the
-- containing task (if available).
viz_receive_compositor_frame_ts TIMESTAMP,
-- Duration of the viz work done on receiving the compositor frame.
viz_receive_compositor_frame_dur DURATION,
-- End timestamp for the `STEP_RECEIVE_COMPOSITOR_FRAME` slice.
viz_receive_compositor_frame_end_ts TIMESTAMP,
-- Duration between viz receiving the compositor frame to frame draw.
viz_wait_for_draw_dur DURATION,
-- Slice id for the `STEP_DRAW_AND_SWAP` slice.
viz_draw_and_swap_slice_id LONG,
-- Timestamp for the `STEP_DRAW_AND_SWAP` slice or the
-- containing task (if available).
viz_draw_and_swap_ts TIMESTAMP,
-- Duration for the viz drawing/swapping work for this frame.
viz_draw_and_swap_dur DURATION,
-- Slice id for the `STEP_SEND_BUFFER_SWAP` slice.
viz_send_buffer_swap_slice_id LONG,
-- End timestamp for the `STEP_SEND_BUFFER_SWAP` slice.
viz_send_buffer_swap_end_ts TIMESTAMP,
-- Delay between viz work on compositor thread and `CompositorGpuThread`.
viz_to_gpu_delay_dur DURATION,
-- Utid for the viz `CompositorGpuThread`.
viz_gpu_thread_utid LONG,
-- Slice id for the `STEP_BUFFER_SWAP_POST_SUBMIT` slice.
viz_swap_buffers_slice_id LONG,
-- Timestamp for the `STEP_BUFFER_SWAP_POST_SUBMIT` slice or the
-- containing task (if available).
viz_swap_buffers_ts TIMESTAMP,
-- Duration of frame buffer swapping work on viz.
viz_swap_buffers_dur DURATION,
-- End timestamp for the `STEP_BUFFER_SWAP_POST_SUBMIT` slice.
viz_swap_buffers_end_ts TIMESTAMP,
-- Duration of `EventLatency`'s `BufferReadyToLatch` step.
viz_swap_buffers_to_latch_dur DURATION,
-- Timestamp for `EventLatency`'s `LatchToSwapEnd` step.
latch_timestamp TIMESTAMP,
-- Duration of either `EventLatency`'s `LatchToSwapEnd` +
-- `SwapEndToPresentationCompositorFrame` steps or its `LatchToPresentation`
-- step.
viz_latch_to_presentation_dur DURATION,
-- Presentation timestamp for the frame.
presentation_timestamp TIMESTAMP
) AS
SELECT
input.id,
input.scroll_id,
lag(input.id) OVER (PARTITION BY input.scroll_id ORDER BY input.generation_ts) AS previous_input_id,
frame.display_trace_id AS frame_display_id,
-- TODO(b:381062412): This is sometimes unexpectedly 0; check/fix this.
frame.vsync_interval_ms,
input.is_presented,
input.is_janky,
input.is_janky_v3,
input.is_inertial,
input.is_first_scroll_update_in_scroll,
input.is_first_scroll_update_in_frame,
generation_ts - browser_process.start_ts AS browser_uptime_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- No applicable utid (duration between two threads).
-- No applicable slice id (duration between two threads).
input.generation_ts,
input.input_reader_processing_end_ts - generation_ts AS input_reader_dur,
input.input_dispatcher_processing_end_ts - input.input_reader_processing_end_ts AS input_dispatcher_dur,
input.generation_ts - lag(input.generation_ts) OVER (PARTITION BY input.scroll_id ORDER BY input.generation_ts) AS since_previous_generation_dur,
input.generation_to_browser_main_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
input.browser_utid,
input.touch_move_received_slice_id,
input.touch_move_received_ts,
input.touch_move_processing_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `browser_utid`.
input.scroll_update_created_slice_id,
input.scroll_update_created_ts,
input.scroll_update_processing_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- No applicable utid (duration between two threads).
-- No applicable slice id (duration between two threads).
input.scroll_update_created_end_ts,
-- TODO(b:380868337): This is sometimes negative; check/fix this.
input.browser_to_compositor_delay_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
input.compositor_utid,
input.compositor_dispatch_slice_id,
input.compositor_dispatch_ts,
input.compositor_dispatch_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
-- No applicable slice id (duration between two slices).
input.compositor_dispatch_end_ts,
-- TODO(b:380868337): This is sometimes negative; check/fix this.
-- TODO(b:381273884): use frame.compositor_receive_begin_frame_ts instead of
-- input.compositor_dispatch_end_ts.
coalesce(frame.compositor_resample_ts, input.compositor_coalesced_input_handled_ts) - input.compositor_dispatch_end_ts AS compositor_dispatch_to_on_begin_frame_delay_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
-- `compositor_on_begin_frame_dur` can depend on two slices.
frame.compositor_resample_slice_id,
input.compositor_coalesced_input_handled_slice_id,
coalesce(frame.compositor_resample_ts, input.compositor_coalesced_input_handled_ts) AS compositor_on_begin_frame_ts,
input.compositor_coalesced_input_handled_end_ts - coalesce(frame.compositor_resample_ts, input.compositor_coalesced_input_handled_ts) AS compositor_on_begin_frame_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
-- No applicable slice id (duration between two slices).
input.compositor_coalesced_input_handled_end_ts AS compositor_on_begin_frame_end_ts,
frame.compositor_generate_compositor_frame_ts - input.compositor_coalesced_input_handled_end_ts AS compositor_on_begin_frame_to_generation_delay_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
frame.compositor_generate_compositor_frame_slice_id,
-- TODO(b:380868337): This is sometimes unexpectedly null; check/fix this.
frame.compositor_generate_compositor_frame_ts,
frame.compositor_generate_frame_to_submit_frame_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `compositor_utid`.
frame.compositor_submit_compositor_frame_slice_id,
frame.compositor_submit_compositor_frame_ts,
frame.compositor_submit_frame_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- No applicable utid (duration between two threads).
-- No applicable slice id (duration between two threads).
frame.compositor_submit_compositor_frame_end_ts,
-- TODO(b:380868337): This is sometimes negative; check/fix this.
frame.compositor_to_viz_delay_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
frame.viz_compositor_utid,
frame.viz_receive_compositor_frame_slice_id,
frame.viz_receive_compositor_frame_ts,
frame.viz_receive_compositor_frame_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `viz_compositor_utid`.
-- No applicable slice id (duration between two slices).
frame.viz_receive_compositor_frame_end_ts,
frame.viz_wait_for_draw_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- On `viz_compositor_utid`.
frame.viz_draw_and_swap_slice_id,
frame.viz_draw_and_swap_ts,
frame.viz_draw_and_swap_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- No applicable utid (duration between two threads).
frame.viz_send_buffer_swap_slice_id,
frame.viz_send_buffer_swap_end_ts,
frame.viz_to_gpu_delay_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
frame.viz_gpu_thread_utid,
frame.viz_swap_buffers_slice_id,
frame.viz_swap_buffers_ts,
frame.viz_swap_buffers_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
frame.viz_swap_buffers_end_ts,
frame.viz_swap_buffers_to_latch_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
frame.latch_timestamp,
frame.viz_latch_to_presentation_dur,
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
frame.presentation_timestamp
FROM chrome_scroll_update_input_pipeline AS input
LEFT JOIN chrome_scroll_update_frame_pipeline AS frame
ON input.presented_in_frame_id = frame.id
LEFT JOIN thread AS browser_main_thread
ON browser_utid = browser_main_thread.utid
LEFT JOIN process AS browser_process
ON browser_process.upid = browser_main_thread.upid;
-- Helper macro to compute the stage delta.
-- Should be used only as a part of `chrome_scroll_frame_info`.
CREATE PERFETTO MACRO _chrome_scroll_frame_stage_delta(
name ColumnName
)
RETURNS Expr AS
iif(
info.is_first_scroll_update_in_scroll,
NULL,
$name - lag($name) OVER (ORDER BY generation_ts)
);
-- A list of all presented Chrome frames which contain scroll updates and associated
-- metadata.
CREATE PERFETTO TABLE chrome_scroll_frame_info (
-- Id (frame's display_trace_id) for the given frame.
id LONG,
-- Id of the scroll this scroll update belongs to.
scroll_id LONG,
-- Id (LatencyInfo.ID) of the last input before this frame.
last_input_before_this_frame_id LONG,
-- Vsync interval (in milliseconds).
-- TODO(b/394303662): Remove in favour of `vsync_interval_dur`.
vsync_interval_ms DOUBLE,
-- Vsync interval (in nanoseconds).
vsync_interval_dur DURATION,
-- Whether the corresponding frame is janky based on the
-- Event.ScrollJank.DelayedFramesPercentage.FixedWindow metric. This comes
-- directly from `perfetto.protos.EventLatency.is_janky_scrolled_frame`.
is_janky BOOL,
-- Whether the corresponding frame is janky based on the
-- Event.ScrollJank.DelayedFramesPercentage.FixedWindow3 metric. This comes
-- directly from `perfetto.protos.EventLatency.is_janky_scrolled_frame_v3`.
is_janky_v3 BOOL,
-- Whether the corresponding scroll is inertial (fling).
is_inertial BOOL,
-- Sum of all input deltas for all scroll updates in this frame.
-- These values are based on the delta of the OS input events.
total_input_delta_y DOUBLE,
-- Presented delta (change in page offset) for the given frame.
-- This delta is computed by Chrome (based on the input events).
presented_scrolled_delta_y DOUBLE,
-- Duration from the start of the browser process to the first
-- input generation timestamp.
browser_uptime_dur DURATION,
-- Input generation timestamp (from the Android system) for the first input.
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.
input_reader_dur DURATION,
-- Duration of InputDispatcher's work.
-- Only populated when atrace 'input' category is enabled.
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,
-- Presentation timestamp for the frame.
presentation_ts TIMESTAMP,
-- Utid for the browser main thread.
browser_utid JOINID(thread.id),
-- Duration from input generation to when the browser received the first input
-- in this frame.
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.
first_input_generation_to_browser_main_delta_dur DURATION,
-- Duration for processing a `TouchMove` event for the first input in this
-- frame.
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.
first_input_touch_move_processing_delta_dur DURATION,
-- Utid for the renderer compositor thread.
compositor_utid JOINID(thread.id),
-- Duration between the browser and compositor dispatch for the first input
-- in this frame.
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.
first_input_browser_to_compositor_delay_delta_dur DURATION,
-- Duration for the compositor dispatch for the first input 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,
-- Duration between the compositor dispatch and the "OnBeginFrame" work for the
-- first input in this frame.
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.
first_input_compositor_dispatch_to_on_begin_frame_delay_delta_dur DURATION,
-- Duration of the "OnBeginFrame" work for this frame.
compositor_on_begin_frame_dur DURATION,
-- Difference between `compositor_on_begin_frame_dur` for this frame and the
-- previous frame in the same scroll.
compositor_on_begin_frame_delta_dur DURATION,
-- Duration between the "OnBeginFrame" work and the generation of this frame.
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.
compositor_on_begin_frame_to_generation_delay_delta_dur DURATION,
-- Duration between the generation and submission of this frame.
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.
compositor_generate_frame_to_submit_frame_delta_dur DURATION,
-- Duration for submitting this frame.
compositor_submit_frame_dur DURATION,
-- Difference between `compositor_submit_frame_dur` for this frame and the
-- previous frame in the same scroll.
compositor_submit_frame_delta_dur DURATION,
-- Utid for the viz compositor thread.
viz_compositor_utid JOINID(thread.id),
-- Delay when a compositor frame is sent from the renderer to viz.
compositor_to_viz_delay_dur DURATION,
-- Difference between `compositor_to_viz_delay_dur` for this frame and the
-- previous frame in the same scroll.
compositor_to_viz_delay_delta_dur DURATION,
-- Duration of the viz work done on receiving the compositor frame.
viz_receive_compositor_frame_dur DURATION,
-- Difference between `viz_receive_compositor_frame_dur` for this frame and the
-- previous frame in the same scroll.
viz_receive_compositor_frame_delta_dur DURATION,
-- Duration between viz receiving the compositor frame to frame draw.
viz_wait_for_draw_dur DURATION,
-- Difference between `viz_wait_for_draw_dur` for this frame and the previous
-- frame in the same scroll.
viz_wait_for_draw_delta_dur DURATION,
-- Duration of the viz drawing/swapping work for this frame.
viz_draw_and_swap_dur DURATION,
-- Difference between `viz_draw_and_swap_dur` for this frame and the previous
-- frame in the same scroll.
viz_draw_and_swap_delta_dur DURATION,
-- Utid for the viz `CompositorGpuThread`.
viz_gpu_thread_utid JOINID(thread.id),
-- Delay between viz work on compositor thread and `CompositorGpuThread`.
viz_to_gpu_delay_dur DURATION,
-- Difference between `viz_to_gpu_delay_dur` for this frame and the previous
-- frame in the same scroll.
viz_to_gpu_delay_delta_dur DURATION,
-- Duration of frame buffer swapping work on viz.
viz_swap_buffers_dur DURATION,
-- Difference between `viz_swap_buffers_dur` for this frame and the previous
-- frame in the same scroll.
viz_swap_buffers_delta_dur DURATION,
-- Time between buffers ready until Choreographer's latch.
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.
viz_swap_buffers_to_latch_delta_dur DURATION,
-- Duration between Choreographer's latch and presentation.
viz_latch_to_presentation_dur DURATION,
-- Difference between `viz_latch_to_presentation_dur` for this frame and the
-- previous frame in the same scroll.
viz_latch_to_presentation_delta_dur DURATION
) AS
SELECT
frame_display_id AS id,
info.scroll_id,
previous_input_id AS last_input_before_this_frame_id,
vsync_interval_ms,
cast_int!(vsync_interval_ms * 1e6) AS vsync_interval_dur,
is_janky,
is_janky_v3,
is_inertial,
(
SELECT
sum(delta_y)
FROM chrome_scroll_input_offsets AS input
JOIN chrome_scroll_update_info AS update_info
ON input.scroll_update_id = update_info.id
WHERE
update_info.frame_display_id = info.frame_display_id
) AS total_input_delta_y,
delta.delta_y AS presented_scrolled_delta_y,
browser_uptime_dur,
info.generation_ts AS first_input_generation_ts,
input_reader_dur,
input_dispatcher_dur,
info.since_previous_generation_dur AS previous_last_input_to_first_input_generation_dur,
info.browser_utid,
info.generation_to_browser_main_dur AS first_input_generation_to_browser_main_dur,
presentation_timestamp AS presentation_ts,
_chrome_scroll_frame_stage_delta!(generation_to_browser_main_dur) AS first_input_generation_to_browser_main_delta_dur,
info.touch_move_processing_dur AS first_input_touch_move_processing_dur,
_chrome_scroll_frame_stage_delta!(touch_move_processing_dur) AS first_input_touch_move_processing_delta_dur,
info.compositor_utid,
info.browser_to_compositor_delay_dur AS first_input_browser_to_compositor_delay_dur,
_chrome_scroll_frame_stage_delta!(browser_to_compositor_delay_dur) AS first_input_browser_to_compositor_delay_delta_dur,
info.compositor_dispatch_dur AS first_input_compositor_dispatch_dur,
_chrome_scroll_frame_stage_delta!(compositor_dispatch_dur) AS first_input_compositor_dispatch_delta_dur,
info.compositor_dispatch_to_on_begin_frame_delay_dur AS first_input_compositor_dispatch_to_on_begin_frame_delay_dur,
_chrome_scroll_frame_stage_delta!(compositor_dispatch_to_on_begin_frame_delay_dur) AS first_input_compositor_dispatch_to_on_begin_frame_delay_delta_dur,
info.compositor_on_begin_frame_dur,
_chrome_scroll_frame_stage_delta!(compositor_on_begin_frame_dur) AS compositor_on_begin_frame_delta_dur,
info.compositor_on_begin_frame_to_generation_delay_dur,
_chrome_scroll_frame_stage_delta!(compositor_on_begin_frame_to_generation_delay_dur) AS compositor_on_begin_frame_to_generation_delay_delta_dur,
info.compositor_generate_frame_to_submit_frame_dur,
_chrome_scroll_frame_stage_delta!(compositor_generate_frame_to_submit_frame_dur) AS compositor_generate_frame_to_submit_frame_delta_dur,
info.compositor_submit_frame_dur,
_chrome_scroll_frame_stage_delta!(compositor_submit_frame_dur) AS compositor_submit_frame_delta_dur,
viz_compositor_utid,
info.compositor_to_viz_delay_dur,
_chrome_scroll_frame_stage_delta!(compositor_to_viz_delay_dur) AS compositor_to_viz_delay_delta_dur,
info.viz_receive_compositor_frame_dur,
_chrome_scroll_frame_stage_delta!(viz_receive_compositor_frame_dur) AS viz_receive_compositor_frame_delta_dur,
info.viz_wait_for_draw_dur,
_chrome_scroll_frame_stage_delta!(viz_wait_for_draw_dur) AS viz_wait_for_draw_delta_dur,
info.viz_draw_and_swap_dur,
_chrome_scroll_frame_stage_delta!(viz_draw_and_swap_dur) AS viz_draw_and_swap_delta_dur,
viz_gpu_thread_utid,
info.viz_to_gpu_delay_dur,
_chrome_scroll_frame_stage_delta!(viz_to_gpu_delay_dur) AS viz_to_gpu_delay_delta_dur,
info.viz_swap_buffers_dur,
_chrome_scroll_frame_stage_delta!(viz_swap_buffers_dur) AS viz_swap_buffers_delta_dur,
info.viz_swap_buffers_to_latch_dur,
_chrome_scroll_frame_stage_delta!(viz_swap_buffers_to_latch_dur) AS viz_swap_buffers_to_latch_delta_dur,
info.viz_latch_to_presentation_dur,
_chrome_scroll_frame_stage_delta!(viz_latch_to_presentation_dur) AS viz_latch_to_presentation_delta_dur
FROM chrome_scroll_update_info AS info
LEFT JOIN chrome_presented_scroll_offsets AS delta
ON info.id = delta.scroll_update_id
-- TODO(b:380286381, b:393051057): remove the frame_display_id condition when dropped frames are handled.
WHERE
is_first_scroll_update_in_frame AND info.frame_display_id IS NOT NULL;
-- Source of truth for the definition of the stages of a scroll. Mainly intended
-- for visualization purposes (e.g. in Chrome Scroll Jank plugin).
CREATE PERFETTO TABLE chrome_scroll_update_info_step_templates (
-- The name of a stage of a scroll.
step_name STRING,
-- The name of the column in `chrome_scroll_update_info` which contains the
-- timestamp of the stage.
ts_column_name STRING,
-- The name of the column in `chrome_scroll_update_info` which contains the
-- duration of the stage. NULL if the stage doesn't have a duration.
dur_column_name STRING
) AS
WITH
steps(step_name, ts_column_name, dur_column_name) AS (
SELECT
*
FROM (VALUES
('GenerationToBrowserMain', 'generation_ts', 'generation_to_browser_main_dur'),
('TouchMoveProcessing', 'touch_move_received_ts', 'touch_move_processing_dur'),
(
'ScrollUpdateProcessing',
'scroll_update_created_ts',
'scroll_update_processing_dur'
),
(
'BrowserMainToRendererCompositor',
'scroll_update_created_end_ts',
'browser_to_compositor_delay_dur'
),
(
'RendererCompositorDispatch',
'compositor_dispatch_ts',
'compositor_dispatch_dur'
),
(
'RendererCompositorDispatchToOnBeginFrame',
'compositor_dispatch_end_ts',
'compositor_dispatch_to_on_begin_frame_delay_dur'
),
(
'RendererCompositorBeginFrame',
'compositor_on_begin_frame_ts',
'compositor_on_begin_frame_dur'
),
(
'RendererCompositorBeginToGenerateFrame',
'compositor_on_begin_frame_end_ts',
'compositor_on_begin_frame_to_generation_delay_dur'
),
(
'RendererCompositorGenerateToSubmitFrame',
'compositor_generate_compositor_frame_ts',
'compositor_generate_frame_to_submit_frame_dur'
),
(
'RendererCompositorSubmitFrame',
'compositor_submit_compositor_frame_ts',
'compositor_submit_frame_dur'
),
(
'RendererCompositorToViz',
'compositor_submit_compositor_frame_end_ts',
'compositor_to_viz_delay_dur'
),
(
'VizReceiveFrame',
'viz_receive_compositor_frame_ts',
'viz_receive_compositor_frame_dur'
),
(
'VizReceiveToDrawFrame',
'viz_receive_compositor_frame_end_ts',
'viz_wait_for_draw_dur'
),
('VizDrawToSwapFrame', 'viz_draw_and_swap_ts', 'viz_draw_and_swap_dur'),
('VizToGpu', 'viz_send_buffer_swap_end_ts', 'viz_to_gpu_delay_dur'),
('VizSwapBuffers', 'viz_swap_buffers_ts', 'viz_swap_buffers_dur'),
(
'VizSwapBuffersToLatch',
'viz_swap_buffers_end_ts',
'viz_swap_buffers_to_latch_dur'
),
('VizLatchToPresentation', 'latch_timestamp', 'viz_latch_to_presentation_dur'),
('Presentation', 'presentation_timestamp', NULL)) AS _values
)
SELECT
step_name,
ts_column_name,
dur_column_name
FROM steps;