1--
2-- Copyright 2020 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-- Needed for the scroll_jank table to tell which updates were janky.
17SELECT RUN_METRIC('chrome/scroll_jank.sql');
18
19--------------------------------------------------------------------------------
20-- Get all the track ids relevant to the critical path.
21--------------------------------------------------------------------------------
22
23-- Grab the track of the browser. sendTouchEvent is a Java category event which
24-- only occurs on the browser. This saves us the trouble of dealing with all the
25-- different possible names of the browser (when including system tracing).
26DROP VIEW IF EXISTS browser_main_track_id;
27CREATE PERFETTO VIEW browser_main_track_id AS
28SELECT
29  track_id AS id
30FROM slice
31WHERE
32  name = "sendTouchEvent"
33LIMIT 1;
34
35DROP VIEW IF EXISTS viz_compositor_track_id;
36CREATE PERFETTO VIEW viz_compositor_track_id AS
37SELECT
38  id
39FROM thread_track
40WHERE
41  utid = (
42    SELECT
43      utid
44    FROM thread
45    WHERE
46      name = "VizCompositorThread"
47  )
48LIMIT 1;
49
50-- Grab the track of the GPU. gpu/command_buffer is a toplevel category event
51-- which only occurs on the gpu main. This saves us the trouble of dealing with
52-- all the different possible names of the GPU process (when including system
53-- tracing).
54DROP VIEW IF EXISTS gpu_main_track_id;
55CREATE PERFETTO VIEW gpu_main_track_id AS
56SELECT
57  track_id AS id
58FROM slice
59WHERE
60  EXTRACT_ARG(arg_set_id, "task.posted_from.file_name") GLOB
61  "*gpu/command_buffer/service/scheduler.cc"
62LIMIT 1;
63
64-- TODO(nuskos): Determine a good way to get all the renderer track_ids (each
65--               scroll will have a single renderer main and a single renderer
66--               compositor however different scroll updates could have
67--               DIFFERENT renderers so bit tricky). Ignore this complexity for
68--               now until we have a single task we want to blame jank on.
69
70--------------------------------------------------------------------------------
71-- Grab the last LatencyInfo.Flow for each trace_id on the browser main.
72--------------------------------------------------------------------------------
73DROP VIEW IF EXISTS browser_flows;
74CREATE PERFETTO VIEW browser_flows AS
75SELECT
76  EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id,
77  EXTRACT_ARG(arg_set_id, "chrome_latency_info.step") AS flow_step,
78  track_id,
79  max(ts) AS ts
80FROM slice
81WHERE
82  track_id = (
83    SELECT id FROM browser_main_track_id
84  )
85  AND name = "LatencyInfo.Flow"
86GROUP BY trace_id;
87
88-- Grab the last LatencyInfo.Flow for each trace_id on the VizCompositor.
89DROP VIEW IF EXISTS viz_flows;
90CREATE PERFETTO VIEW viz_flows AS
91SELECT
92  EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id,
93  EXTRACT_ARG(arg_set_id, "chrome_latency_info.step") AS flow_step,
94  track_id,
95  max(ts) AS ts
96FROM slice
97WHERE
98  track_id = (
99    SELECT id FROM viz_compositor_track_id
100  )
101  AND name = "LatencyInfo.Flow"
102GROUP BY trace_id;
103
104-- Grab the last LatencyInfo.Flow for each trace_id on the GPU main.
105DROP VIEW IF EXISTS gpu_flows;
106CREATE PERFETTO VIEW gpu_flows AS
107SELECT
108  EXTRACT_ARG(arg_set_id, "chrome_latency_info.trace_id") AS trace_id,
109  EXTRACT_ARG(arg_set_id, "chrome_latency_info.step") AS flow_step,
110  track_id,
111  max(ts) AS ts
112FROM slice
113WHERE
114  track_id = (
115    SELECT id FROM gpu_main_track_id
116  )
117  AND name = "LatencyInfo.Flow"
118GROUP BY trace_id;
119
120--------------------------------------------------------------------------------
121-- Finally join the relevant tracks/flows to the individual scrolls.
122--------------------------------------------------------------------------------
123
124-- Keeping only the GestureScrollUpdates join the maximum flows with their
125-- associated scrolls. We only keep non-coalesced scrolls.
126DROP VIEW IF EXISTS scroll_with_browser_gpu_and_viz_flows;
127CREATE PERFETTO VIEW scroll_with_browser_gpu_and_viz_flows AS
128SELECT
129  scroll.trace_id,
130  scroll.scroll_id,
131  scroll.ts,
132  scroll.dur,
133  scroll.track_id,
134  browser_flows.ts AS browser_flow_ts,
135  browser_flows.flow_step AS browser_flow_step,
136  browser_flows.track_id AS browser_track_id,
137  viz_flows.ts AS viz_flow_ts,
138  viz_flows.flow_step AS viz_flow_step,
139  viz_flows.track_id AS viz_track_id,
140  gpu_flows.ts AS gpu_flow_ts,
141  gpu_flows.flow_step AS gpu_flow_step,
142  gpu_flows.track_id AS gpu_track_id
143FROM (
144  SELECT
145    trace_id,
146    id AS scroll_id,
147    ts,
148    dur,
149    track_id
150  FROM scroll_jank
151) scroll JOIN browser_flows ON
152  scroll.trace_id = browser_flows.trace_id
153JOIN viz_flows ON viz_flows.trace_id = scroll.trace_id
154JOIN gpu_flows ON gpu_flows.trace_id = scroll.trace_id;
155
156--------------------------------------------------------------------------------
157-- Below we determine individual causes of blocking tasks.
158--------------------------------------------------------------------------------
159
160--------------------------------------------------------------------------------
161-- Determine if a CopyOutputRequest blocked any important threads.
162--------------------------------------------------------------------------------
163
164-- These are the events that block the Browser Main or the VizCompositor thread.
165DROP VIEW IF EXISTS blocking_browser_gpu_and_viz_copies;
166CREATE PERFETTO VIEW blocking_browser_gpu_and_viz_copies AS
167SELECT
168  id,
169  ts,
170  dur,
171  track_id
172FROM slice
173WHERE
174  (
175    (
176      name = "viz.mojom.CopyOutputResultSender"
177      OR name = "GLRenderer::CopyDrawnRenderPass"
178    )
179    AND track_id = (SELECT id FROM browser_main_track_id)
180  ) OR (
181    EXTRACT_ARG(arg_set_id, "task.posted_from.file_name") GLOB
182    "*components/viz/common/frame_sinks/copy_output_request.cc"
183    AND track_id = (SELECT id FROM viz_compositor_track_id)
184  ) OR (
185    name = "SkiaOutputSurfaceImplOnGpu::CopyOutput"
186    AND track_id = (SELECT id FROM gpu_main_track_id)
187  );
188
189-- Determine based on the LatencyInfo.Flow timestamp and the copy task overlap
190-- if this scroll might have been delayed because of the copy.
191DROP VIEW IF EXISTS blocking_copy_tasks;
192CREATE PERFETTO VIEW blocking_copy_tasks AS
193SELECT
194  scroll.scroll_id,
195  scroll.trace_id,
196  copy.id,
197  copy.ts,
198  copy.dur,
199  copy.track_id,
200  CASE WHEN copy.track_id = scroll.browser_track_id THEN
201    COALESCE(copy.ts < scroll.browser_flow_ts, FALSE)
202    WHEN copy.track_id = scroll.viz_track_id THEN
203      COALESCE(copy.ts < scroll.viz_flow_ts, FALSE)
204    WHEN copy.track_id = scroll.gpu_track_id THEN
205      COALESCE(copy.ts < scroll.gpu_flow_ts, FALSE)
206    ELSE
207      FALSE
208  END AS blocked_by_copy
209FROM
210  scroll_with_browser_gpu_and_viz_flows scroll JOIN
211  blocking_browser_gpu_and_viz_copies copy ON
212    scroll.ts + scroll.dur >= copy.ts
213    AND copy.ts + copy.dur >= scroll.ts;
214
215-- Group by scroll so we can equally join one reply to the ScrollJankAndCauses
216-- view.
217DROP VIEW IF EXISTS screenshot_overlapping_scrolls;
218CREATE PERFETTO VIEW screenshot_overlapping_scrolls AS
219SELECT
220  scroll_id, trace_id, SUM(blocked_by_copy) > 0 AS blocked_by_copy_request
221FROM blocking_copy_tasks
222GROUP BY 1, 2;
223
224--------------------------------------------------------------------------------
225-- Check for blocking language_detection on the browser thread
226--------------------------------------------------------------------------------
227DROP VIEW IF EXISTS blocking_browser_language_detection;
228CREATE PERFETTO VIEW blocking_browser_language_detection AS
229SELECT
230  id,
231  ts,
232  dur,
233  track_id
234FROM slice
235WHERE
236  (
237    name = "language_detection.mojom.LanguageDetectionService"
238    AND track_id = (SELECT id FROM browser_main_track_id)
239  );
240
241DROP VIEW IF EXISTS blocking_language_detection_tasks;
242CREATE PERFETTO VIEW blocking_language_detection_tasks AS
243SELECT
244  scroll.scroll_id,
245  scroll.trace_id,
246  lang.id,
247  lang.ts,
248  lang.dur,
249  lang.track_id,
250  CASE WHEN lang.track_id = scroll.browser_track_id THEN
251    COALESCE(lang.ts < scroll.browser_flow_ts, FALSE)
252  END AS blocked_by_language_detection
253FROM
254  scroll_with_browser_gpu_and_viz_flows scroll JOIN
255  blocking_browser_language_detection lang ON
256    scroll.ts + scroll.dur >= lang.ts
257    AND lang.ts + lang.dur >= scroll.ts;
258
259DROP VIEW IF EXISTS language_detection_overlapping_scrolls;
260CREATE PERFETTO VIEW language_detection_overlapping_scrolls AS
261SELECT
262  scroll_id, trace_id,
263  SUM(blocked_by_language_detection) > 0 AS blocked_by_language_detection
264FROM blocking_language_detection_tasks
265GROUP BY 1, 2;
266
267--------------------------------------------------------------------------------
268-- Finally join the causes together for easy grouping.
269--------------------------------------------------------------------------------
270DROP VIEW IF EXISTS scroll_jank_cause_blocking_task;
271CREATE PERFETTO VIEW scroll_jank_cause_blocking_task AS
272SELECT
273  lang.scroll_id,
274  lang.blocked_by_language_detection,
275  copy.blocked_by_copy_request
276FROM
277  language_detection_overlapping_scrolls lang JOIN
278  screenshot_overlapping_scrolls copy ON copy.scroll_id = lang.scroll_id;
279