blob: 4116e63b16ec957e96913afbc1f7c4a9bee93d35 [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 common.slices;
-- Hardware info is useful when using sql metrics for analysis
-- in BTP.
INCLUDE PERFETTO MODULE chrome.metadata;
INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_v3_cause;
-- Grabs all gesture updates with respective scroll ids and start/end
-- timestamps, regardless of being coalesced.
--
-- @column ts The start timestamp of the scroll.
-- @column dur The duration of the scroll.
-- @column id Slice id for the scroll.
-- @column scroll_update_id The id of the scroll update event.
-- @column scroll_id The id of the scroll.
-- @column is_coalesced Whether this input event was coalesced.
CREATE PERFETTO TABLE chrome_gesture_scroll_updates AS
SELECT
ts,
dur,
id,
-- TODO(b/250089570) Add trace_id to EventLatency and update this script to use it.
EXTRACT_ARG(arg_set_id, 'chrome_latency_info.trace_id') AS scroll_update_id,
EXTRACT_ARG(arg_set_id, 'chrome_latency_info.gesture_scroll_id') AS scroll_id,
EXTRACT_ARG(arg_set_id, 'chrome_latency_info.is_coalesced') AS is_coalesced
FROM slice
WHERE name = "InputLatency::GestureScrollUpdate" AND dur != -1;
CREATE PERFETTO TABLE internal_non_coalesced_gesture_scrolls AS
SELECT
id,
ts,
dur,
scroll_update_id,
scroll_id
FROM chrome_gesture_scroll_updates
WHERE is_coalesced = false
ORDER BY ts ASC;
-- Scroll updates, corresponding to all input events that were converted to a
-- presented scroll update.
--
-- @column id Minimum slice id for input presented in this
-- frame, the non coalesced input.
-- @column ts The start timestamp for producing the frame.
-- @column dur The duration between producing and
-- presenting the frame.
-- @column last_coalesced_input_ts The timestamp of the last input that arrived
-- and got coalesced into the frame.
-- @column scroll_update_id The id of the scroll update event, a unique
-- identifier to the gesture.
-- @column scroll_id The id of the ongoing scroll.
CREATE PERFETTO TABLE chrome_presented_gesture_scrolls AS
WITH
scroll_updates_with_coalesce_info as MATERIALIZED (
SELECT
id,
ts,
-- For each scroll update, find the latest non-coalesced update which
-- happened before it. For coalesced scroll updates, this will be the
-- presented scroll update they have been coalesced into.
(
SELECT id
FROM internal_non_coalesced_gesture_scrolls non_coalesced
WHERE non_coalesced.ts <= scroll_update.ts
ORDER BY ts DESC
LIMIT 1
) as coalesced_to_scroll_update_slice_id
FROM chrome_gesture_scroll_updates scroll_update
ORDER BY coalesced_to_scroll_update_slice_id, ts
)
SELECT
id,
ts,
dur,
-- Find the latest input that was coalesced into this scroll update.
(
SELECT coalesce_info.ts
FROM scroll_updates_with_coalesce_info coalesce_info
WHERE
coalesce_info.coalesced_to_scroll_update_slice_id =
internal_non_coalesced_gesture_scrolls.id
ORDER BY ts DESC
LIMIT 1
) as last_coalesced_input_ts,
scroll_update_id,
scroll_id
FROM internal_non_coalesced_gesture_scrolls;
-- Associate every trace_id with it's perceived delta_y on the screen after
-- prediction.
--
-- @column scroll_update_id The id of the scroll update event.
-- @column delta_y The perceived delta_y on the screen post
-- prediction.
CREATE PERFETTO TABLE chrome_scroll_updates_with_deltas AS
SELECT
EXTRACT_ARG(arg_set_id, 'scroll_deltas.trace_id') AS scroll_update_id,
EXTRACT_ARG(arg_set_id, 'scroll_deltas.provided_to_compositor_delta_y') AS delta_y
FROM slice
WHERE name = "InputHandlerProxy::HandleGestureScrollUpdate_Result";
-- Extract event latency timestamps, to later use it for joining
-- with gesture scroll updates, as event latencies don't have trace
-- ids associated with it.
--
-- @column ts Start timestamp for the EventLatency.
-- @column event_latency_id Slice id of the EventLatency.
-- @column dur Duration of the EventLatency.
-- @column input_latency_end_ts End timestamp for input aka the
-- timestamp of the LatchToSwapEnd
-- substage.
-- @column presentation_timestamp Frame presentation timestamp aka the
-- timestamp of the
-- SwapEndToPresentationCompositorFrame
-- substage.
-- @column event_type EventLatency event type.
CREATE PERFETTO TABLE chrome_gesture_scroll_event_latencies AS
SELECT
slice.ts,
slice.id AS event_latency_id,
slice.dur AS dur,
descendant_slice_end(slice.id, "LatchToSwapEnd") AS input_latency_end_ts,
descendant_slice_end(slice.id, "SwapEndToPresentationCompositorFrame") AS presentation_timestamp,
EXTRACT_ARG(arg_set_id, 'event_latency.event_type') AS event_type
FROM slice
WHERE name = "EventLatency"
AND event_type in (
"GESTURE_SCROLL_UPDATE",
"FIRST_GESTURE_SCROLL_UPDATE",
"INERTIAL_GESTURE_SCROLL_UPDATE")
AND has_descendant_slice_with_name(slice.id, "SwapEndToPresentationCompositorFrame");
-- Join presented gesture scrolls with their respective event
-- latencies based on |LatchToSwapEnd| timestamp, as it's the
-- end timestamp for both the gesture scroll update slice and
-- the LatchToSwapEnd slice.
--
-- @column id ID of the frame.
-- @column ts Start timestamp of the frame.
-- @column last_coalesced_input_ts The timestamp of the last coalesced
-- input.
-- @column scroll_id ID of the associated scroll.
-- @column scroll_update_id ID of the associated scroll update.
-- @column event_latency_id ID of the associated EventLatency.
-- @column dur Duration of the associated EventLatency.
-- @column presentation_timestamp Frame presentation timestamp.
CREATE PERFETTO TABLE chrome_full_frame_view AS
SELECT
frames.id,
frames.ts,
frames.last_coalesced_input_ts,
frames.scroll_id,
frames.scroll_update_id,
events.event_latency_id,
events.dur,
events.presentation_timestamp
FROM chrome_presented_gesture_scrolls frames
JOIN chrome_gesture_scroll_event_latencies events
ON frames.ts = events.ts
AND events.input_latency_end_ts = (frames.ts + frames.dur);
-- Join deltas with EventLatency data.
--
-- @column id ID of the frame.
-- @column ts Start timestamp of the frame.
-- @column scroll_id ID of the associated scroll.
-- @column scroll_update_id ID of the associated scroll update.
-- @column last_coalesced_input_ts The timestamp of the last coalesced
-- input.
-- @column delta_y The perceived delta_y on the screen post
-- -- prediction.
-- @column event_latency_id ID of the associated EventLatency.
-- @column dur Duration of the associated EventLatency.
-- @column presentation_timestamp Frame presentation timestamp.
CREATE PERFETTO TABLE chrome_full_frame_delta_view AS
SELECT
frames.id,
frames.ts,
frames.scroll_id,
frames.scroll_update_id,
frames.last_coalesced_input_ts,
deltas.delta_y,
frames.event_latency_id,
frames.dur,
frames.presentation_timestamp
FROM chrome_full_frame_view frames
LEFT JOIN chrome_scroll_updates_with_deltas deltas
ON deltas.scroll_update_id = frames.scroll_update_id;
-- Group all gestures presented at the same timestamp together in
-- a single row.
--
-- @column id ID of the frame.
-- @column max_start_ts The timestamp of the last coalesced
-- input.
-- @column min_start_ts The earliest frame start timestamp.
-- @column scroll_id ID of the associated scroll.
-- @column scroll_update_id ID of the associated scroll update.
-- @column encapsulated_scroll_ids All scroll updates associated with the
-- frame presentation timestamp.
-- @column total_delta Sum of all perceived delta_y values at
-- the frame presentation timestamp.
-- @column segregated_delta_y Lists all of the perceived delta_y
-- values at the frame presentation
-- timestamp.
-- @column event_latency_id ID of the associated EventLatency.
-- @column dur Maximum duration of the associated
-- EventLatency.
-- @column presentation_timestamp Frame presentation timestamp.
CREATE VIEW chrome_merged_frame_view AS
SELECT
id,
MAX(last_coalesced_input_ts) AS max_start_ts,
MIN(ts) AS min_start_ts,
scroll_id,
scroll_update_id,
GROUP_CONCAT(scroll_update_id,',') AS encapsulated_scroll_ids,
SUM(delta_y) AS total_delta,
GROUP_CONCAT(delta_y, ',') AS segregated_delta_y,
event_latency_id,
MAX(dur) AS dur,
presentation_timestamp
FROM chrome_full_frame_delta_view
GROUP BY presentation_timestamp
ORDER BY presentation_timestamp;
-- View contains all chrome presented frames during gesture updates
-- while calculating delay since last presented which usually should
-- equal to |VSYNC_INTERVAL| if no jank is present.
--
-- @column id gesture scroll slice id.
-- @column min_start_ts OS timestamp of the first touch move arrival
-- within a frame.
-- @column max_start_ts OS timestamp of the last touch move arrival
-- within a frame.
-- @column scroll_id The scroll which the touch belongs to.
-- @column encapsulated_scroll_ids Trace ids of all frames presented in at this
-- vsync.
-- @column total_delta Summation of all delta_y of all gesture
-- scrolls in this frame.
-- @column segregated_delta_y All delta y of all gesture scrolls comma
-- separated, summing those gives |total_delta|.
-- @column event_latency_id Event latency id of the presented frame.
-- @column dur Duration of the EventLatency.
-- @column presentation_timestamp Timestamp at which the frame was shown on the
-- screen.
-- @column delay_since_last_frame Time elapsed since the previous frame was
-- presented, usually equals |VSYNC| if no frame
-- drops happened.
-- @column delay_since_last_input Difference in OS timestamps of inputs in the
-- current and the previous frame.
-- @column prev_event_latency_id The event latency id that will be used as a
-- reference to determine the jank cause.
CREATE VIEW chrome_frame_info_with_delay AS
SELECT
*,
(presentation_timestamp -
LAG(presentation_timestamp, 1, presentation_timestamp)
OVER (PARTITION BY scroll_id ORDER BY presentation_timestamp)) / 1e6 AS delay_since_last_frame,
(min_start_ts -
LAG(max_start_ts, 1, min_start_ts)
OVER (PARTITION BY scroll_id ORDER BY min_start_ts)) / 1e6 AS delay_since_last_input,
LAG(event_latency_id, 1, -1) OVER (PARTITION BY scroll_id ORDER BY min_start_ts) AS prev_event_latency_id
FROM chrome_merged_frame_view;
-- Calculate |VSYNC_INTERVAL| as the lowest delay between frames larger than
-- zero.
-- TODO(b/286222128): Emit this data from Chrome instead of calculating it.
--
-- @column vsync_interval The lowest delay between frames larger than
-- zero.
CREATE VIEW chrome_vsyncs AS
SELECT
MIN(delay_since_last_frame) AS vsync_interval
FROM chrome_frame_info_with_delay
WHERE delay_since_last_frame > 0;
-- Filter the frame view only to frames that had missed vsyncs.
--
-- @column delay_since_last_frame Time elapsed since the previous frame was
-- presented, will be more than |VSYNC| in this
-- view.
-- @column event_latency_id Event latency id of the presented frame.
-- @column vsync_interval Vsync interval at the time of recording the
-- trace.
-- @column hardware_class Device brand and model.
-- @column scroll_id The scroll corresponding to this frame.
-- @column prev_event_latency_id The event latency id that will be used as a
-- reference to determine the jank cause.
CREATE VIEW chrome_janky_frames_no_cause AS
SELECT
delay_since_last_frame,
event_latency_id,
(SELECT vsync_interval FROM chrome_vsyncs) AS vsync_interval,
chrome_hardware_class() AS hardware_class,
scroll_id,
prev_event_latency_id
FROM chrome_frame_info_with_delay
WHERE delay_since_last_frame > (select vsync_interval + vsync_interval / 2 from chrome_vsyncs)
AND delay_since_last_input < (select vsync_interval + vsync_interval / 2 from chrome_vsyncs);
-- Janky frame information including the jank cause.
-- @column delay_since_last_frame Time elapsed since the previous frame was
-- presented, will be more than |VSYNC| in this
-- view.
-- @column event_latency_id Event latency id of the presented frame.
-- @column vsync_interval Vsync interval at the time of recording the
-- trace.
-- @column hardware_class Device brand and model.
-- @column scroll_id The scroll corresponding to this frame.
-- @column prev_event_latency_id The event latency id that will be used as a
-- reference to determine the jank cause.
-- @column cause_id Id of the slice corresponding to the offending stage.
CREATE VIEW chrome_janky_frames_no_subcause AS
SELECT
*,
get_v3_jank_cause_id(event_latency_id, prev_event_latency_id) AS cause_id
FROM chrome_janky_frames_no_cause;
-- Finds all causes of jank for all janky frames, and a cause of sub jank
-- if the cause of jank was GPU related.
--
-- @column cause_of_jank The reason the Vsync was missed.
-- @column sub_cause_of_jank Further breakdown if the root cause was GPU
-- related.
-- @column delay_since_last_frame Time elapsed since the previous frame was
-- presented, will be more than |VSYNC| in this
-- view.
-- @column event_latency_id Event latency id of the presented frame.
-- @column vsync_interval Vsync interval at the time of recording the
-- trace.
-- @column hardware_class Device brand and model.
-- @column scroll_id The scroll corresponding to this frame.
CREATE VIEW chrome_janky_frames AS
SELECT
slice_name_from_id(cause_id) AS cause_of_jank,
slice_name_from_id(
-- Getting sub-cause
get_v3_jank_cause_id(
-- Here the cause itself is the parent.
cause_id,
-- Get the previous cause id as a child to the previous |EventLatency|.
(SELECT
id
FROM slice
WHERE name = slice_name_from_id(cause_id)
AND parent_id = prev_event_latency_id)
)) AS sub_cause_of_jank,
delay_since_last_frame,
event_latency_id,
vsync_interval,
hardware_class,
scroll_id
FROM chrome_janky_frames_no_subcause;
-- Counting all unique frame presentation timestamps.
--
-- @column presentation_timestamp The unique frame presentation timestamp.
CREATE VIEW chrome_unique_frame_presentation_ts AS
SELECT DISTINCT
presentation_timestamp
FROM chrome_gesture_scroll_event_latencies;
-- Dividing missed frames over total frames to get janky frame percentage.
-- This represents the v3 scroll jank metrics.
-- Reflects Event.Jank.DelayedFramesPercentage UMA metric.
--
-- @column delayed_frame_percentage The percent of missed frames relative
-- to total frames - aka the percent of
-- janky frames.
CREATE VIEW chrome_janky_frames_percentage AS
SELECT
(SELECT
COUNT()
FROM chrome_janky_frames) * 1.0
/ (SELECT
COUNT()
FROM chrome_unique_frame_presentation_ts) * 100 AS delayed_frame_percentage;
-- Number of frames and janky frames per scroll.
--
-- @column scroll_id The ID of the scroll.
-- @column num_frames The number of frames in the scroll.
-- @column num_janky_frames The number of delayed/janky frames.
-- @column scroll_jank_percentage The percentage of janky frames relative to
-- total frames.
CREATE VIEW chrome_frames_per_scroll AS
WITH
frames AS (
SELECT scroll_id, COUNT(*) AS num_frames
FROM
chrome_frame_info_with_delay
GROUP BY scroll_id
),
janky_frames AS (
SELECT scroll_id, COUNT(*) AS num_janky_frames
FROM
chrome_janky_frames
GROUP BY scroll_id
)
SELECT
frames.scroll_id AS scroll_id,
frames.num_frames AS num_frames,
janky_frames.num_janky_frames AS num_janky_frames,
100.0 * janky_frames.num_janky_frames / frames.num_frames
AS scroll_jank_percentage
FROM frames
LEFT JOIN janky_frames
ON frames.scroll_id = janky_frames.scroll_id;
-- Scroll jank causes per scroll.
--
-- @column scroll_id The ID of the scroll.
-- @column max_delay_since_last_frame The maximum time a frame was delayed
-- after the presentation of the previous
-- frame.
-- @column vsync_interval The expected vsync interval.
-- @column scroll_jank_causes A proto amalgamation of each scroll
-- jank cause including cause name, sub
-- cause and the duration of the delay
-- since the previous frame was presented.
CREATE VIEW chrome_causes_per_scroll AS
SELECT
scroll_id,
MAX(1.0 * delay_since_last_frame / vsync_interval)
AS max_delay_since_last_frame,
-- MAX does not matter, since `vsync_interval` is the computed as the
-- same value for a single trace.
MAX(vsync_interval) AS vsync_interval,
RepeatedField(
ChromeScrollJankV3_Scroll_ScrollJankCause(
'cause',
cause_of_jank,
'sub_cause',
sub_cause_of_jank,
'delay_since_last_frame',
1.0 * delay_since_last_frame / vsync_interval))
AS scroll_jank_causes
FROM
chrome_janky_frames
GROUP BY scroll_id;