CREATE PERFETTO FUNCTION _has_parent_slice_with_name(
id LONG,
parent_name STRING
)
RETURNS BOOL AS
SELECT
EXISTS(
SELECT
1
FROM ancestor_slice($id)
WHERE
name = $parent_name
LIMIT 1
);
CREATE PERFETTO FUNCTION _extract_mojo_ipc_hash(
slice_id LONG
)
RETURNS LONG AS
SELECT
extract_arg(arg_set_id, "chrome_mojo_event_info.ipc_hash")
FROM descendant_slice($slice_id)
WHERE
name = "ScopedSetIpcHash"
ORDER BY
id
LIMIT 1;
CREATE PERFETTO FUNCTION _extract_frame_type(
slice_id LONG
)
RETURNS LONG AS
SELECT
extract_arg(arg_set_id, "render_frame_host.frame_type")
FROM descendant_slice($slice_id)
WHERE
name IN ("RenderFrameHostImpl::BeginNavigation", "RenderFrameHostImpl::DidCommitProvisionalLoad", "RenderFrameHostImpl::DidCommitSameDocumentNavigation", "RenderFrameHostImpl::DidStopLoading")
LIMIT 1;
CREATE PERFETTO FUNCTION _human_readable_navigation_task_name(
task_name STRING
)
RETURNS STRING AS
SELECT
CASE
WHEN $task_name = "content.mojom.FrameHost message (hash=2168461044)"
THEN "FrameHost::BeginNavigation"
WHEN $task_name = "content.mojom.FrameHost message (hash=3561497419)"
THEN "FrameHost::DidCommitProvisionalLoad"
WHEN $task_name = "content.mojom.FrameHost message (hash=1421450774)"
THEN "FrameHost::DidCommitSameDocumentNavigation"
WHEN $task_name = "content.mojom.FrameHost message (hash=368650583)"
THEN "FrameHost::DidStopLoading"
END;
CREATE PERFETTO FUNCTION _format_scheduler_task_name(
task_name STRING
)
RETURNS STRING AS
SELECT
printf("RunTask(posted_from=%s)", $task_name);
CREATE PERFETTO FUNCTION _java_not_top_level_category(
category STRING
)
RETURNS BOOL AS
SELECT
$category GLOB "*Java*" AND NOT $category GLOB "*toplevel*";
CREATE PERFETTO FUNCTION _any_top_level_category(
category STRING
)
RETURNS BOOL AS
SELECT
$category IN ("toplevel", "toplevel,viz", "toplevel,Java");
CREATE PERFETTO FUNCTION _get_java_views_task_type(
kind STRING
)
RETURNS STRING AS
SELECT
CASE $kind
WHEN "Choreographer"
THEN "choreographer"
WHEN "SingleThreadProxy::BeginMainFrame"
THEN "ui_thread_begin_main_frame"
END;
CREATE PERFETTO TABLE _chrome_mojo_slices AS
WITH
new_mojo_slices AS (
SELECT
extract_arg(arg_set_id, "chrome_mojo_event_info.mojo_interface_tag") AS interface_name,
extract_arg(arg_set_id, "chrome_mojo_event_info.ipc_hash") AS ipc_hash,
CASE name
WHEN "Receive mojo message"
THEN "message"
WHEN "Receive mojo reply"
THEN "reply"
END AS message_type,
id
FROM slice
WHERE
category GLOB '*toplevel*' AND name GLOB 'Receive *'
),
old_associated_mojo_slices AS (
SELECT
name AS interface_name,
_extract_mojo_ipc_hash(id) AS ipc_hash,
"message" AS message_type,
id
FROM slice
WHERE
category GLOB "*mojom*" AND name GLOB '*.mojom.*'
),
old_non_associated_mojo_slices AS (
SELECT
coalesce(
extract_arg(arg_set_id, "chrome_mojo_event_info.watcher_notify_interface_tag"),
extract_arg(arg_set_id, "chrome_mojo_event_info.mojo_interface_tag")
) AS interface_name,
_extract_mojo_ipc_hash(id) AS ipc_hash,
"message" AS message_type,
id
FROM slice
WHERE
category GLOB "*toplevel*" AND name = "Connector::DispatchMessage"
),
merged AS (
SELECT
*
FROM new_mojo_slices
UNION ALL
SELECT
*
FROM old_associated_mojo_slices
UNION ALL
SELECT
*
FROM old_non_associated_mojo_slices
)
SELECT
*
FROM merged
ORDER BY
id;
CREATE PERFETTO TABLE _chrome_java_views AS
WITH
java_slices_with_trimmed_names AS (
SELECT
id,
replace(
replace(
replace(replace(replace(s1.name, ".draw", ""), ".onLayout", ""), ".onMeasure", ""),
".Layout",
""
),
".Measure",
""
) AS name,
ts,
dur
FROM slice AS s1
WHERE
_java_not_top_level_category(category) AND dur > 0
),
interesting_java_slices AS (
SELECT
id,
name,
ts,
dur
FROM java_slices_with_trimmed_names
WHERE
NOT name IN ("FitWindowsFrameLayout", "FitWindowsLinearLayout", "ContentFrameLayout", "CoordinatorLayout")
AND NOT name IN ("ComponentHost")
AND NOT name IN ("CompositorView:finalizeLayers", "CompositorViewHolder", "CompositorViewHolder:layout", "CompositorViewHolder:updateContentViewChildrenDimension", "CoordinatorLayoutForPointer", "OptimizedFrameLayout", "ViewResourceAdapter:getBitmap", "ViewResourceFrameLayout")
AND NOT name IN ("AppCompatImageButton", "ScrollingBottomViewResourceFrameLayout")
AND NOT name IN ("ViewResourceAdapter:captureWithHardwareDraw", "ViewResourceAdapter:captureWithSoftwareDraw")
AND NOT name IN ("LayoutDriver:onUpdate")
)
SELECT
s1.*,
_has_parent_slice_with_name(s1.id, "ViewResourceAdapter:captureWithSoftwareDraw") AS is_software_screenshot,
_has_parent_slice_with_name(s1.id, "ViewResourceAdapter:captureWithHardwareDraw") AS is_hardware_screenshot
FROM interesting_java_slices AS s1
WHERE
(
SELECT
count()
FROM ancestor_slice(s1.id) AS s2
JOIN interesting_java_slices AS s3
ON s2.id = s3.id
) = 0;
CREATE PERFETTO VIEW chrome_java_views (
filtered_name STRING,
is_software_screenshot BOOL,
is_hardware_screenshot BOOL,
slice_id LONG
) AS
SELECT
java_view.name AS filtered_name,
java_view.is_software_screenshot,
java_view.is_hardware_screenshot,
slice.id AS slice_id
FROM _chrome_java_views AS java_view
JOIN slice
USING (id);
CREATE PERFETTO VIEW _chrome_choreographer_tasks AS
SELECT
id,
"Choreographer" AS kind,
ts,
dur,
name
FROM slice
WHERE
name GLOB "Looper.dispatch: android.view.Choreographer$FrameHandler*";
CREATE PERFETTO FUNCTION _get_posted_from(
arg_set_id LONG
)
RETURNS STRING AS
WITH
posted_from AS (
SELECT
extract_arg($arg_set_id, "task.posted_from.file_name") AS file_name,
extract_arg($arg_set_id, "task.posted_from.function_name") AS function_name
)
SELECT
file_name || ":" || function_name AS posted_from
FROM posted_from;
CREATE PERFETTO FUNCTION _select_begin_main_frame_java_slices(
name STRING
)
RETURNS TABLE (
id LONG,
kind STRING,
ts TIMESTAMP,
dur DURATION,
name STRING
) AS
SELECT
id,
"SingleThreadProxy::BeginMainFrame" AS kind,
ts,
dur,
name
FROM slice
WHERE
(
name = $name
AND _get_posted_from(arg_set_id) = "cc/trees/single_thread_proxy.cc:ScheduledActionSendBeginMainFrame"
);
CREATE PERFETTO VIEW _chrome_slices_with_java_views AS
WITH
root_slices AS (
SELECT
id,
kind
FROM _select_begin_main_frame_java_slices('ThreadControllerImpl::RunTask')
UNION ALL
SELECT
id,
kind
FROM _chrome_choreographer_tasks
),
root_slice_and_java_view_not_grouped AS (
SELECT
root.id,
root.kind,
java_view.name AS java_view_name
FROM root_slices AS root, descendant_slice(root.id) AS child
JOIN _chrome_java_views AS java_view
ON java_view.id = child.id
)
SELECT
root.id,
root.kind,
GROUP_CONCAT(DISTINCT java_view.java_view_name) AS java_views
FROM root_slices AS root
LEFT JOIN root_slice_and_java_view_not_grouped AS java_view
USING (id)
GROUP BY
root.id;
CREATE PERFETTO TABLE _chrome_scheduler_tasks AS
SELECT
id
FROM slice
WHERE
category GLOB "*toplevel*"
AND (
name = "ThreadControllerImpl::RunTask" OR name = "ThreadPool_RunTask"
)
ORDER BY
id;
CREATE PERFETTO VIEW chrome_scheduler_tasks (
id LONG,
type STRING,
name STRING,
ts TIMESTAMP,
dur DURATION,
utid LONG,
thread_name STRING,
upid LONG,
process_name STRING,
track_id LONG,
category STRING,
depth LONG,
parent_id LONG,
arg_set_id LONG,
thread_ts TIMESTAMP,
thread_dur DURATION,
posted_from STRING
) AS
SELECT
task.id,
"chrome_scheduler_tasks" AS type,
_format_scheduler_task_name(_get_posted_from(slice.arg_set_id)) AS name,
slice.ts,
slice.dur,
thread.utid,
thread.name AS thread_name,
process.upid,
process.name AS process_name,
slice.track_id,
slice.category,
slice.depth,
slice.parent_id,
slice.arg_set_id,
slice.thread_ts,
slice.thread_dur,
_get_posted_from(slice.arg_set_id) AS posted_from
FROM _chrome_scheduler_tasks AS task
JOIN slice
USING (id)
JOIN thread_track
ON slice.track_id = thread_track.id
JOIN thread
USING (utid)
JOIN process
USING (upid)
ORDER BY
task.id;
CREATE PERFETTO FUNCTION _get_descendant_mojo_slice_candidate(
slice_id LONG
)
RETURNS LONG AS
SELECT
id
FROM descendant_slice($slice_id)
WHERE
category GLOB "*toplevel*"
AND NOT name IN ("SimpleWatcher::OnHandleReady", "MessagePipe peer closed")
ORDER BY
depth,
ts
LIMIT 1;
CREATE PERFETTO FUNCTION _descendant_mojo_slice(
slice_id LONG
)
RETURNS TABLE (
task_name STRING
) AS
SELECT
printf("%s %s (hash=%d)", mojo.interface_name, mojo.message_type, mojo.ipc_hash) AS task_name
FROM slice AS task
JOIN _chrome_mojo_slices AS mojo
ON mojo.id = _get_descendant_mojo_slice_candidate($slice_id)
WHERE
task.id = $slice_id;
CREATE PERFETTO TABLE _chrome_tasks AS
WITH
non_embedded_toplevel_slices AS (
SELECT
*
FROM slice
WHERE
_any_top_level_category(category)
AND (
SELECT
count()
FROM ancestor_slice(slice.id) AS anc
WHERE
anc.category GLOB "*toplevel*" OR anc.category GLOB "*toplevel.viz*"
) = 0
),
non_embedded_java_slices AS (
SELECT
id,
name AS task_name,
"java" AS task_type
FROM slice AS s
WHERE
_java_not_top_level_category(category)
AND (
SELECT
count()
FROM ancestor_slice(s.id) AS s2
WHERE
s2.category GLOB "*toplevel*" OR s2.category GLOB "*Java*"
) = 0
),
java_views_tasks AS (
SELECT
id,
printf('%s(java_views=%s)', kind, java_views) AS task_name,
_get_java_views_task_type(kind) AS task_type
FROM _chrome_slices_with_java_views
),
scheduler_tasks AS (
SELECT
id,
name AS task_name,
"scheduler" AS task_type
FROM chrome_scheduler_tasks
),
scheduler_tasks_with_mojo AS (
SELECT
task.id,
receive_message.task_name,
"mojo" AS task_type
FROM chrome_scheduler_tasks AS task, _descendant_mojo_slice(task.id) AS receive_message
WHERE
task.posted_from IN ("mojo/public/cpp/system/simple_watcher.cc:Notify", "mojo/public/cpp/system/simple_watcher.cc:ArmOrNotify", "mojo/public/cpp/bindings/lib/connector.cc:PostDispatchNextMessageFromPipe", "ipc/ipc_mojo_bootstrap.cc:Accept")
),
navigation_tasks AS (
WITH
tasks_with_readable_names AS (
SELECT
id,
_human_readable_navigation_task_name(task_name) AS readable_name,
coalesce(_extract_frame_type(id), 'unknown frame type') AS frame_type
FROM scheduler_tasks_with_mojo
)
SELECT
id,
printf("%s (%s)", readable_name, frame_type) AS task_name,
'navigation_task' AS task_type
FROM tasks_with_readable_names
WHERE
readable_name IS NOT NULL
),
non_embedded_toplevel_slices_with_task_name AS (
SELECT
task.id AS id,
coalesce(
navigation.task_name,
java_views.task_name,
mojo.task_name,
scheduler.task_name,
task.name
) AS name,
coalesce(navigation.task_type, java_views.task_type, mojo.task_type, scheduler.task_type, "other") AS task_type
FROM non_embedded_toplevel_slices AS task
LEFT JOIN scheduler_tasks_with_mojo AS mojo
ON mojo.id = task.id
LEFT JOIN scheduler_tasks AS scheduler
ON scheduler.id = task.id
LEFT JOIN java_views_tasks AS java_views
ON java_views.id = task.id
LEFT JOIN navigation_tasks AS navigation
ON navigation.id = task.id
)
SELECT
*
FROM non_embedded_toplevel_slices_with_task_name
UNION ALL
SELECT
*
FROM non_embedded_java_slices
ORDER BY
id;
CREATE PERFETTO VIEW chrome_tasks (
id LONG,
name STRING,
task_type STRING,
thread_name STRING,
utid LONG,
process_name STRING,
upid LONG,
ts TIMESTAMP,
dur DURATION,
track_id LONG,
category STRING,
arg_set_id LONG,
thread_ts TIMESTAMP,
thread_dur DURATION,
full_name STRING
) AS
SELECT
cti.id,
cti.name,
task_type,
thread.name AS thread_name,
thread.utid,
process.name AS process_name,
thread.upid,
s.ts,
s.dur,
s.track_id,
s.category,
s.arg_set_id,
s.thread_ts,
s.thread_dur,
cti.name AS full_name
FROM _chrome_tasks AS cti
JOIN slice AS s
ON cti.id = s.id
JOIN thread_track AS tt
ON s.track_id = tt.id
JOIN thread
USING (utid)
JOIN process
USING (upid);