INCLUDE PERFETTO MODULE chrome.metadata;
INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_v3_cause;
INCLUDE PERFETTO MODULE chrome.event_latency;
CREATE PERFETTO FUNCTION _slice_name_from_id(
id LONG
)
RETURNS STRING AS
SELECT
name
FROM slice
WHERE
$id = id;
CREATE PERFETTO TABLE _presented_gesture_scrolls AS
SELECT
id,
ts,
dur,
scroll_update_id,
scroll_id,
presentation_timestamp,
event_type
FROM chrome_gesture_scroll_updates
WHERE
is_presented = TRUE
ORDER BY
ts ASC;
CREATE PERFETTO TABLE chrome_presented_gesture_scrolls (
id LONG,
ts TIMESTAMP,
dur DURATION,
last_presented_input_ts TIMESTAMP,
scroll_update_id LONG,
scroll_id LONG,
presentation_timestamp LONG,
event_type STRING
) AS
WITH
scroll_updates_with_presentation_info AS MATERIALIZED (
SELECT
id,
ts,
(
SELECT
id
FROM _presented_gesture_scrolls AS _presented
WHERE
_presented.ts <= scroll_update.ts
ORDER BY
ts DESC
LIMIT 1
) AS presented_to_scroll_update_slice_id
FROM chrome_gesture_scroll_updates AS scroll_update
ORDER BY
presented_to_scroll_update_slice_id,
ts
)
SELECT
id,
ts,
dur,
(
SELECT
presentation_info.ts
FROM scroll_updates_with_presentation_info AS presentation_info
WHERE
presentation_info.presented_to_scroll_update_slice_id = _presented_gesture_scrolls.id
ORDER BY
ts DESC
LIMIT 1
) AS last_presented_input_ts,
scroll_update_id,
scroll_id,
presentation_timestamp,
event_type
FROM _presented_gesture_scrolls;
CREATE PERFETTO TABLE chrome_scroll_updates_with_deltas (
scroll_update_id LONG,
delta_y DOUBLE
) 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";
CREATE PERFETTO TABLE chrome_full_frame_view (
id LONG,
ts TIMESTAMP,
last_presented_input_ts TIMESTAMP,
scroll_id LONG,
scroll_update_id LONG,
event_latency_id LONG,
dur DURATION,
presentation_timestamp LONG
) AS
SELECT
frames.id,
frames.ts,
frames.last_presented_input_ts,
frames.scroll_id,
frames.scroll_update_id,
frames.id AS event_latency_id,
frames.dur,
frames.presentation_timestamp
FROM chrome_presented_gesture_scrolls AS frames
WHERE
frames.event_type IN ('GESTURE_SCROLL_UPDATE', 'FIRST_GESTURE_SCROLL_UPDATE', 'INERTIAL_GESTURE_SCROLL_UPDATE', 'GESTURE_PINCH_UPDATE')
AND frames.presentation_timestamp IS NOT NULL;
CREATE PERFETTO TABLE chrome_full_frame_delta_view (
id LONG,
ts TIMESTAMP,
scroll_id LONG,
scroll_update_id LONG,
last_presented_input_ts TIMESTAMP,
delta_y DOUBLE,
event_latency_id LONG,
dur DURATION,
presentation_timestamp LONG
) AS
SELECT
frames.id,
frames.ts,
frames.scroll_id,
frames.scroll_update_id,
frames.last_presented_input_ts,
deltas.delta_y,
frames.event_latency_id,
frames.dur,
frames.presentation_timestamp
FROM chrome_full_frame_view AS frames
LEFT JOIN chrome_scroll_updates_with_deltas AS deltas
ON deltas.scroll_update_id = frames.scroll_update_id;
CREATE PERFETTO TABLE chrome_merged_frame_view (
id LONG,
max_start_ts TIMESTAMP,
min_start_ts TIMESTAMP,
scroll_id LONG,
scroll_update_id LONG,
encapsulated_scroll_ids STRING,
total_delta DOUBLE,
segregated_delta_y STRING,
event_latency_id LONG,
dur DURATION,
presentation_timestamp LONG
) AS
SELECT
id,
max(last_presented_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;
CREATE PERFETTO TABLE chrome_frame_info_with_delay (
id LONG,
max_start_ts TIMESTAMP,
min_start_ts TIMESTAMP,
scroll_id LONG,
scroll_update_id LONG,
encapsulated_scroll_ids STRING,
total_delta DOUBLE,
segregated_delta_y STRING,
event_latency_id LONG,
dur DURATION,
presentation_timestamp LONG,
delay_since_last_frame DOUBLE,
delay_since_last_input DOUBLE,
prev_event_latency_id LONG
) 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;
CREATE PERFETTO TABLE chrome_vsyncs (
vsync_interval DOUBLE
) AS
WITH
trace_vsyncs AS (
SELECT
extract_arg(slice.arg_set_id, 'event_latency.vsync_interval_ms') AS vsync_interval_ms
FROM slice
JOIN chrome_frame_info_with_delay
ON chrome_frame_info_with_delay.event_latency_id = slice.id
WHERE
extract_arg(slice.arg_set_id, 'event_latency.vsync_interval_ms') > 0
)
SELECT
coalesce(
(
SELECT
min(vsync_interval_ms)
FROM trace_vsyncs
),
min(delay_since_last_frame)
) AS vsync_interval
FROM chrome_frame_info_with_delay
WHERE
delay_since_last_frame > 0;
CREATE PERFETTO TABLE chrome_janky_frames_no_cause (
delay_since_last_frame DOUBLE,
event_latency_id LONG,
vsync_interval DOUBLE,
hardware_class STRING,
scroll_id LONG,
prev_event_latency_id LONG
) 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
);
CREATE PERFETTO TABLE chrome_janky_frames_no_subcause (
delay_since_last_frame DOUBLE,
event_latency_id LONG,
vsync_interval DOUBLE,
hardware_class STRING,
scroll_id LONG,
prev_event_latency_id LONG,
cause_id LONG
) AS
SELECT
*,
chrome_get_v3_jank_cause_id(event_latency_id, prev_event_latency_id) AS cause_id
FROM chrome_janky_frames_no_cause;
CREATE PERFETTO TABLE chrome_janky_frames (
cause_of_jank STRING,
sub_cause_of_jank STRING,
delay_since_last_frame DOUBLE,
event_latency_id LONG,
vsync_interval DOUBLE,
hardware_class STRING,
scroll_id LONG
) AS
SELECT
_slice_name_from_id(cause_id) AS cause_of_jank,
_slice_name_from_id(
chrome_get_v3_jank_cause_id(
cause_id,
(
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;
CREATE PERFETTO TABLE chrome_unique_frame_presentation_ts (
presentation_timestamp LONG
) AS
SELECT DISTINCT
presentation_timestamp
FROM chrome_presented_gesture_scrolls;
CREATE PERFETTO TABLE chrome_janky_frames_percentage (
delayed_frame_percentage DOUBLE
) AS
SELECT
(
SELECT
count()
FROM chrome_janky_frames
) * 1.0 / (
SELECT
count()
FROM chrome_unique_frame_presentation_ts
) * 100 AS delayed_frame_percentage;
CREATE PERFETTO TABLE chrome_frames_per_scroll (
scroll_id LONG,
num_frames LONG,
num_janky_frames LONG,
scroll_jank_percentage DOUBLE
) 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;