• 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
37SELECT
38  *
39FROM (
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'
63      AND 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
77UNION ALL
78SELECT
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
102FROM {{prefix}}_jank
103ORDER 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
109SELECT
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
119FROM {{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
138SELECT
139  gesture_slice_id,
140  MIN(ts) AS max_flow_ts
141FROM {{prefix}}_latency_info_flow_step
142WHERE
143  trace_id = {{prefix}}_trace_id
144  AND ts > gesture_ts + {{prefix}}_dur
145GROUP 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
156SELECT
157  ROW_NUMBER() OVER (ORDER BY
158      flow.{{id_field}} ASC, trace_id ASC, ts ASC) AS row_number,
159  *
160FROM
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
164WHERE
165  ts >= gesture_ts
166  AND ts <= max_flow_ts
167ORDER 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
178SELECT
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    COALESCE(
199      curr.step,
200      CASE WHEN
201          prev.{{id_field}} != curr.{{id_field}}
202          OR prev.trace_id != curr.trace_id
203          OR prev.trace_id IS NULL
204          OR prev.step = 'AsyncBegin' THEN
205        'Begin'
206      ELSE
207        CASE WHEN
208          next.{{id_field}} != curr.{{id_field}}
209          OR next.trace_id != curr.trace_id
210          OR next.trace_id IS NULL THEN
211          'End'
212          ELSE
213            'Unknown'
214        END
215      END
216    ) AS step
217  FROM
218    {{prefix}}_latency_info_flow_step_filtered curr LEFT JOIN
219    {{prefix}}_latency_info_flow_step_filtered prev ON
220      curr.row_number - 1 = prev.row_number LEFT JOIN
221    {{prefix}}_latency_info_flow_step_filtered next ON
222      curr.row_number + 1 = next.row_number
223  ORDER BY curr.{{id_field}} ASC, curr.trace_id ASC, curr.ts ASC;
224
225-- Now that we've got the steps all named properly we want to join them with the
226-- next step so we can compute the difference between the end of the current
227-- step and the beginning of the next step.
228DROP VIEW IF EXISTS {{prefix}}_flow_event;
229CREATE VIEW {{prefix}}_flow_event AS
230SELECT
231  curr.trace_id,
232  curr.id,
233  curr.ts,
234  curr.dur,
235  curr.track_id,
236  curr.{{id_field}},
237  curr.avg_vsync_interval,
238  curr.gesture_slice_id AS {{prefix}}_slice_id,
239  curr.gesture_ts AS {{prefix}}_ts,
240  curr.{{prefix}}_dur AS {{prefix}}_dur,
241  curr.gesture_track_id AS {{prefix}}_track_id,
242  curr.jank,
243  curr.step,
244  curr.ancestor_id,
245  curr.ancestor_ts,
246  curr.ancestor_dur,
247  curr.ancestor_end,
248  next.id AS next_id,
249  next.ts AS next_ts,
250  next.dur AS next_dur,
251  next.track_id AS next_track_id,
252  next.trace_id AS next_trace_id,
253  next.step AS next_step,
254  CASE WHEN next.trace_id = curr.trace_id THEN
255      next.ancestor_ts
256    ELSE
257      NULL
258  END AS maybe_next_ancestor_ts
259FROM
260  {{prefix}}_latency_info_flow_null_step_removed curr LEFT JOIN
261  {{prefix}}_latency_info_flow_null_step_removed next ON
262    curr.row_number + 1 = next.row_number
263ORDER BY curr.{{id_field}}, curr.trace_id, curr.ts;
264