• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
20INCLUDE PERFETTO MODULE chrome.tasks;
21
22-- Extract mojo information for the long-task-tracking scenario for specific
23-- names. For example, LongTaskTracker slices may have associated IPC
24-- metadata, or InterestingTask slices for input may have associated IPC to
25-- determine whether the task is fling/etc.
26CREATE OR REPLACE PERFETTO FUNCTION select_long_task_slices(name STRING)
27RETURNS TABLE(
28  interface_name STRING,
29  ipc_hash INT,
30  message_type STRING,
31  id INT,
32  task_name STRING)
33AS
34WITH slices_with_mojo_data AS (
35  SELECT
36      EXTRACT_ARG(
37        arg_set_id,
38        "chrome_mojo_event_info.mojo_interface_tag"
39      ) AS interface_name,
40      EXTRACT_ARG(
41        arg_set_id,
42        "chrome_mojo_event_info.ipc_hash"
43      ) AS ipc_hash,
44      CASE
45        WHEN EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.is_reply") THEN "reply"
46        ELSE "message"
47      END AS message_type,
48      id
49  FROM slice
50  WHERE
51    category GLOB "*scheduler.long_tasks*"
52    AND name = $name
53)
54SELECT
55  *,
56  printf("%s %s(hash=%s)", interface_name, message_type, ipc_hash) as task_name
57FROM slices_with_mojo_data;
58
59CREATE OR REPLACE PERFETTO FUNCTION is_long_choreographer_task(dur LONG)
60RETURNS BOOL AS
61SELECT $dur >= 4 * 1e6;
62
63-- Note that not all slices will be mojo slices; filter on interface_name IS
64-- NOT NULL for mojo slices specifically.
65DROP TABLE IF EXISTS long_tasks_extracted_slices;
66CREATE PERFETTO TABLE long_tasks_extracted_slices AS
67SELECT * FROM SELECT_LONG_TASK_SLICES(/*name*/'LongTaskTracker');
68
69-- Create |long_tasks_internal_tbl| table, which gathers all of the
70-- information needed to produce the full name + metadata required
71-- for LongTaskTracker slices. Unlike toplevel slices, which will
72-- have nested descendants, LongTaskTracker slices will store all of
73-- the relevant information within the single slice.
74DROP TABLE IF EXISTS long_tasks_internal_tbl;
75CREATE PERFETTO TABLE long_tasks_internal_tbl AS
76WITH
77  raw_extracted_values AS (
78    SELECT
79      mojo.id,
80      mojo.interface_name,
81      mojo.ipc_hash,
82      mojo.message_type,
83      _get_posted_from(s.arg_set_id) as posted_from
84    FROM long_tasks_extracted_slices mojo
85    JOIN slice s ON mojo.id = s.id
86  )
87SELECT
88  id,
89  CASE
90    WHEN interface_name IS NOT NULL
91      THEN printf('%s %s (hash=%d)', interface_name, message_type, ipc_hash)
92    ELSE
93      _format_scheduler_task_name(posted_from)
94    END AS full_name,
95  interface_name IS NOT NULL AS is_mojo
96FROM raw_extracted_values;
97
98-- Attach java views to its associated LongTaskTracker slice, as they
99-- will be on different tracks. This follows the same logic as creating
100-- chrome_slices_with_java_views_internal, differing only in how a
101-- descendent is calculated.
102DROP VIEW IF EXISTS long_task_slices_with_java_views;
103CREATE PERFETTO VIEW long_task_slices_with_java_views AS
104WITH
105  -- Select UI thread BeginMainFrames frames.
106  root_slices AS (
107    SELECT *
108    FROM _SELECT_BEGIN_MAIN_FRAME_JAVA_SLICES('LongTaskTracker')
109    UNION ALL
110    SELECT id, "Choreographer" as kind, ts, dur, name
111    FROM slice
112    WHERE is_long_choreographer_task(dur)
113      AND name GLOB "Looper.dispatch: android.view.Choreographer$FrameHandler*"
114  ),
115  -- Intermediate step to allow us to sort java view names.
116  root_slice_and_java_view_not_grouped AS (
117    SELECT
118      s1.id, s1.kind, s2.name AS java_view_name
119    FROM root_slices s1
120    JOIN _chrome_java_views s2
121      ON (
122        s1.ts < s2.ts AND s1.ts + s1.dur > s2.ts + s2.dur)
123  )
124SELECT
125  s1.id,
126  s1.kind,
127  GROUP_CONCAT(DISTINCT s2.java_view_name) AS java_views
128FROM root_slices s1
129LEFT JOIN root_slice_and_java_view_not_grouped s2
130  USING (id)
131GROUP BY s1.id;
132
133DROP VIEW IF EXISTS chrome_long_tasks_internal;
134CREATE PERFETTO VIEW chrome_long_tasks_internal AS
135WITH -- Generate full names for tasks with java views.
136  java_views_tasks AS (
137    SELECT
138      printf('%s(java_views=%s)', kind, java_views) as full_name,
139      _get_java_views_task_type(kind) AS task_type,
140      id
141    FROM long_task_slices_with_java_views
142    WHERE kind = "SingleThreadProxy::BeginMainFrame"
143  ),
144  scheduler_tasks_with_mojo AS (
145    SELECT
146      full_name,
147      'mojo' as task_type,
148      id
149    FROM long_tasks_internal_tbl
150    WHERE is_mojo
151  ),
152  navigation_tasks AS (
153    SELECT
154      -- NOTE: unless Navigation category is enabled and recorded on the same
155      -- track as the LongTaskTracker slice, frame type will always be unknown.
156      printf('%s (%s)',
157        _human_readable_navigation_task_name(full_name),
158        IFNULL(_extract_frame_type(id), 'unknown frame type')) AS full_name,
159      'navigation_task' AS task_type,
160      id
161    FROM scheduler_tasks_with_mojo
162    WHERE _human_readable_navigation_task_name(full_name) IS NOT NULL
163  )
164SELECT
165  COALESCE(s4.full_name, s3.full_name, s2.full_name, s1.full_name) AS full_name,
166  COALESCE(s4.task_type, s3.task_type, s2.task_type, 'scheduler') as task_type,
167  s1.id as id
168FROM long_tasks_internal_tbl s1
169LEFT JOIN scheduler_tasks_with_mojo s2 ON s2.id = s1.id
170LEFT JOIN java_views_tasks s3 ON s3.id = s1.id
171LEFT JOIN navigation_tasks s4 ON s4.id = s1.id
172UNION ALL
173-- Choreographer slices won't necessarily be associated with an overlying
174-- LongTaskTracker slice, so join them separately.
175SELECT
176  printf('%s(java_views=%s)', kind, java_views) as full_name,
177  _get_java_views_task_type(kind) AS task_type,
178  id
179FROM long_task_slices_with_java_views
180WHERE kind = "Choreographer";
181
182DROP VIEW IF EXISTS chrome_long_tasks;
183CREATE PERFETTO VIEW chrome_long_tasks AS
184SELECT
185  full_name,
186  task_type,
187  thread.name AS thread_name,
188  thread.utid,
189  process.name AS process_name,
190  thread.upid,
191  ts.*
192FROM chrome_long_tasks_internal cti
193JOIN slice ts USING (id)
194JOIN thread_track tt ON ts.track_id = tt.id
195JOIN thread USING (utid)
196JOIN process USING (upid);
197