• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--
2-- Copyright 2021 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-- While handling a InputLatency::{{gesture_update}} event a sequence of Flows
17-- define the critical path from Beginning to End. This metric breaks down the
18-- flows for the same InputLatency::{{gesture_update}} event.
19--
20-- WARNING: This metric should not be used as a source of truth. It is under
21--          active development and the values & meaning might change without
22--          notice.
23
24-- Provides the {{prefix}}_jank table which gives us all the {{gesture_update}}
25-- events we care about and labels them janky or not.
26SELECT RUN_METRIC('chrome/{{prefix}}_jank.sql');
27
28-- We get all latency_info that have valid trace_ids, And we make a synthetic
29-- one for the beginning of each {{gesture_update}} event so we can track the
30-- time between receiving the input and being converted into a gesture.
31--
32-- flows with a trace_id of -1 are incomplete and are difficult to reason about
33-- (especially if {{gesture_update}} flows end up getting -1). so ignore them
34-- for this table.
35DROP VIEW IF EXISTS {{prefix}}_latency_info_flow_step_and_ancestors;
36CREATE VIEW {{prefix}}_latency_info_flow_step_and_ancestors AS
37  SELECT
38    *
39  FROM (
40    SELECT
41      slice.name,
42      slice.id,
43      slice.ts,
44      slice.dur,
45      slice.track_id,
46      EXTRACT_ARG(slice.arg_set_id, 'chrome_latency_info.trace_id') AS trace_id,
47      EXTRACT_ARG(slice.arg_set_id, 'chrome_latency_info.step') AS step,
48      COALESCE(ancestor_zero.name, slice.name) AS ancestor_name_zero,
49      COALESCE(ancestor_zero.id, slice.id) AS ancestor_id_zero,
50      COALESCE(ancestor_zero.ts, slice.ts) AS ancestor_ts_zero,
51      COALESCE(ancestor_zero.dur, slice.dur) AS ancestor_dur_zero,
52      COALESCE(ancestor_one.name, slice.name) AS ancestor_name_one,
53      COALESCE(ancestor_one.id, slice.id) AS ancestor_id_one,
54      COALESCE(ancestor_one.ts, slice.ts) AS ancestor_ts_one,
55      COALESCE(ancestor_one.dur, slice.dur) AS ancestor_dur_one
56    FROM
57      slice LEFT JOIN
58      ancestor_slice(slice.id) AS ancestor_zero
59          ON ancestor_zero.depth = 0 LEFT JOIN
60      ancestor_slice(slice.id) AS ancestor_one ON ancestor_one.depth = 1
61    WHERE
62      slice.name = 'LatencyInfo.Flow' AND
63      EXTRACT_ARG(slice.arg_set_id, 'chrome_latency_info.trace_id') != -1
64  ) flow JOIN (
65      SELECT
66        id AS gesture_slice_id,
67        ts AS gesture_ts,
68        dur AS {{prefix}}_dur,
69        track_id AS gesture_track_id,
70        trace_id AS {{prefix}}_trace_id,
71        jank,
72        {{id_field}},
73        avg_vsync_interval
74      FROM {{prefix}}_jank
75  ) gesture ON
76    flow.trace_id = gesture.{{prefix}}_trace_id
77  UNION ALL
78  SELECT
79    'InputLatency::{{gesture_update}}' AS name,
80    id,
81    ts,
82    dur,
83    track_id,
84    trace_id,
85    'AsyncBegin' AS step,
86    'InputLatency::{{gesture_update}}' AS ancestor_name_zero,
87    id AS ancestor_id_zero,
88    ts AS ancestor_ts_zero,
89    0 AS ancestor_dur_zero,
90    'InputLatency::{{gesture_update}}' AS ancestor_name_one,
91    id AS ancestor_id_one,
92    ts AS ancestor_ts_one,
93    0 AS ancestor_dur_one,
94    id AS gesture_slice_id,
95    ts AS gesture_ts,
96    dur AS {{prefix}}_dur,
97    track_id AS gesture_track_id,
98    trace_id AS {{prefix}}_trace_id,
99    jank,
100    {{id_field}},
101    avg_vsync_interval
102  FROM {{prefix}}_jank
103  ORDER BY {{id_field}} ASC, trace_id ASC, ts ASC;
104
105-- See b/184134310, but "ThreadController active" spans multiple tasks and when
106-- the top level parent is this event we should use the second event instead.
107DROP VIEW IF EXISTS {{prefix}}_latency_info_flow_step;
108CREATE VIEW {{prefix}}_latency_info_flow_step AS
109  SELECT
110    *,
111    CASE WHEN ancestor_name_zero != "ThreadController active" THEN
112      ancestor_name_zero ELSE ancestor_name_one END AS ancestor_name,
113    CASE WHEN ancestor_name_zero != "ThreadController active" THEN
114      ancestor_id_zero ELSE ancestor_id_one END AS ancestor_id,
115    CASE WHEN ancestor_name_zero != "ThreadController active" THEN
116      ancestor_ts_zero ELSE ancestor_ts_one END AS ancestor_ts,
117    CASE WHEN ancestor_name_zero != "ThreadController active" THEN
118      ancestor_dur_zero ELSE ancestor_dur_one END AS ancestor_dur
119  FROM {{prefix}}_latency_info_flow_step_and_ancestors;
120
121-- This is a heuristic to figure out which flow event properly joins this
122-- {{gesture_update}}. This heuristic is only needed in traces before we added
123-- {{id_field}}.
124--
125-- We select the first |ts| from a flow event after its corresponding
126-- {{gesture_update}} has ended. This allows us to use this |ts| to contain all
127-- flow events from the start of a particular gesture_slice_id (the slice id of
128-- the async event) to that |ts|.
129--
130-- The reason for this is if these flow events share the same trace_id which can
131-- occur if multiple chrome browsers are in the trace (webview & chrome for
132-- example). We would normally add flow events from different gestures, but by
133-- limiting by the {{gesture_update}} end we can prevent incorrect duplication.
134-- This breaks of course if the same trace_id happens at the exact same time in
135-- both browsers but this is hopefully unlikely.
136DROP VIEW IF EXISTS {{prefix}}_max_latency_info_ts_per_trace_id;
137CREATE VIEW {{prefix}}_max_latency_info_ts_per_trace_id AS
138  SELECT
139    gesture_slice_id,
140    MIN(ts) AS max_flow_ts
141  FROM {{prefix}}_latency_info_flow_step
142  WHERE
143    trace_id = {{prefix}}_trace_id AND
144    ts > gesture_ts + {{prefix}}_dur
145  GROUP BY gesture_slice_id;
146
147-- As described by the comments about this uses the heuristic to remove any flow
148-- events that aren't contained within the |max_flow_ts| and the beginning of
149-- the {{gesture_update}}. This prevents other processes that share the same
150-- trace_id from inserting events in the middle.
151--
152-- Note: Must be a TABLE because it uses a window function which can behave
153--       strangely in views.
154DROP TABLE IF EXISTS {{prefix}}_latency_info_flow_step_filtered;
155CREATE TABLE {{prefix}}_latency_info_flow_step_filtered AS
156  SELECT
157    ROW_NUMBER() OVER (ORDER BY
158      flow.{{id_field}} ASC, trace_id ASC, ts ASC) AS row_number,
159    *
160  FROM
161    {{prefix}}_latency_info_flow_step flow JOIN
162    {{prefix}}_max_latency_info_ts_per_trace_id max_flow on
163    max_flow.gesture_slice_id = flow.gesture_slice_id
164  WHERE
165    ts >= gesture_ts AND
166    ts <= max_flow_ts
167  ORDER BY flow.{{id_field}} ASC, flow.trace_id ASC, flow.ts ASC;
168
169-- Take all the LatencyInfo.Flow events and within a |trace_id| join it with the
170-- previous and nextflows. Some events are 'Unknown' when they don't have a step
171-- but occur in the middle of the critical path. Most of these are errors though
172-- and we've weeded I think all of them out (citation needed).
173--
174-- Note: Must be a TABLE because it uses a window function which can behave
175--       strangely in views.
176DROP TABLE IF EXISTS {{prefix}}_latency_info_flow_null_step_removed;
177CREATE TABLE {{prefix}}_latency_info_flow_null_step_removed AS
178  SELECT
179    ROW_NUMBER() OVER (ORDER BY
180      curr.{{id_field}} ASC, curr.trace_id ASC, curr.ts ASC
181    ) AS row_number,
182    curr.id,
183    curr.ts,
184    curr.dur,
185    curr.track_id,
186    curr.trace_id,
187    curr.{{id_field}},
188    curr.avg_vsync_interval,
189    curr.gesture_slice_id,
190    curr.gesture_ts,
191    curr.{{prefix}}_dur,
192    curr.gesture_track_id,
193    curr.jank,
194    curr.ancestor_id,
195    curr.ancestor_ts,
196    curr.ancestor_dur,
197    curr.ancestor_ts + curr.ancestor_dur AS ancestor_end,
198    CASE WHEN curr.step IS NULL THEN
199      CASE WHEN
200          prev.{{id_field}} != curr.{{id_field}} OR
201          prev.trace_id != curr.trace_id OR
202          prev.trace_id IS NULL OR
203          prev.step = 'AsyncBegin' THEN
204        'Begin'
205      ELSE
206        CASE WHEN
207            next.{{id_field}} != curr.{{id_field}} OR
208            next.trace_id != curr.trace_id OR
209            next.trace_id IS NULL THEN
210          'End'
211        ELSE
212         'Unknown'
213        END
214      END
215    ELSE curr.step END AS step
216  FROM
217    {{prefix}}_latency_info_flow_step_filtered curr LEFT JOIN
218    {{prefix}}_latency_info_flow_step_filtered prev ON
219      curr.row_number - 1 = prev.row_number LEFT JOIN
220    {{prefix}}_latency_info_flow_step_filtered next ON
221      curr.row_number + 1 = next.row_number
222  ORDER BY curr.{{id_field}} ASC, curr.trace_id ASC, curr.ts ASC;
223
224-- Now that we've got the steps all named properly we want to join them with the
225-- next step so we can compute the difference between the end of the current
226-- step and the beginning of the next step.
227DROP VIEW IF EXISTS {{prefix}}_flow_event;
228CREATE VIEW {{prefix}}_flow_event AS
229  SELECT
230    curr.trace_id,
231    curr.id,
232    curr.ts,
233    curr.dur,
234    curr.track_id,
235    curr.{{id_field}},
236    curr.avg_vsync_interval,
237    curr.gesture_slice_id AS {{prefix}}_slice_id,
238    curr.gesture_ts AS {{prefix}}_ts,
239    curr.{{prefix}}_dur AS {{prefix}}_dur,
240    curr.gesture_track_id AS {{prefix}}_track_id,
241    curr.jank,
242    curr.step,
243    curr.ancestor_id,
244    curr.ancestor_ts,
245    curr.ancestor_dur,
246    curr.ancestor_end,
247    next.id as next_id,
248    next.ts AS next_ts,
249    next.dur AS next_dur,
250    next.track_id AS next_track_id,
251    next.trace_id AS next_trace_id,
252    next.step AS next_step,
253    CASE WHEN next.trace_id = curr.trace_id THEN
254      next.ancestor_ts
255    ELSE
256      NULL
257    END AS maybe_next_ancestor_ts
258  FROM
259    {{prefix}}_latency_info_flow_null_step_removed curr LEFT JOIN
260    {{prefix}}_latency_info_flow_null_step_removed next ON
261    curr.row_number + 1 = next.row_number
262  ORDER BY curr.{{id_field}}, curr.trace_id, curr.ts;
263