tp: Add thread_slice_cpu_time to stdlib
Change-Id: Ib8bbda2f7c43b5bc4ea0f25df125add26e84f787
diff --git a/Android.bp b/Android.bp
index 40a53fd..ccc41a7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12062,6 +12062,7 @@
"src/trace_processor/perfetto_sql/stdlib/sched/utilization/process.sql",
"src/trace_processor/perfetto_sql/stdlib/sched/utilization/system.sql",
"src/trace_processor/perfetto_sql/stdlib/sched/utilization/thread.sql",
+ "src/trace_processor/perfetto_sql/stdlib/slices/cpu_time.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/flat_slices.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/slices.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/with_context.sql",
diff --git a/BUILD b/BUILD
index 14dc7b2..c161054 100644
--- a/BUILD
+++ b/BUILD
@@ -2517,6 +2517,7 @@
perfetto_filegroup(
name = "src_trace_processor_perfetto_sql_stdlib_slices_slices",
srcs = [
+ "src/trace_processor/perfetto_sql/stdlib/slices/cpu_time.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/flat_slices.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/slices.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/with_context.sql",
diff --git a/python/generators/sql_processing/utils.py b/python/generators/sql_processing/utils.py
index ba14110..539115e 100644
--- a/python/generators/sql_processing/utils.py
+++ b/python/generators/sql_processing/utils.py
@@ -116,7 +116,8 @@
# Allows for nonstandard object names.
OBJECT_NAME_ALLOWLIST = {
- 'slices/with_context.sql': ['process_slice', 'thread_slice']
+ 'slices/with_context.sql': ['process_slice', 'thread_slice'],
+ 'slices/cpu_time.sql': ['thread_slice_cpu_time']
}
# Given a regex pattern and a string to match against, returns all the
diff --git a/src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn
index 2e5f02f..f69eafd 100644
--- a/src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn
@@ -16,6 +16,7 @@
perfetto_sql_source_set("slices") {
sources = [
+ "cpu_time.sql",
"flat_slices.sql",
"slices.sql",
"with_context.sql",
diff --git a/src/trace_processor/perfetto_sql/stdlib/slices/cpu_time.sql b/src/trace_processor/perfetto_sql/stdlib/slices/cpu_time.sql
new file mode 100644
index 0000000..4a36d9c
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/stdlib/slices/cpu_time.sql
@@ -0,0 +1,72 @@
+--
+-- Copyright 2024 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+-- TODO(mayzner): Replace with good implementation of interval intersect.
+CREATE PERFETTO MACRO _interval_intersect_partition_utid(
+ left_table TableOrSubquery,
+ right_table TableOrSubquery
+)
+RETURNS TableOrSubquery AS
+(
+ WITH on_left AS (
+ SELECT
+ B.ts,
+ IIF(
+ A.ts + A.dur <= B.ts + B.dur,
+ A.ts + A.dur - B.ts, B.dur) AS dur,
+ A.id AS left_id,
+ B.id as right_id
+ FROM $left_table A
+ JOIN $right_table B ON (A.ts <= B.ts AND A.ts + A.dur > B.ts AND A.utid = B.utid)
+ ), on_right AS (
+ SELECT
+ B.ts,
+ IIF(
+ A.ts + A.dur <= B.ts + B.dur,
+ A.ts + A.dur - B.ts, B.dur) AS dur,
+ B.id as left_id,
+ A.id AS right_id
+ FROM $right_table A
+ -- The difference between this table and on_left is the lack of equality on
+ -- A.ts <= B.ts. This is to remove the issue of double accounting
+ -- timestamps that start at the same time.
+ JOIN $left_table B ON (A.ts < B.ts AND A.ts + A.dur > B.ts AND A.utid = B.utid)
+ )
+ SELECT * FROM on_left
+ UNION ALL
+ SELECT * FROM on_right
+);
+
+-- Time each thread slice spent running on CPU.
+-- Requires scheduling data to be available in the trace.
+CREATE PERFETTO TABLE thread_slice_cpu_time(
+ -- Slice id.
+ id INT,
+ -- Duration of the time the slice was running.
+ cpu_time INT) AS
+WITH slice_with_utid AS (
+ SELECT
+ slice.id,
+ slice.ts,
+ slice.dur,
+ utid
+ FROM slice
+ JOIN thread_track ON slice.track_id = thread_track.id
+ JOIN thread USING (utid)
+ WHERE utid != 0)
+SELECT left_id AS id, SUM(dur) AS cpu_time
+FROM _interval_intersect_partition_utid!(slice_with_utid, sched)
+GROUP BY 1
+ORDER BY 1;
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/stdlib/slices/tests.py b/test/trace_processor/diff_tests/stdlib/slices/tests.py
index e3db459..053dabf 100644
--- a/test/trace_processor/diff_tests/stdlib/slices/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/slices/tests.py
@@ -91,4 +91,28 @@
"ThreadControllerImpl::RunTask",174796099970797,186000,0
"Looper.dispatch: jy3(null)",174800056530797,1368000,0
"ThreadControllerImpl::RunTask",174800107962797,132000,0
- """))
\ No newline at end of file
+ """))
+
+ def test_thread_slice_cpu_time(self):
+ return DiffTestBlueprint(
+ trace=DataPath('example_android_trace_30s.pb'),
+ query="""
+ INCLUDE PERFETTO MODULE slices.cpu_time;
+
+ SELECT *
+ FROM thread_slice_cpu_time
+ LIMIT 10;
+ """,
+ out=Csv("""
+ "id","cpu_time"
+ 0,178646
+ 1,119740
+ 2,58073
+ 3,98698
+ 4,121979
+ 5,45000
+ 6,35104
+ 7,33333
+ 8,46926
+ 9,17865
+ """))
\ No newline at end of file