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 RUN_METRIC('chrome/jank_utilities.sql'); 21SELECT RUN_METRIC( 22 'chrome/chrome_tasks_template.sql', 23 'slice_table_name', 'slice', 24 'function_prefix', '' 25); 26 27SELECT CREATE_FUNCTION( 28 'IS_LONG_CHOREOGRAPHER_TASK(dur LONG)', 29 'BOOL', 30 'SELECT $dur >= 4 * 1e6' 31); 32 33-- Note that not all slices will be mojo slices; filter on interface_name IS 34-- NOT NULL for mojo slices specifically. 35DROP TABLE IF EXISTS long_tasks_extracted_slices; 36CREATE TABLE long_tasks_extracted_slices AS 37SELECT * FROM SELECT_LONG_TASK_SLICES(/*name*/'LongTaskTracker'); 38 39-- Create |long_tasks_internal_tbl| table, which gathers all of the 40-- information needed to produce the full name + metadata required 41-- for LongTaskTracker slices. Unlike toplevel slices, which will 42-- have nested descendants, LongTaskTracker slices will store all of 43-- the relevant information within the single slice. 44DROP TABLE IF EXISTS long_tasks_internal_tbl; 45CREATE TABLE long_tasks_internal_tbl AS 46WITH 47 raw_extracted_values AS ( 48 SELECT 49 mojo.id, 50 mojo.interface_name, 51 mojo.ipc_hash, 52 mojo.message_type, 53 EXTRACT_ARG(s.arg_set_id, 'task.posted_from.file_name') AS posted_from_file_name, 54 EXTRACT_ARG(s.arg_set_id, 'task.posted_from.function_name') AS posted_from_function_name 55 FROM long_tasks_extracted_slices mojo 56 JOIN slice s ON mojo.id = s.id 57 ) 58SELECT 59 id, 60 CASE 61 WHEN interface_name IS NOT NULL 62 THEN printf('%s %s (hash=%d)', interface_name, message_type, ipc_hash) 63 ELSE 64 FORMAT_SCHEDULER_TASK_NAME(posted_from_file_name || ':' || posted_from_function_name) 65 END AS full_name, 66 interface_name IS NOT NULL AS is_mojo 67FROM raw_extracted_values; 68 69-- Attach java views to its associated LongTaskTracker slice, as they 70-- will be on different tracks. This follows the same logic as creating 71-- chrome_slices_with_java_views_internal, differing only in how a 72-- descendent is calculated. 73DROP VIEW IF EXISTS long_task_slices_with_java_views; 74CREATE VIEW long_task_slices_with_java_views AS 75WITH 76 -- Select UI thread BeginMainFrames frames. 77 root_slices AS ( 78 SELECT * 79 FROM SELECT_BEGIN_MAIN_FRAME_JAVA_SLICES('LongTaskTracker') 80 UNION ALL 81 SELECT * FROM chrome_choreographer_tasks WHERE IS_LONG_CHOREOGRAPHER_TASK(dur) 82 ), 83 -- Intermediate step to allow us to sort java view names. 84 root_slice_and_java_view_not_grouped AS ( 85 SELECT 86 s1.id, s1.kind, s2.name AS java_view_name 87 FROM root_slices s1 88 JOIN chrome_java_views_internal s2 89 ON ( 90 s1.ts < s2.ts AND s1.ts + s1.dur > s2.ts + s2.dur) 91 ) 92SELECT 93 s1.id, 94 s1.kind, 95 GROUP_CONCAT(DISTINCT s2.java_view_name) AS java_views 96FROM root_slices s1 97LEFT JOIN root_slice_and_java_view_not_grouped s2 98 USING (id) 99GROUP BY s1.id; 100 101DROP VIEW IF EXISTS chrome_long_tasks_internal; 102CREATE VIEW chrome_long_tasks_internal AS 103WITH -- Generate full names for tasks with java views. 104 java_views_tasks AS ( 105 SELECT 106 printf('%s(java_views=%s)', kind, java_views) as full_name, 107 GET_JAVA_VIEWS_TASK_TYPE(kind) AS task_type, 108 id 109 FROM long_task_slices_with_java_views 110 WHERE kind = "SingleThreadProxy::BeginMainFrame" 111 ), 112 scheduler_tasks_with_mojo AS ( 113 SELECT 114 full_name, 115 'mojo' as task_type, 116 id 117 FROM long_tasks_internal_tbl 118 WHERE is_mojo 119 ), 120 navigation_tasks AS ( 121 SELECT 122 -- NOTE: unless Navigation category is enabled and recorded on the same 123 -- track as the LongTaskTracker slice, frame type will always be unknown. 124 printf('%s (%s)', 125 HUMAN_READABLE_NAVIGATION_TASK_NAME(full_name), 126 IFNULL(EXTRACT_FRAME_TYPE(id), 'unknown frame type')) AS full_name, 127 'navigation_task' AS task_type, 128 id 129 FROM scheduler_tasks_with_mojo 130 WHERE HUMAN_READABLE_NAVIGATION_TASK_NAME(full_name) IS NOT NULL 131 ) 132SELECT 133 COALESCE(s4.full_name, s3.full_name, s2.full_name, s1.full_name) AS full_name, 134 COALESCE(s4.task_type, s3.task_type, s2.task_type, 'scheduler') as task_type, 135 s1.id as id 136FROM long_tasks_internal_tbl s1 137LEFT JOIN scheduler_tasks_with_mojo s2 ON s2.id = s1.id 138LEFT JOIN java_views_tasks s3 ON s3.id = s1.id 139LEFT JOIN navigation_tasks s4 ON s4.id = s1.id 140UNION ALL 141-- Choreographer slices won't necessarily be associated with an overlying 142-- LongTaskTracker slice, so join them separately. 143SELECT 144 printf('%s(java_views=%s)', kind, java_views) as full_name, 145 GET_JAVA_VIEWS_TASK_TYPE(kind) AS task_type, 146 id 147FROM long_task_slices_with_java_views 148WHERE kind = "Choreographer"; 149 150DROP VIEW IF EXISTS chrome_long_tasks; 151CREATE VIEW chrome_long_tasks AS 152SELECT 153 full_name, 154 task_type, 155 thread.name AS thread_name, 156 thread.utid, 157 process.name AS process_name, 158 thread.upid, 159 ts.* 160FROM chrome_long_tasks_internal cti 161JOIN slice ts USING (id) 162JOIN thread_track tt ON ts.track_id = tt.id 163JOIN thread USING (utid) 164JOIN process USING (upid);