xref: /aosp_15_r20/external/cronet/base/tracing/stdlib/chrome/tasks.sql (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1-- Copyright 2023 The Chromium Authors
2-- Use of this source code is governed by a BSD-style license that can be
3-- found in the LICENSE file.
4
5-- Checks if slice has an ancestor with provided name.
6CREATE PERFETTO FUNCTION _has_parent_slice_with_name(
7  -- Id of the slice to check parents of.
8  id INT,
9  -- Name of potential ancestor slice.
10  parent_name STRING)
11-- Whether `parent_name` is a name of an ancestor slice.
12RETURNS BOOL AS
13SELECT EXISTS(
14  SELECT 1
15  FROM ancestor_slice($id)
16  WHERE name = $parent_name
17  LIMIT 1
18);
19
20-- Returns the mojo ipc hash for a given task, looking it up from the
21-- argument of descendant ScopedSetIpcHash slice.
22-- This is relevant only for the older Chrome traces, where mojo IPC
23-- hash was reported in a separate ScopedSetIpcHash slice.
24CREATE PERFETTO FUNCTION _extract_mojo_ipc_hash(slice_id INT)
25RETURNS INT AS
26SELECT EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.ipc_hash")
27FROM descendant_slice($slice_id)
28WHERE name="ScopedSetIpcHash"
29ORDER BY id
30LIMIT 1;
31
32-- Returns the frame type (main frame vs subframe) for key navigation tasks
33-- which capture the associated RenderFrameHost in an argument.
34CREATE PERFETTO FUNCTION _extract_frame_type(slice_id INT)
35RETURNS INT AS
36SELECT EXTRACT_ARG(arg_set_id, "render_frame_host.frame_type")
37FROM descendant_slice($slice_id)
38WHERE name IN (
39  "RenderFrameHostImpl::BeginNavigation",
40  "RenderFrameHostImpl::DidCommitProvisionalLoad",
41  "RenderFrameHostImpl::DidCommitSameDocumentNavigation",
42  "RenderFrameHostImpl::DidStopLoading"
43)
44LIMIT 1;
45
46-- Human-readable aliases for a few key navigation tasks.
47CREATE PERFETTO FUNCTION _human_readable_navigation_task_name(
48  task_name STRING)
49RETURNS STRING AS
50SELECT
51  CASE
52    WHEN $task_name = "content.mojom.FrameHost message (hash=2168461044)"
53      THEN "FrameHost::BeginNavigation"
54    WHEN $task_name = "content.mojom.FrameHost message (hash=3561497419)"
55      THEN "FrameHost::DidCommitProvisionalLoad"
56    WHEN $task_name = "content.mojom.FrameHost message (hash=1421450774)"
57      THEN "FrameHost::DidCommitSameDocumentNavigation"
58    WHEN $task_name = "content.mojom.FrameHost message (hash=368650583)"
59      THEN "FrameHost::DidStopLoading"
60  END;
61
62-- Takes a task name and formats it correctly for scheduler tasks.
63CREATE PERFETTO FUNCTION _format_scheduler_task_name(task_name STRING)
64RETURNS STRING AS
65SELECT printf("RunTask(posted_from=%s)", $task_name);
66
67-- Takes the category and determines whether it is "Java" only, as opposed to
68-- "toplevel,Java".
69CREATE PERFETTO FUNCTION _java_not_top_level_category(category STRING)
70RETURNS BOOL AS
71SELECT $category GLOB "*Java*" AND $category not GLOB "*toplevel*";
72
73-- Takes the category and determines whether is any valid
74-- toplevel category or combination of categories.
75CREATE PERFETTO FUNCTION _any_top_level_category(category STRING)
76RETURNS BOOL AS
77SELECT $category IN ("toplevel", "toplevel,viz", "toplevel,Java");
78
79-- TODO(altimin): the situations with kinds in this file is a bit of a mess.
80-- The idea is that it should work as `type` in the `slice` table, pointing to
81-- a "child" table with more information about the task (e.g. posted_from for
82-- scheduler tasks). Currently this is not the case and needs a cleanup.
83-- Also we should align this with how table inheritance should work for
84-- `CREATE PERFETTO TABLE`.
85
86-- Get task type for a given task kind.
87CREATE PERFETTO FUNCTION _get_java_views_task_type(kind STRING)
88RETURNS STRING AS
89SELECT
90  CASE $kind
91    WHEN "Choreographer" THEN "choreographer"
92    WHEN "SingleThreadProxy::BeginMainFrame" THEN "ui_thread_begin_main_frame"
93  END;
94
95-- All slices corresponding to receiving mojo messages.
96-- On the newer Chrome versions, it's just "Receive mojo message" and
97-- "Receive mojo reply" slices (or "Receive {mojo_message_name}" if
98-- built with `extended_tracing_enabled`. On legacy Chrome versions,
99-- other appropriate messages (like "Connector::DispatchMessage") are used.
100--
101-- @column STRING interface_name    Name of the IPC interface.
102-- @column INT ipc_hash             Hash of a message name.
103-- @column STRING message_type      Either 'message' or 'reply'.
104-- @column INT id                   Slice id.
105--
106-- Note: this might include messages received within a sync mojo call.
107-- TODO(altimin): This should use EXTEND_TABLE when it becomes available.
108CREATE TABLE _chrome_mojo_slices AS
109WITH
110-- Select all new-style (post crrev.com/c/3270337) mojo slices and
111-- generate |task_name| for them.
112-- If extended tracing is enabled, the slice name will have the full method
113-- name (i.e. "Receive content::mojom::FrameHost::DidStopLoading") and we
114-- should use it as a full name.
115-- If extended tracing is not enabled, we should include the interface name
116-- and method hash into the full name.
117new_mojo_slices AS (
118  SELECT
119    EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.mojo_interface_tag") AS interface_name,
120    EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.ipc_hash") AS ipc_hash,
121    CASE name
122      WHEN "Receive mojo message" THEN "message"
123      WHEN "Receive mojo reply" THEN "reply"
124    END AS message_type,
125    id
126  FROM slice
127  WHERE
128    category GLOB '*toplevel*'
129    AND name GLOB 'Receive *'
130),
131-- Select old-style slices for channel-associated mojo events.
132old_associated_mojo_slices AS (
133  SELECT
134    name AS interface_name,
135    _extract_mojo_ipc_hash(id) AS ipc_hash,
136    "message" AS message_type,
137    id
138  FROM slice
139  WHERE
140    category GLOB "*mojom*"
141    AND name GLOB '*.mojom.*'
142),
143-- Select old-style slices for non-(channel-associated) mojo events.
144old_non_associated_mojo_slices AS (
145  SELECT
146    COALESCE(
147      EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.watcher_notify_interface_tag"),
148      EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.mojo_interface_tag")
149    ) AS interface_name,
150    _extract_mojo_ipc_hash(id) AS ipc_hash,
151    "message" AS message_type,
152    id
153  FROM slice
154  WHERE
155    category GLOB "*toplevel*" AND name = "Connector::DispatchMessage"
156)
157-- Merge all mojo slices.
158SELECT * FROM new_mojo_slices
159UNION ALL
160SELECT * FROM old_associated_mojo_slices
161UNION ALL
162SELECT * FROM old_non_associated_mojo_slices;
163
164-- As we lookup by ID on |_chrome_mojo_slices| table, add an index on
165-- id to make lookups fast.
166CREATE INDEX _chrome_mojo_slices_idx ON _chrome_mojo_slices(id);
167
168-- This table contains a list of slices corresponding to the _representative_
169-- Chrome Java view operations.
170-- These are the outermost Java view slices after filtering out generic framework views
171-- (like FitWindowsLinearLayout) and selecting the outermost slices from the remaining ones.
172--
173-- @column id INT                       Slice id.
174-- @column ts INT                       Timestamp.
175-- @column dur INT                      Duration.
176-- @column name STRING                  Name of the view.
177-- @column is_software_screenshot BOOL  Whether this slice is a part of non-accelerated
178--                                      capture toolbar screenshot.
179-- @column is_hardware_screenshot BOOL  Whether this slice is a part of accelerated
180--                                      capture toolbar screenshot.
181CREATE TABLE _chrome_java_views AS
182WITH
183-- .draw, .onLayout and .onMeasure parts of the java view names don't add much, strip them.
184java_slices_with_trimmed_names AS (
185  SELECT
186    id,
187    REPLACE(
188      REPLACE(
189        REPLACE(
190          REPLACE(
191            REPLACE(
192              s1.name,
193              ".draw", ""),
194            ".onLayout", ""),
195          ".onMeasure", ""),
196        ".Layout", ""),
197      ".Measure", "") AS name,
198      ts,
199      dur
200    FROM
201      slice s1
202    -- Ensure that toplevel Java slices are not included, as they may be logged
203    -- with either category = "toplevel" or category = "toplevel,Java".
204    -- Also filter out the zero duration slices as an attempt to reduce noise as
205    -- "Java" category contains misc events (as it's hard to add new categories).
206    WHERE _java_not_top_level_category(category) AND dur > 0
207  ),
208  -- We filter out generic slices from various UI frameworks which don't tell us much about
209  -- what exactly this view is doing.
210  interesting_java_slices AS (
211    SELECT
212      id, name, ts, dur
213    FROM java_slices_with_trimmed_names
214    WHERE NOT name IN (
215      -- AndroidX.
216      "FitWindowsFrameLayout",
217      "FitWindowsLinearLayout",
218      "ContentFrameLayout",
219      "CoordinatorLayout",
220      -- Other non-Chrome UI libraries.
221      "ComponentHost",
222      -- Generic Chrome frameworks.
223      "CompositorView:finalizeLayers",
224      "CompositorViewHolder",
225      "CompositorViewHolder:layout",
226      "CompositorViewHolder:updateContentViewChildrenDimension",
227      "CoordinatorLayoutForPointer",
228      "OptimizedFrameLayout",
229      "ViewResourceAdapter:getBitmap",
230      "ViewResourceFrameLayout",
231      -- Non-specific Chrome slices.
232      "AppCompatImageButton",
233      "ScrollingBottomViewResourceFrameLayout",
234      -- Screenshots get their custom annotations below.
235      "ViewResourceAdapter:captureWithHardwareDraw",
236      "ViewResourceAdapter:captureWithSoftwareDraw",
237      -- Non-bytecode generated slices.
238      "LayoutDriver:onUpdate"
239    )
240)
241SELECT
242  s1.*,
243  -- While the parent slices are too generic to be used by themselves,
244  -- they can provide some useful metadata.
245  _has_parent_slice_with_name(
246    s1.id,
247    "ViewResourceAdapter:captureWithSoftwareDraw"
248  ) AS is_software_screenshot,
249  _has_parent_slice_with_name(
250    s1.id,
251    "ViewResourceAdapter:captureWithHardwareDraw"
252  ) AS is_hardware_screenshot
253FROM interesting_java_slices s1
254-- We select "outermost" interesting slices: interesting slices which
255-- do not another interesting slice in their parent chain.
256WHERE (SELECT count()
257  FROM ancestor_slice(s1.id) s2
258  JOIN interesting_java_slices s3 ON s2.id = s3.id) = 0;
259
260-- A list of slices corresponding to operations on interesting (non-generic)
261-- Chrome Java views. The view is considered interested if it's not a system
262-- (ContentFrameLayout) or generic library (CompositorViewHolder) views.
263--
264-- TODO(altimin): Add "columns_from slice" annotation.
265-- TODO(altimin): convert this to EXTEND_TABLE when it becomes available.
266CREATE PERFETTO VIEW chrome_java_views(
267  -- Name of the view.
268  filtered_name STRING,
269  -- Whether this slice is a part of non-accelerated capture toolbar screenshot.
270  is_software_screenshot BOOL,
271  -- Whether this slice is a part of accelerated capture toolbar screenshot.
272  is_hardware_screenshot BOOL,
273  -- Slice id.
274  slice_id INT
275) AS
276SELECT
277  java_view.name AS filtered_name,
278  java_view.is_software_screenshot,
279  java_view.is_hardware_screenshot,
280  slice.id as slice_id
281FROM _chrome_java_views java_view
282JOIN slice USING (id);
283
284-- A list of Choreographer tasks (Android frame generation) in Chrome.
285CREATE PERFETTO VIEW _chrome_choreographer_tasks
286AS
287SELECT
288  id,
289  "Choreographer" AS kind,
290  ts,
291  dur,
292  name
293FROM slice
294WHERE name GLOB "Looper.dispatch: android.view.Choreographer$FrameHandler*";
295
296-- Extract task's posted_from information from task's arguments.
297CREATE PERFETTO FUNCTION _get_posted_from(arg_set_id INT)
298RETURNS STRING AS
299WITH posted_from as (
300  SELECT
301    EXTRACT_ARG($arg_set_id, "task.posted_from.file_name") AS file_name,
302    EXTRACT_ARG($arg_set_id, "task.posted_from.function_name") AS function_name
303)
304SELECT file_name || ":" || function_name as posted_from
305FROM posted_from;
306
307-- Selects the BeginMainFrame slices (which as posted from ScheduledActionSendBeginMainFrame),
308-- used for root-level processing. In top-level/Java based slices, these will correspond to the
309-- ancestor of descendant slices; in long-task tracking, these tasks will be
310-- on a custom track and will need to be associated with children by timestamp
311-- and duration. Corresponds with the Choreographer root slices in
312-- chrome_choreographer_tasks below.
313--
314-- Schema:
315-- @column is            The slice id.
316-- @column kind          The type of Java slice.
317-- @column ts            The timestamp of the slice.
318-- @column name          The name of the slice.
319CREATE PERFETTO FUNCTION _select_begin_main_frame_java_slices(
320  name STRING)
321RETURNS TABLE(id INT, kind STRING, ts LONG, dur LONG, name STRING) AS
322SELECT
323  id,
324  "SingleThreadProxy::BeginMainFrame" AS kind,
325  ts,
326  dur,
327  name
328FROM slice
329WHERE
330  (name = $name
331    AND _get_posted_from(arg_set_id) =
332        "cc/trees/single_thread_proxy.cc:ScheduledActionSendBeginMainFrame");
333
334-- A list of Chrome tasks which were performing operations with Java views,
335-- together with the names of these views.
336-- @column id INT            Slice id.
337-- @column kind STRING       Type of the task.
338-- @column java_views STRING Concatenated names of Java views used by the task.
339CREATE PERFETTO VIEW _chrome_slices_with_java_views AS
340WITH
341  -- Select UI thread BeginMainFrames (which are Chrome scheduler tasks) and
342  -- Choreographer frames (which are looper tasks).
343  root_slices AS (
344    SELECT id, kind
345    FROM _SELECT_BEGIN_MAIN_FRAME_JAVA_SLICES('ThreadControllerImpl::RunTask')
346    UNION ALL
347    SELECT id, kind FROM _chrome_choreographer_tasks
348  ),
349  -- Intermediate step to allow us to sort java view names.
350  root_slice_and_java_view_not_grouped AS (
351    SELECT
352      root.id, root.kind, java_view.name AS java_view_name
353    FROM root_slices root
354    JOIN descendant_slice(root.id) child
355    JOIN _chrome_java_views java_view ON java_view.id = child.id
356  )
357SELECT
358  root.id,
359  root.kind,
360  GROUP_CONCAT(DISTINCT java_view.java_view_name) AS java_views
361FROM root_slices root
362LEFT JOIN root_slice_and_java_view_not_grouped java_view USING (id)
363GROUP BY root.id;
364
365-- A list of tasks executed by Chrome scheduler.
366CREATE TABLE _chrome_scheduler_tasks AS
367SELECT
368  id
369FROM slice
370WHERE
371  category GLOB "*toplevel*"
372  AND (name = "ThreadControllerImpl::RunTask" OR name = "ThreadPool_RunTask")
373ORDER BY id;
374
375-- A list of tasks executed by Chrome scheduler.
376CREATE PERFETTO VIEW chrome_scheduler_tasks(
377  -- Slice id.
378  id INT,
379  -- Type.
380  type STRING,
381  -- Name of the task.
382  name STRING,
383  -- Timestamp.
384  ts INT,
385  -- Duration.
386  dur INT,
387  -- Utid of the thread this task run on.
388  utid INT,
389  -- Name of the thread this task run on.
390  thread_name STRING,
391  -- Upid of the process of this task.
392  upid INT,
393  -- Name of the process of this task.
394  process_name STRING,
395  -- Same as slice.track_id.
396  track_id INT,
397  -- Same as slice.category.
398  category STRING,
399  -- Same as slice.depth.
400  depth INT,
401  -- Same as slice.parent_id.
402  parent_id INT,
403  -- Same as slice.arg_set_id.
404  arg_set_id INT,
405  -- Same as slice.thread_ts.
406  thread_ts INT,
407  -- Same as slice.thread_dur.
408  thread_dur INT,
409  -- Source location where the PostTask was called.
410  posted_from STRING
411) AS
412SELECT
413  task.id,
414  "chrome_scheduler_tasks" as type,
415  _format_scheduler_task_name(
416    _get_posted_from(slice.arg_set_id)) as name,
417  slice.ts,
418  slice.dur,
419  thread.utid,
420  thread.name as thread_name,
421  process.upid,
422  process.name as process_name,
423  slice.track_id,
424  slice.category,
425  slice.depth,
426  slice.parent_id,
427  slice.arg_set_id,
428  slice.thread_ts,
429  slice.thread_dur,
430  _get_posted_from(slice.arg_set_id) as posted_from
431FROM _chrome_scheduler_tasks task
432JOIN slice using (id)
433JOIN thread_track ON slice.track_id = thread_track.id
434JOIN thread using (utid)
435JOIN process using (upid)
436ORDER BY task.id;
437
438-- Select the slice that might be the descendant mojo slice for the given task
439-- slice if it exists.
440CREATE PERFETTO FUNCTION _get_descendant_mojo_slice_candidate(
441  slice_id INT
442)
443RETURNS INT AS
444SELECT
445  id
446FROM descendant_slice($slice_id)
447WHERE
448  -- The tricky case here is dealing with sync mojo IPCs: we do not want to
449  -- pick up sync IPCs when we are in a non-IPC task.
450  -- So we look at all toplevel events and pick up the first one:
451  -- for sync mojo messages, it will be "Send mojo message", which then
452  -- will fail.
453  -- Some events are excluded as they can legimately appear under "RunTask"
454  -- before "Receive mojo message".
455  category GLOB "*toplevel*" AND
456  name NOT IN (
457    "SimpleWatcher::OnHandleReady",
458    "MessagePipe peer closed")
459ORDER by depth, ts
460LIMIT 1;
461
462CREATE PERFETTO FUNCTION _descendant_mojo_slice(slice_id INT)
463RETURNS TABLE(task_name STRING) AS
464SELECT
465  printf("%s %s (hash=%d)",
466    mojo.interface_name, mojo.message_type, mojo.ipc_hash) AS task_name
467FROM slice task
468JOIN _chrome_mojo_slices mojo
469  ON mojo.id = _get_descendant_mojo_slice_candidate($slice_id)
470WHERE task.id = $slice_id;
471
472-- A list of "Chrome tasks": top-level execution units (e.g. scheduler tasks /
473-- IPCs / system callbacks) run by Chrome. For a given thread, the tasks
474-- will not intersect.
475--
476-- @column task_name STRING  Name for the given task.
477-- @column task_type STRING  Type of the task (e.g. "scheduler").
478-- @column scheduling_delay INT
479CREATE TABLE _chrome_tasks AS
480WITH
481-- Select slices from "toplevel" category which do not have another
482-- "toplevel" slice as ancestor. The possible cases include sync mojo messages
483-- and tasks in nested runloops. Toplevel events may also be logged as with
484-- the Java category.
485non_embedded_toplevel_slices AS (
486  SELECT * FROM slice
487  WHERE
488    _any_top_level_category(category)
489    AND (SELECT count() FROM ancestor_slice(slice.id) anc
490      WHERE anc.category GLOB "*toplevel*" or anc.category GLOB "*toplevel.viz*") = 0
491),
492-- Select slices from "Java" category which do not have another "Java" or
493-- "toplevel" slice as parent. In the longer term they should probably belong
494-- to "toplevel" category as well, but for now this will have to do. Ensure
495-- that "Java" slices do not include "toplevel" slices as those would be
496-- handled elsewhere.
497non_embedded_java_slices AS (
498  SELECT
499    id,
500    name AS task_name,
501    "java" as task_type
502  FROM slice s
503  WHERE
504    _java_not_top_level_category(category)
505    AND (SELECT count()
506      FROM ancestor_slice(s.id) s2
507      WHERE s2.category GLOB "*toplevel*" OR s2.category GLOB "*Java*") = 0
508),
509-- Generate full names for tasks with java views.
510java_views_tasks AS (
511  SELECT
512    id,
513    printf('%s(java_views=%s)', kind, java_views) AS task_name,
514    _get_java_views_task_type(kind) AS task_type
515  FROM _chrome_slices_with_java_views
516),
517scheduler_tasks AS (
518  SELECT
519    id,
520    name as task_name,
521    "scheduler" as task_type
522  FROM chrome_scheduler_tasks
523),
524-- Select scheduler tasks which are used to run mojo messages and use the mojo names
525-- as full names for these slices.
526-- We restrict this to specific scheduler tasks which are expected to run mojo
527-- tasks due to sync mojo events, which also emit similar events.
528scheduler_tasks_with_mojo AS (
529  SELECT
530    -- We use the "RunTask" as the task, and pick up the name from its child
531    -- "Receive mojo message" event.
532    task.id,
533    receive_message.task_name,
534    "mojo" AS task_type
535  FROM
536    chrome_scheduler_tasks task
537  JOIN _DESCENDANT_MOJO_SLICE(task.id) receive_message
538  WHERE
539    task.posted_from IN (
540      "mojo/public/cpp/system/simple_watcher.cc:Notify",
541      "mojo/public/cpp/system/simple_watcher.cc:ArmOrNotify",
542      "mojo/public/cpp/bindings/lib/connector.cc:PostDispatchNextMessageFromPipe",
543      "ipc/ipc_mojo_bootstrap.cc:Accept")
544),
545navigation_tasks AS (
546  WITH tasks_with_readable_names AS (
547    SELECT
548      id,
549      _human_readable_navigation_task_name(task_name) as readable_name,
550      IFNULL(_extract_frame_type(id), 'unknown frame type') as frame_type
551    FROM
552      scheduler_tasks_with_mojo
553  )
554  SELECT
555    id,
556    printf("%s (%s)", readable_name, frame_type) as task_name,
557    'navigation_task' AS task_type
558  FROM tasks_with_readable_names
559  WHERE readable_name IS NOT NULL
560),
561-- Add scheduler and mojo full names to non-embedded slices from
562-- the "toplevel" category, with mojo ones taking precedence.
563non_embedded_toplevel_slices_with_task_name AS (
564  SELECT
565    task.id AS id,
566    COALESCE(
567        navigation.task_name,
568        java_views.task_name,
569        mojo.task_name,
570        scheduler.task_name,
571        task.name
572    ) AS name,
573    COALESCE(
574        navigation.task_type,
575        java_views.task_type,
576        mojo.task_type,
577        scheduler.task_type,
578        "other"
579    ) AS task_type
580  FROM non_embedded_toplevel_slices task
581  LEFT JOIN scheduler_tasks_with_mojo mojo ON mojo.id = task.id
582  LEFT JOIN scheduler_tasks scheduler ON scheduler.id = task.id
583  LEFT JOIN java_views_tasks java_views ON java_views.id = task.id
584  LEFT JOIN navigation_tasks navigation ON navigation.id = task.id
585)
586-- Merge slices from toplevel and Java categories.
587SELECT * FROM non_embedded_toplevel_slices_with_task_name
588UNION ALL
589SELECT * FROM non_embedded_java_slices
590ORDER BY id;
591
592-- A list of "Chrome tasks": top-level execution units (e.g. scheduler tasks /
593-- IPCs / system callbacks) run by Chrome. For a given thread, the slices
594-- corresponding to these tasks will not intersect.
595CREATE PERFETTO VIEW chrome_tasks(
596  -- Id for the given task, also the id of the slice this task corresponds to.
597  id INT,
598  -- Name for the given task.
599  name STRING,
600  -- Type of the task (e.g. "scheduler").
601  task_type STRING,
602  -- Thread name.
603  thread_name STRING,
604  -- Utid.
605  utid INT,
606  -- Process name.
607  process_name STRING,
608  -- Upid.
609  upid INT,
610  -- Alias of |slice.ts|.
611  ts INT,
612  -- Alias of |slice.dur|.
613  dur INT,
614  -- Alias of |slice.track_id|.
615  track_id INT,
616  -- Alias of |slice.category|.
617  category INT,
618  -- Alias of |slice.arg_set_id|.
619  arg_set_id INT,
620  -- Alias of |slice.thread_ts|.
621  thread_ts INT,
622  -- Alias of |slice.thread_dur|.
623  thread_dur INT,
624  -- STRING    Legacy alias for |name|.
625  full_name STRING
626) AS
627SELECT
628  cti.id,
629  cti.name,
630  task_type,
631  thread.name AS thread_name,
632  thread.utid,
633  process.name AS process_name,
634  thread.upid,
635  s.ts,
636  s.dur,
637  s.track_id,
638  s.category,
639  s.arg_set_id,
640  s.thread_ts,
641  s.thread_dur,
642  cti.name as full_name
643FROM _chrome_tasks cti
644JOIN slice s ON cti.id = s.id
645JOIN thread_track tt ON s.track_id = tt.id
646JOIN thread USING (utid)
647JOIN process USING (upid);
648