• 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
20SELECT CREATE_FUNCTION(
21  -- Given a slice id of an event, get timestamp of the most recent flow
22  -- event on the Chrome IO thread that preceded this slice.
23  -- This helps us identify the last flow event on the IO thread before
24  -- letting the browser main thread be aware of input.
25  -- We need this for flings (generated by the GPU process) and blocked
26  -- touch moves that are forwarded from the renderer.
27  '{{function_prefix}}PRECEDING_IO_THREAD_EVENT_FLOW_ID(id LONG)',
28  -- Returning the slice id for the flow_out on the chrome IO thread.
29  'LONG',
30  'SELECT MAX(flow.slice_out) AS id
31  FROM
32    PRECEDING_FLOW(($id)) flow');
33
34SELECT CREATE_FUNCTION(
35  '{{function_prefix}}GET_MOJO_PARENT_INTERFACE_TAG(id LONG)',
36  'STRING',
37  'SELECT
38    interface_name
39    FROM
40    (SELECT MAX(mojo.id),
41    interface_name
42      FROM ((SELECT id FROM ancestor_slice(($id))
43             UNION
44             SELECT slice.id as id FROM PRECEDING_FLOW(($id)) flow
45        	 JOIN slice ON flow.slice_out = slice.id) candidates
46    JOIN chrome_mojo_slices_tbl mojo
47    ON mojo.id = candidates.id
48      OR (SELECT COUNT() FROM ancestor_slice(candidates.id) parents
49      WHERE parents.id = mojo.id) > 0))'
50);
51
52SELECT CREATE_FUNCTION(
53  '{{function_prefix}}GET_SCROLL_TYPE(blocked_gesture BOOL, mojo_interface_tag STRING)',
54  'STRING',
55  'SELECT
56    CASE WHEN ($blocked_gesture)
57    THEN (SELECT
58            CASE WHEN ($mojo_interface_tag) = "viz.mojom.BeginFrameObserver"
59            THEN "fling"
60            WHEN ($mojo_interface_tag) = "blink.mojom.WidgetInputHandler"
61            THEN "blocking_touch_move"
62            ELSE "unknown" END)
63    ELSE "regular" END AS delay_type');
64
65-- Get all InputLatency::GestureScrollUpdate events, to use their
66-- flows later on to decide how much time we waited from queueing the event
67-- until we started processing it.
68DROP VIEW IF EXISTS chrome_valid_gesture_updates;
69CREATE VIEW chrome_valid_gesture_updates
70AS
71SELECT
72  name,
73  EXTRACT_ARG(
74    arg_set_id, 'chrome_latency_info.trace_id') AS trace_id,
75  ts,
76  id,
77  dur
78FROM
79  {{slice_table_name}}
80WHERE
81  name = 'InputLatency::GestureScrollUpdate'
82  AND EXTRACT_ARG(
83    arg_set_id, "chrome_latency_info.is_coalesced")
84  = 0
85ORDER BY trace_id;
86
87-- Get all chrome_latency_info_for_gesture_slices where trace_ids are not -1,
88-- as those are faulty, then join with the GestureScrollUpdate table to get
89-- only slices associated with update events.
90DROP VIEW IF EXISTS chrome_flow_slices_for_gestures;
91CREATE VIEW chrome_flow_slices_for_gestures
92AS
93SELECT
94  s.ts,
95  EXTRACT_ARG(
96    s.arg_set_id, 'chrome_latency_info.trace_id') AS trace_id,
97  s.arg_set_id,
98  s.id,
99  s.track_id,
100  s.dur
101FROM
102  {{slice_table_name}} s
103JOIN chrome_valid_gesture_updates
104  ON
105    chrome_valid_gesture_updates.trace_id = EXTRACT_ARG(
106      s.arg_set_id, 'chrome_latency_info.trace_id')
107    AND s.ts >= chrome_valid_gesture_updates.ts
108    AND s.ts + s.dur
109    <= chrome_valid_gesture_updates.ts + chrome_valid_gesture_updates.dur
110WHERE
111  s.name = 'LatencyInfo.Flow'
112  AND trace_id != -1;
113
114-- Tie chrome_latency_info_for_gesture_slices slices to processes to avoid
115-- calculating intervals per process as multiple chrome instances can be up
116-- on system traces.
117DROP VIEW IF EXISTS chrome_flow_slices_for_gestures_tied_process;
118CREATE VIEW chrome_flow_slices_for_gestures_tied_process
119AS
120SELECT
121  ts,
122  trace_id,
123  arg_set_id,
124  chrome_flow_slices_for_gestures.id,
125  dur,
126  thread.upid
127FROM
128  chrome_flow_slices_for_gestures
129JOIN thread_track ON chrome_flow_slices_for_gestures.track_id = thread_track.id
130JOIN thread ON thread_track.utid = thread.utid
131  AND is_main_thread;
132
133-- Index all flows per trace_id, to get the first flow event per input
134-- GestureScrollUpdate, this will later be used to calculate the time
135-- from receiving input to the first flow event appearing.
136DROP TABLE IF EXISTS chrome_indexed_flow_per_gesture;
137CREATE TABLE chrome_indexed_flow_per_gesture
138AS
139SELECT
140  ts,
141  trace_id,
142  arg_set_id,
143  id,
144  ROW_NUMBER()
145  OVER (
146    PARTITION BY trace_id, upid
147    ORDER BY
148      ts ASC
149  ) AS flow_order,
150  upid,
151  dur
152FROM
153  chrome_flow_slices_for_gestures_tied_process;
154
155-- TODO(b/235067134) all the previous views including this one are
156-- reimplementations of gesture_jank.sql with less restrictions, let's
157-- merge both of them into one script or make this script a base for the
158-- other.
159-- Get the first flow event per gesture.
160DROP VIEW IF EXISTS chrome_first_flow_per_gesture;
161CREATE VIEW chrome_first_flow_per_gesture
162AS
163SELECT
164  *
165FROM
166  chrome_indexed_flow_per_gesture
167WHERE
168  flow_order = 1;
169
170
171
172-- The decision for processing on the browser main thread for a frame can be
173-- instant, or delayed by the renderer in cases where the renderer needs to
174-- decide whether the touch move is an ScrollUpdate or not, and in other cases
175-- for flings, the scroll itself will be generated by the viz compositor thread
176-- on each vsync interval.
177DROP VIEW IF EXISTS chrome_categorized_first_flow_events;
178CREATE VIEW chrome_categorized_first_flow_events
179AS
180SELECT
181  *,
182  NOT COALESCE((
183    SELECT
184      COUNT()
185    FROM
186      ancestor_slice(chrome_first_flow_per_gesture.id) ancestor_slices
187    WHERE
188      -- sendTouchEvent means the event wasn't delayed by the renderer
189      -- and is not a fling generated by the viz compositor thread(GPU process).
190      ancestor_slices.name = "sendTouchEvent"
191  )
192  = 1, FALSE) AS blocked_gesture
193FROM
194  chrome_first_flow_per_gesture;
195
196-- For cases where it's not blocked, get the timestamp of input as the
197-- beginning of time we theoretically could have started processing
198-- the input event, which is the timestamp of the GestureScrollUpdate event
199-- otherwise fall back to the top level slice to check the timestamp
200-- of it's calling flow
201DROP VIEW IF EXISTS chrome_input_to_browser_interval_slice_ids;
202CREATE VIEW chrome_input_to_browser_interval_slice_ids
203AS
204SELECT
205  chrome_categorized_first_flow_events.id AS window_end_id,
206  chrome_categorized_first_flow_events.ts AS window_end_ts,
207  -- If blocked, get the flow_out slice's timestamp as our beginning
208  -- given that the flow_in is coming to our toplevel parent task
209  CASE
210    WHEN blocked_gesture
211      THEN
212      {{function_prefix}}PRECEDING_IO_THREAD_EVENT_FLOW_ID(chrome_categorized_first_flow_events.id)
213    ELSE
214      -- TODO(b/236590359): is selecting here better or join and ordering by?
215      -- Let's benchmark and modify accordingly.
216      (
217        SELECT
218          chrome_gestures.id
219        FROM
220          chrome_valid_gesture_updates chrome_gestures
221        WHERE
222          chrome_gestures.trace_id = chrome_categorized_first_flow_events.trace_id
223          AND chrome_gestures.ts <= chrome_categorized_first_flow_events.ts
224          AND chrome_gestures.ts + chrome_gestures.dur >= chrome_categorized_first_flow_events.ts
225          + chrome_categorized_first_flow_events.dur
226      )
227  END AS window_start_id,
228  blocked_gesture,
229  upid
230FROM
231  chrome_categorized_first_flow_events;