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