• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--
2-- Copyright 2022 The Android Open Source Project
3--
4-- Licensed under the Apache License, Version 2.0 (the "License");
5-- you may not use this file except in compliance with the License.
6-- You may obtain a copy of the License at
7--
8--     https://www.apache.org/licenses/LICENSE-2.0
9--
10-- Unless required by applicable law or agreed to in writing, software
11-- distributed under the License is distributed on an "AS IS" BASIS,
12-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-- See the License for the specific language governing permissions and
14-- limitations under the License.
15--
16-- WARNING: This metric should not be used as a source of truth. It is under
17--          active development and the values & meaning might change without
18--          notice.
19
20-- Given a slice id of an event, get timestamp of the most recent flow
21-- event on the Chrome IO thread that preceded this slice.
22-- This helps us identify the last flow event on the IO thread before
23-- letting the browser main thread be aware of input.
24-- We need this for flings (generated by the GPU process) and blocked
25-- touch moves that are forwarded from the renderer.
26-- Returning the slice id for the flow_out on the chrome IO thread.
27CREATE OR REPLACE PERFETTO FUNCTION {{function_prefix}}PRECEDING_IO_THREAD_EVENT_FLOW_ID(id LONG)
28RETURNS LONG AS
29SELECT MAX(flow.slice_out) AS id
30FROM PRECEDING_FLOW(($id)) flow;
31
32-- Returns a Chrome task which contains the given slice.
33CREATE OR REPLACE PERFETTO FUNCTION {{function_prefix}}GET_ENCLOSING_CHROME_TASK_NAME(
34  slice_id LONG
35)
36RETURNS STRING AS
37SELECT
38  task.name
39FROM ancestor_slice($slice_id)
40JOIN chrome_tasks task USING (id)
41LIMIT 1;
42
43CREATE OR REPLACE PERFETTO FUNCTION {{function_prefix}}GET_SCROLL_TYPE(
44  blocked_gesture BOOL,
45  task_name STRING
46)
47RETURNS STRING AS
48SELECT
49  CASE WHEN ($blocked_gesture)
50  THEN (SELECT
51          CASE WHEN ($task_name) glob "viz.mojom.BeginFrameObserver *"
52          THEN "fling"
53          WHEN ($task_name) glob "blink.mojom.WidgetInputHandler *"
54          THEN "blocking_touch_move"
55          ELSE "unknown" END)
56  ELSE "regular" END AS delay_type;
57
58-- Get all InputLatency::GestureScrollUpdate events, to use their
59-- flows later on to decide how much time we waited from queueing the event
60-- until we started processing it.
61DROP VIEW IF EXISTS chrome_valid_gesture_updates;
62CREATE PERFETTO VIEW chrome_valid_gesture_updates
63AS
64SELECT
65  name,
66  EXTRACT_ARG(
67    arg_set_id, 'chrome_latency_info.trace_id') AS trace_id,
68  ts,
69  id,
70  dur
71FROM
72  {{slice_table_name}}
73WHERE
74  name = 'InputLatency::GestureScrollUpdate'
75  AND EXTRACT_ARG(
76    arg_set_id, "chrome_latency_info.is_coalesced")
77  = 0
78ORDER BY trace_id;
79
80-- Get all chrome_latency_info_for_gesture_slices where trace_ids are not -1,
81-- as those are faulty, then join with the GestureScrollUpdate table to get
82-- only slices associated with update events.
83DROP VIEW IF EXISTS chrome_flow_slices_for_gestures;
84CREATE PERFETTO VIEW chrome_flow_slices_for_gestures
85AS
86SELECT
87  s.ts,
88  EXTRACT_ARG(
89    s.arg_set_id, 'chrome_latency_info.trace_id') AS trace_id,
90  s.arg_set_id,
91  s.id,
92  s.track_id,
93  s.dur
94FROM
95  {{slice_table_name}} s
96JOIN chrome_valid_gesture_updates
97  ON
98    chrome_valid_gesture_updates.trace_id = EXTRACT_ARG(
99      s.arg_set_id, 'chrome_latency_info.trace_id')
100    AND s.ts >= chrome_valid_gesture_updates.ts
101    AND s.ts + s.dur
102    <= chrome_valid_gesture_updates.ts + chrome_valid_gesture_updates.dur
103WHERE
104  s.name = 'LatencyInfo.Flow'
105  AND trace_id != -1;
106
107-- Tie chrome_latency_info_for_gesture_slices slices to processes to avoid
108-- calculating intervals per process as multiple chrome instances can be up
109-- on system traces.
110DROP VIEW IF EXISTS chrome_flow_slices_for_gestures_tied_process;
111CREATE PERFETTO VIEW chrome_flow_slices_for_gestures_tied_process
112AS
113SELECT
114  ts,
115  trace_id,
116  arg_set_id,
117  chrome_flow_slices_for_gestures.id,
118  dur,
119  thread.upid
120FROM
121  chrome_flow_slices_for_gestures
122JOIN thread_track ON chrome_flow_slices_for_gestures.track_id = thread_track.id
123JOIN thread ON thread_track.utid = thread.utid
124  AND is_main_thread;
125
126-- Index all flows per trace_id, to get the first flow event per input
127-- GestureScrollUpdate, this will later be used to calculate the time
128-- from receiving input to the first flow event appearing.
129DROP TABLE IF EXISTS chrome_indexed_flow_per_gesture;
130CREATE PERFETTO TABLE chrome_indexed_flow_per_gesture
131AS
132SELECT
133  ts,
134  trace_id,
135  arg_set_id,
136  id,
137  ROW_NUMBER()
138  OVER (
139    PARTITION BY trace_id, upid
140    ORDER BY
141      ts ASC
142  ) AS flow_order,
143  upid,
144  dur
145FROM
146  chrome_flow_slices_for_gestures_tied_process;
147
148-- TODO(b/235067134) all the previous views including this one are
149-- reimplementations of gesture_jank.sql with less restrictions, let's
150-- merge both of them into one script or make this script a base for the
151-- other.
152-- Get the first flow event per gesture.
153DROP VIEW IF EXISTS chrome_first_flow_per_gesture;
154CREATE PERFETTO VIEW chrome_first_flow_per_gesture
155AS
156SELECT
157  *
158FROM
159  chrome_indexed_flow_per_gesture
160WHERE
161  flow_order = 1;
162
163-- The decision for processing on the browser main thread for a frame can be
164-- instant, or delayed by the renderer in cases where the renderer needs to
165-- decide whether the touch move is an ScrollUpdate or not, and in other cases
166-- for flings, the scroll itself will be generated by the viz compositor thread
167-- on each vsync interval.
168DROP VIEW IF EXISTS chrome_categorized_first_flow_events;
169CREATE PERFETTO VIEW chrome_categorized_first_flow_events
170AS
171SELECT
172  *,
173  NOT COALESCE((
174    SELECT
175      COUNT()
176    FROM
177      ancestor_slice(chrome_first_flow_per_gesture.id) ancestor_slices
178    WHERE
179      -- sendTouchEvent means the event wasn't delayed by the renderer
180      -- and is not a fling generated by the viz compositor thread(GPU process).
181      ancestor_slices.name = "sendTouchEvent"
182  )
183  = 1, FALSE) AS blocked_gesture
184FROM
185  chrome_first_flow_per_gesture;
186
187-- For cases where it's not blocked, get the timestamp of input as the
188-- beginning of time we theoretically could have started processing
189-- the input event, which is the timestamp of the GestureScrollUpdate event
190-- otherwise fall back to the top level slice to check the timestamp
191-- of it's calling flow
192DROP VIEW IF EXISTS chrome_input_to_browser_interval_slice_ids;
193CREATE PERFETTO VIEW chrome_input_to_browser_interval_slice_ids
194AS
195SELECT
196  chrome_categorized_first_flow_events.id AS window_end_id,
197  chrome_categorized_first_flow_events.ts AS window_end_ts,
198  -- If blocked, get the flow_out slice's timestamp as our beginning
199  -- given that the flow_in is coming to our toplevel parent task
200  CASE
201    WHEN blocked_gesture
202      THEN
203      {{function_prefix}}PRECEDING_IO_THREAD_EVENT_FLOW_ID(chrome_categorized_first_flow_events.id)
204    ELSE
205      -- TODO(b/236590359): is selecting here better or join and ordering by?
206      -- Let's benchmark and modify accordingly.
207      (
208        SELECT
209          chrome_gestures.id
210        FROM
211          chrome_valid_gesture_updates chrome_gestures
212        WHERE
213          chrome_gestures.trace_id = chrome_categorized_first_flow_events.trace_id
214          AND chrome_gestures.ts <= chrome_categorized_first_flow_events.ts
215          AND chrome_gestures.ts + chrome_gestures.dur >= chrome_categorized_first_flow_events.ts
216          + chrome_categorized_first_flow_events.dur
217      )
218  END AS window_start_id,
219  blocked_gesture,
220  upid
221FROM
222  chrome_categorized_first_flow_events;