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 LONG, 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 LONG) 25RETURNS LONG 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 LONG) 35RETURNS LONG 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 PERFETTO 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), 157merged AS ( 158-- Merge all mojo slices. 159SELECT * FROM new_mojo_slices 160UNION ALL 161SELECT * FROM old_associated_mojo_slices 162UNION ALL 163SELECT * FROM old_non_associated_mojo_slices 164) 165SELECT * FROM merged ORDER BY id; 166 167-- This table contains a list of slices corresponding to the _representative_ 168-- Chrome Java view operations. 169-- These are the outermost Java view slices after filtering out generic framework views 170-- (like FitWindowsLinearLayout) and selecting the outermost slices from the remaining ones. 171-- 172-- @column id INT Slice id. 173-- @column ts INT Timestamp. 174-- @column dur INT Duration. 175-- @column name STRING Name of the view. 176-- @column is_software_screenshot BOOL Whether this slice is a part of non-accelerated 177-- capture toolbar screenshot. 178-- @column is_hardware_screenshot BOOL Whether this slice is a part of accelerated 179-- capture toolbar screenshot. 180CREATE PERFETTO TABLE _chrome_java_views AS 181WITH 182-- .draw, .onLayout and .onMeasure parts of the java view names don't add much, strip them. 183java_slices_with_trimmed_names AS ( 184 SELECT 185 id, 186 REPLACE( 187 REPLACE( 188 REPLACE( 189 REPLACE( 190 REPLACE( 191 s1.name, 192 ".draw", ""), 193 ".onLayout", ""), 194 ".onMeasure", ""), 195 ".Layout", ""), 196 ".Measure", "") AS name, 197 ts, 198 dur 199 FROM 200 slice s1 201 -- Ensure that toplevel Java slices are not included, as they may be logged 202 -- with either category = "toplevel" or category = "toplevel,Java". 203 -- Also filter out the zero duration slices as an attempt to reduce noise as 204 -- "Java" category contains misc events (as it's hard to add new categories). 205 WHERE _java_not_top_level_category(category) AND dur > 0 206 ), 207 -- We filter out generic slices from various UI frameworks which don't tell us much about 208 -- what exactly this view is doing. 209 interesting_java_slices AS ( 210 SELECT 211 id, name, ts, dur 212 FROM java_slices_with_trimmed_names 213 WHERE NOT name IN ( 214 -- AndroidX. 215 "FitWindowsFrameLayout", 216 "FitWindowsLinearLayout", 217 "ContentFrameLayout", 218 "CoordinatorLayout", 219 -- Other non-Chrome UI libraries. 220 "ComponentHost", 221 -- Generic Chrome frameworks. 222 "CompositorView:finalizeLayers", 223 "CompositorViewHolder", 224 "CompositorViewHolder:layout", 225 "CompositorViewHolder:updateContentViewChildrenDimension", 226 "CoordinatorLayoutForPointer", 227 "OptimizedFrameLayout", 228 "ViewResourceAdapter:getBitmap", 229 "ViewResourceFrameLayout", 230 -- Non-specific Chrome slices. 231 "AppCompatImageButton", 232 "ScrollingBottomViewResourceFrameLayout", 233 -- Screenshots get their custom annotations below. 234 "ViewResourceAdapter:captureWithHardwareDraw", 235 "ViewResourceAdapter:captureWithSoftwareDraw", 236 -- Non-bytecode generated slices. 237 "LayoutDriver:onUpdate" 238 ) 239) 240SELECT 241 s1.*, 242 -- While the parent slices are too generic to be used by themselves, 243 -- they can provide some useful metadata. 244 _has_parent_slice_with_name( 245 s1.id, 246 "ViewResourceAdapter:captureWithSoftwareDraw" 247 ) AS is_software_screenshot, 248 _has_parent_slice_with_name( 249 s1.id, 250 "ViewResourceAdapter:captureWithHardwareDraw" 251 ) AS is_hardware_screenshot 252FROM interesting_java_slices s1 253-- We select "outermost" interesting slices: interesting slices which 254-- do not another interesting slice in their parent chain. 255WHERE (SELECT count() 256 FROM ancestor_slice(s1.id) s2 257 JOIN interesting_java_slices s3 ON s2.id = s3.id) = 0; 258 259-- A list of slices corresponding to operations on interesting (non-generic) 260-- Chrome Java views. The view is considered interested if it's not a system 261-- (ContentFrameLayout) or generic library (CompositorViewHolder) views. 262-- 263-- TODO(altimin): Add "columns_from slice" annotation. 264-- TODO(altimin): convert this to EXTEND_TABLE when it becomes available. 265CREATE PERFETTO VIEW chrome_java_views( 266 -- Name of the view. 267 filtered_name STRING, 268 -- Whether this slice is a part of non-accelerated capture toolbar screenshot. 269 is_software_screenshot BOOL, 270 -- Whether this slice is a part of accelerated capture toolbar screenshot. 271 is_hardware_screenshot BOOL, 272 -- Slice id. 273 slice_id LONG 274) AS 275SELECT 276 java_view.name AS filtered_name, 277 java_view.is_software_screenshot, 278 java_view.is_hardware_screenshot, 279 slice.id as slice_id 280FROM _chrome_java_views java_view 281JOIN slice USING (id); 282 283-- A list of Choreographer tasks (Android frame generation) in Chrome. 284CREATE PERFETTO VIEW _chrome_choreographer_tasks 285AS 286SELECT 287 id, 288 "Choreographer" AS kind, 289 ts, 290 dur, 291 name 292FROM slice 293WHERE name GLOB "Looper.dispatch: android.view.Choreographer$FrameHandler*"; 294 295-- Extract task's posted_from information from task's arguments. 296CREATE PERFETTO FUNCTION _get_posted_from(arg_set_id LONG) 297RETURNS STRING AS 298WITH posted_from as ( 299 SELECT 300 EXTRACT_ARG($arg_set_id, "task.posted_from.file_name") AS file_name, 301 EXTRACT_ARG($arg_set_id, "task.posted_from.function_name") AS function_name 302) 303SELECT file_name || ":" || function_name as posted_from 304FROM posted_from; 305 306-- Selects the BeginMainFrame slices (which as posted from ScheduledActionSendBeginMainFrame), 307-- used for root-level processing. In top-level/Java based slices, these will correspond to the 308-- ancestor of descendant slices; in long-task tracking, these tasks will be 309-- on a custom track and will need to be associated with children by timestamp 310-- and duration. Corresponds with the Choreographer root slices in 311-- chrome_choreographer_tasks below. 312-- 313-- Schema: 314-- @column is The slice id. 315-- @column kind The type of Java slice. 316-- @column ts The timestamp of the slice. 317-- @column name The name of the slice. 318CREATE PERFETTO FUNCTION _select_begin_main_frame_java_slices( 319 name STRING) 320RETURNS TABLE(id LONG, kind STRING, ts TIMESTAMP, dur DURATION, name STRING) AS 321SELECT 322 id, 323 "SingleThreadProxy::BeginMainFrame" AS kind, 324 ts, 325 dur, 326 name 327FROM slice 328WHERE 329 (name = $name 330 AND _get_posted_from(arg_set_id) = 331 "cc/trees/single_thread_proxy.cc:ScheduledActionSendBeginMainFrame"); 332 333-- A list of Chrome tasks which were performing operations with Java views, 334-- together with the names of these views. 335-- @column id INT Slice id. 336-- @column kind STRING Type of the task. 337-- @column java_views STRING Concatenated names of Java views used by the task. 338CREATE PERFETTO VIEW _chrome_slices_with_java_views AS 339WITH 340 -- Select UI thread BeginMainFrames (which are Chrome scheduler tasks) and 341 -- Choreographer frames (which are looper tasks). 342 root_slices AS ( 343 SELECT id, kind 344 FROM _SELECT_BEGIN_MAIN_FRAME_JAVA_SLICES('ThreadControllerImpl::RunTask') 345 UNION ALL 346 SELECT id, kind FROM _chrome_choreographer_tasks 347 ), 348 -- Intermediate step to allow us to sort java view names. 349 root_slice_and_java_view_not_grouped AS ( 350 SELECT 351 root.id, root.kind, java_view.name AS java_view_name 352 FROM root_slices root 353 JOIN descendant_slice(root.id) child 354 JOIN _chrome_java_views java_view ON java_view.id = child.id 355 ) 356SELECT 357 root.id, 358 root.kind, 359 GROUP_CONCAT(DISTINCT java_view.java_view_name) AS java_views 360FROM root_slices root 361LEFT JOIN root_slice_and_java_view_not_grouped java_view USING (id) 362GROUP BY root.id; 363 364-- A list of tasks executed by Chrome scheduler. 365CREATE PERFETTO TABLE _chrome_scheduler_tasks AS 366SELECT 367 id 368FROM slice 369WHERE 370 category GLOB "*toplevel*" 371 AND (name = "ThreadControllerImpl::RunTask" OR name = "ThreadPool_RunTask") 372ORDER BY id; 373 374-- A list of tasks executed by Chrome scheduler. 375CREATE PERFETTO VIEW chrome_scheduler_tasks( 376 -- Slice id. 377 id LONG, 378 -- Type. 379 type STRING, 380 -- Name of the task. 381 name STRING, 382 -- Timestamp. 383 ts TIMESTAMP, 384 -- Duration. 385 dur DURATION, 386 -- Utid of the thread this task run on. 387 utid LONG, 388 -- Name of the thread this task run on. 389 thread_name STRING, 390 -- Upid of the process of this task. 391 upid LONG, 392 -- Name of the process of this task. 393 process_name STRING, 394 -- Same as slice.track_id. 395 track_id LONG, 396 -- Same as slice.category. 397 category STRING, 398 -- Same as slice.depth. 399 depth LONG, 400 -- Same as slice.parent_id. 401 parent_id LONG, 402 -- Same as slice.arg_set_id. 403 arg_set_id LONG, 404 -- Same as slice.thread_ts. 405 thread_ts TIMESTAMP, 406 -- Same as slice.thread_dur. 407 thread_dur DURATION, 408 -- Source location where the PostTask was called. 409 posted_from STRING 410) AS 411SELECT 412 task.id, 413 "chrome_scheduler_tasks" as type, 414 _format_scheduler_task_name( 415 _get_posted_from(slice.arg_set_id)) as name, 416 slice.ts, 417 slice.dur, 418 thread.utid, 419 thread.name as thread_name, 420 process.upid, 421 process.name as process_name, 422 slice.track_id, 423 slice.category, 424 slice.depth, 425 slice.parent_id, 426 slice.arg_set_id, 427 slice.thread_ts, 428 slice.thread_dur, 429 _get_posted_from(slice.arg_set_id) as posted_from 430FROM _chrome_scheduler_tasks task 431JOIN slice using (id) 432JOIN thread_track ON slice.track_id = thread_track.id 433JOIN thread using (utid) 434JOIN process using (upid) 435ORDER BY task.id; 436 437-- Select the slice that might be the descendant mojo slice for the given task 438-- slice if it exists. 439CREATE PERFETTO FUNCTION _get_descendant_mojo_slice_candidate( 440 slice_id LONG 441) 442RETURNS LONG AS 443SELECT 444 id 445FROM descendant_slice($slice_id) 446WHERE 447 -- The tricky case here is dealing with sync mojo IPCs: we do not want to 448 -- pick up sync IPCs when we are in a non-IPC task. 449 -- So we look at all toplevel events and pick up the first one: 450 -- for sync mojo messages, it will be "Send mojo message", which then 451 -- will fail. 452 -- Some events are excluded as they can legimately appear under "RunTask" 453 -- before "Receive mojo message". 454 category GLOB "*toplevel*" AND 455 name NOT IN ( 456 "SimpleWatcher::OnHandleReady", 457 "MessagePipe peer closed") 458ORDER by depth, ts 459LIMIT 1; 460 461CREATE PERFETTO FUNCTION _descendant_mojo_slice(slice_id LONG) 462RETURNS TABLE(task_name STRING) AS 463SELECT 464 printf("%s %s (hash=%d)", 465 mojo.interface_name, mojo.message_type, mojo.ipc_hash) AS task_name 466FROM slice task 467JOIN _chrome_mojo_slices mojo 468 ON mojo.id = _get_descendant_mojo_slice_candidate($slice_id) 469WHERE task.id = $slice_id; 470 471-- A list of "Chrome tasks": top-level execution units (e.g. scheduler tasks / 472-- IPCs / system callbacks) run by Chrome. For a given thread, the tasks 473-- will not intersect. 474-- 475-- @column task_name STRING Name for the given task. 476-- @column task_type STRING Type of the task (e.g. "scheduler"). 477-- @column scheduling_delay LONG 478CREATE PERFETTO TABLE _chrome_tasks AS 479WITH 480-- Select slices from "toplevel" category which do not have another 481-- "toplevel" slice as ancestor. The possible cases include sync mojo messages 482-- and tasks in nested runloops. Toplevel events may also be logged as with 483-- the Java category. 484non_embedded_toplevel_slices AS ( 485 SELECT * FROM slice 486 WHERE 487 _any_top_level_category(category) 488 AND (SELECT count() FROM ancestor_slice(slice.id) anc 489 WHERE anc.category GLOB "*toplevel*" or anc.category GLOB "*toplevel.viz*") = 0 490), 491-- Select slices from "Java" category which do not have another "Java" or 492-- "toplevel" slice as parent. In the longer term they should probably belong 493-- to "toplevel" category as well, but for now this will have to do. Ensure 494-- that "Java" slices do not include "toplevel" slices as those would be 495-- handled elsewhere. 496non_embedded_java_slices AS ( 497 SELECT 498 id, 499 name AS task_name, 500 "java" as task_type 501 FROM slice s 502 WHERE 503 _java_not_top_level_category(category) 504 AND (SELECT count() 505 FROM ancestor_slice(s.id) s2 506 WHERE s2.category GLOB "*toplevel*" OR s2.category GLOB "*Java*") = 0 507), 508-- Generate full names for tasks with java views. 509java_views_tasks AS ( 510 SELECT 511 id, 512 printf('%s(java_views=%s)', kind, java_views) AS task_name, 513 _get_java_views_task_type(kind) AS task_type 514 FROM _chrome_slices_with_java_views 515), 516scheduler_tasks AS ( 517 SELECT 518 id, 519 name as task_name, 520 "scheduler" as task_type 521 FROM chrome_scheduler_tasks 522), 523-- Select scheduler tasks which are used to run mojo messages and use the mojo names 524-- as full names for these slices. 525-- We restrict this to specific scheduler tasks which are expected to run mojo 526-- tasks due to sync mojo events, which also emit similar events. 527scheduler_tasks_with_mojo AS ( 528 SELECT 529 -- We use the "RunTask" as the task, and pick up the name from its child 530 -- "Receive mojo message" event. 531 task.id, 532 receive_message.task_name, 533 "mojo" AS task_type 534 FROM 535 chrome_scheduler_tasks task 536 JOIN _DESCENDANT_MOJO_SLICE(task.id) receive_message 537 WHERE 538 task.posted_from IN ( 539 "mojo/public/cpp/system/simple_watcher.cc:Notify", 540 "mojo/public/cpp/system/simple_watcher.cc:ArmOrNotify", 541 "mojo/public/cpp/bindings/lib/connector.cc:PostDispatchNextMessageFromPipe", 542 "ipc/ipc_mojo_bootstrap.cc:Accept") 543), 544navigation_tasks AS ( 545 WITH tasks_with_readable_names AS ( 546 SELECT 547 id, 548 _human_readable_navigation_task_name(task_name) as readable_name, 549 IFNULL(_extract_frame_type(id), 'unknown frame type') as frame_type 550 FROM 551 scheduler_tasks_with_mojo 552 ) 553 SELECT 554 id, 555 printf("%s (%s)", readable_name, frame_type) as task_name, 556 'navigation_task' AS task_type 557 FROM tasks_with_readable_names 558 WHERE readable_name IS NOT NULL 559), 560-- Add scheduler and mojo full names to non-embedded slices from 561-- the "toplevel" category, with mojo ones taking precedence. 562non_embedded_toplevel_slices_with_task_name AS ( 563 SELECT 564 task.id AS id, 565 COALESCE( 566 navigation.task_name, 567 java_views.task_name, 568 mojo.task_name, 569 scheduler.task_name, 570 task.name 571 ) AS name, 572 COALESCE( 573 navigation.task_type, 574 java_views.task_type, 575 mojo.task_type, 576 scheduler.task_type, 577 "other" 578 ) AS task_type 579 FROM non_embedded_toplevel_slices task 580 LEFT JOIN scheduler_tasks_with_mojo mojo ON mojo.id = task.id 581 LEFT JOIN scheduler_tasks scheduler ON scheduler.id = task.id 582 LEFT JOIN java_views_tasks java_views ON java_views.id = task.id 583 LEFT JOIN navigation_tasks navigation ON navigation.id = task.id 584) 585-- Merge slices from toplevel and Java categories. 586SELECT * FROM non_embedded_toplevel_slices_with_task_name 587UNION ALL 588SELECT * FROM non_embedded_java_slices 589ORDER BY id; 590 591-- A list of "Chrome tasks": top-level execution units (e.g. scheduler tasks / 592-- IPCs / system callbacks) run by Chrome. For a given thread, the slices 593-- corresponding to these tasks will not intersect. 594CREATE PERFETTO VIEW chrome_tasks( 595 -- Id for the given task, also the id of the slice this task corresponds to. 596 id LONG, 597 -- Name for the given task. 598 name STRING, 599 -- Type of the task (e.g. "scheduler"). 600 task_type STRING, 601 -- Thread name. 602 thread_name STRING, 603 -- Utid. 604 utid LONG, 605 -- Process name. 606 process_name STRING, 607 -- Upid. 608 upid LONG, 609 -- Alias of |slice.ts|. 610 ts TIMESTAMP, 611 -- Alias of |slice.dur|. 612 dur DURATION, 613 -- Alias of |slice.track_id|. 614 track_id LONG, 615 -- Alias of |slice.category|. 616 category STRING, 617 -- Alias of |slice.arg_set_id|. 618 arg_set_id LONG, 619 -- Alias of |slice.thread_ts|. 620 thread_ts TIMESTAMP, 621 -- Alias of |slice.thread_dur|. 622 thread_dur DURATION, 623 -- STRING Legacy alias for |name|. 624 full_name STRING 625) AS 626SELECT 627 cti.id, 628 cti.name, 629 task_type, 630 thread.name AS thread_name, 631 thread.utid, 632 process.name AS process_name, 633 thread.upid, 634 s.ts, 635 s.dur, 636 s.track_id, 637 s.category, 638 s.arg_set_id, 639 s.thread_ts, 640 s.thread_dur, 641 cti.name as full_name 642FROM _chrome_tasks cti 643JOIN slice s ON cti.id = s.id 644JOIN thread_track tt ON s.track_id = tt.id 645JOIN thread USING (utid) 646JOIN process USING (upid); 647