Loading packages/SystemUI/metrics/perfetto/metrics_specs/Android.bp +6 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ filegroup { "android_sf_critical_work_main_thread.textproto", "android_dmabuf_per_process_metric.textproto", "android_sf_critical_work_region_sampling.textproto", "android_gralloc_buffers_per_process_metric.textproto", ], } Loading @@ -48,6 +49,11 @@ prebuilt_etc { src: "android_sf_critical_work_region_sampling.textproto", } prebuilt_etc { name: "android_gralloc_buffers_per_process_metric.textproto", src: "android_gralloc_buffers_per_process_metric.textproto", } python_library_host { name: "metrics-tests-utils", srcs: ["tests/utils/*.py"], Loading packages/SystemUI/metrics/perfetto/metrics_specs/android_gralloc_buffers_per_process_metric.textproto 0 → 100644 +76 −0 Original line number Diff line number Diff line # Copyright (C) 2025 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 # # http://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. # There is a specific counter added to Perfetto trace of each process that tracks individual GrAlloc # allocations for each process. This metric monitors said counter. # We compute the duration of the current counter value by subtracting the current timestamp # from the timestamp of the next counter value. # The LEAD function is used to get the next timestamp. If there is no next timestamp, it uses the # end of the trace as the next timestamp. query: { id: "gralloc_buffers_counter_span" sql: { sql: "SELECT p.name as process_name, pct.name AS counter_name, value AS metric_val, LEAD(ts, 1, ( SELECT IFNULL( end_ts, trace_end() ) FROM process p WHERE p.upid = pct.upid) ) OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur FROM counter c JOIN process_counter_track pct ON pct.id = c.track_id JOIN process p ON pct.upid = p.upid WHERE pct.name = 'mem.gralloc.buffers' AND pct.upid IS NOT NULL " column_names: "process_name" column_names: "counter_name" column_names: "metric_val" column_names: "dur" } } metric_template_spec: { id_prefix: "android_gralloc_buffers_per_process_metric" dimensions: "process_name" dimensions: "counter_name" value_columns: "min_val" value_columns: "max_val" value_columns: "avg_val" query: { inner_query_id: "gralloc_buffers_counter_span" group_by: { column_names: "process_name" column_names: "counter_name" aggregates: { column_name: "metric_val" op: MIN result_column_name: "min_val" } aggregates: { column_name: "metric_val" op: MAX result_column_name: "max_val" } aggregates: { column_name: "metric_val" op: DURATION_WEIGHTED_MEAN result_column_name: "avg_val" } } } } packages/SystemUI/metrics/perfetto/metrics_specs/tests/data/android_gralloc_buffers_per_process_metric_output.txt 0 → 100644 +123 −0 Original line number Diff line number Diff line metric_bundles { row { values { double_value: 10.0 } values { double_value: 20.0 } values { double_value: 13.333333333333334 } dimension { string_value: "com.android.systemui" } dimension { string_value: "mem.gralloc.buffers" } } row { values { double_value: 15.0 } values { double_value: 25.0 } values { double_value: 15.0 } dimension { string_value: "com.google.android.apps.nexuslauncher" } dimension { string_value: "mem.gralloc.buffers" } } specs { id: "android_gralloc_buffers_per_process_metric_min_val" dimensions: "process_name" dimensions: "counter_name" value: "min_val" query { inner_query_id: "gralloc_buffers_counter_span" group_by { column_names: "process_name" column_names: "counter_name" aggregates { column_name: "metric_val" op: MIN result_column_name: "min_val" } aggregates { column_name: "metric_val" op: MAX result_column_name: "max_val" } aggregates { column_name: "metric_val" op: DURATION_WEIGHTED_MEAN result_column_name: "avg_val" } } } bundle_id: "android_gralloc_buffers_per_process_metric" } specs { id: "android_gralloc_buffers_per_process_metric_max_val" dimensions: "process_name" dimensions: "counter_name" value: "max_val" query { inner_query_id: "gralloc_buffers_counter_span" group_by { column_names: "process_name" column_names: "counter_name" aggregates { column_name: "metric_val" op: MIN result_column_name: "min_val" } aggregates { column_name: "metric_val" op: MAX result_column_name: "max_val" } aggregates { column_name: "metric_val" op: DURATION_WEIGHTED_MEAN result_column_name: "avg_val" } } } bundle_id: "android_gralloc_buffers_per_process_metric" } specs { id: "android_gralloc_buffers_per_process_metric_avg_val" dimensions: "process_name" dimensions: "counter_name" value: "avg_val" query { inner_query_id: "gralloc_buffers_counter_span" group_by { column_names: "process_name" column_names: "counter_name" aggregates { column_name: "metric_val" op: MIN result_column_name: "min_val" } aggregates { column_name: "metric_val" op: MAX result_column_name: "max_val" } aggregates { column_name: "metric_val" op: DURATION_WEIGHTED_MEAN result_column_name: "avg_val" } } } bundle_id: "android_gralloc_buffers_per_process_metric" } } packages/SystemUI/metrics/perfetto/metrics_specs/tests/metrics_v2_test.py +13 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ from metrics_specs.tests.utils import android_bitmap_metric_trace from metrics_specs.tests.utils import android_sf_critical_work_main_thread_trace from metrics_specs.tests.utils import android_dmabuf_per_process_metric_trace from metrics_specs.tests.utils import android_sf_critical_work_region_sampling_trace from metrics_specs.tests.utils import android_gralloc_buffers_per_process_metric_trace from metrics_specs.tests.utils import test_helper import unittest Loading Loading @@ -73,5 +74,17 @@ class MetricsV2Test(unittest.TestCase): ] ) def test_android_gralloc_buffers_per_process_metric(self): self.helper.verify_metric( spec_file="android_gralloc_buffers_per_process_metric.textproto", trace_proto_bytes = android_gralloc_buffers_per_process_metric_trace.get_proto(), expected_output_file = "android_gralloc_buffers_per_process_metric_output.txt", metric_ids = [ "android_gralloc_buffers_per_process_metric_min_val", "android_gralloc_buffers_per_process_metric_max_val", "android_gralloc_buffers_per_process_metric_avg_val", ] ) if __name__ == '__main__': unittest.main() packages/SystemUI/metrics/perfetto/metrics_specs/tests/utils/android_gralloc_buffers_per_process_metric_trace.py 0 → 100644 +48 −0 Original line number Diff line number Diff line #!/usr/bin/env python3 # Copyright (C) 2025 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 # # http://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. from metrics_specs.tests.utils import trace_proto_builder from perfetto.protos.perfetto.trace.perfetto_trace_pb2 import Trace def get_proto(): SYSUI_PID = 1000 SYSUI_PROCESS_NAME = "com.android.systemui" LAUNCHER_PID = 2000 LAUNCHER_PROCESS_NAME = "com.google.android.apps.nexuslauncher" trace = Trace() builder = trace_proto_builder.TraceProtoBuilder(trace) # Add all processes builder.add_packet() builder.add_process(pid=SYSUI_PID, ppid=SYSUI_PID, cmdline=SYSUI_PROCESS_NAME, uid=10001) builder.add_process(pid=LAUNCHER_PID, ppid=LAUNCHER_PID, cmdline=LAUNCHER_PROCESS_NAME, uid=20001) # Add counters in the com.android.systemui process builder.add_ftrace_packet(cpu=0) builder.add_atrace_counter(ts=1000, pid=SYSUI_PID, tid=SYSUI_PID, buf="mem.gralloc.buffers", cnt=10) builder.add_ftrace_packet(cpu=0) builder.add_atrace_counter(ts=2000, pid=SYSUI_PID, tid=SYSUI_PID, buf="mem.gralloc.buffers", cnt=20) builder.add_ftrace_packet(cpu=0) builder.add_atrace_counter(ts=1000, pid=SYSUI_PID, tid=SYSUI_PID, buf="Random Counter", cnt=111) # Add counters in the com.google.android.apps.nexuslauncher process builder.add_ftrace_packet(cpu=0) builder.add_atrace_counter(ts=1500, pid=LAUNCHER_PID, tid=LAUNCHER_PID, buf="mem.gralloc.buffers", cnt=15) builder.add_ftrace_packet(cpu=0) builder.add_atrace_counter(ts=2500, pid=LAUNCHER_PID, tid=LAUNCHER_PID, buf="mem.gralloc.buffers", cnt=25) return builder.trace.SerializeToString() No newline at end of file Loading
packages/SystemUI/metrics/perfetto/metrics_specs/Android.bp +6 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ filegroup { "android_sf_critical_work_main_thread.textproto", "android_dmabuf_per_process_metric.textproto", "android_sf_critical_work_region_sampling.textproto", "android_gralloc_buffers_per_process_metric.textproto", ], } Loading @@ -48,6 +49,11 @@ prebuilt_etc { src: "android_sf_critical_work_region_sampling.textproto", } prebuilt_etc { name: "android_gralloc_buffers_per_process_metric.textproto", src: "android_gralloc_buffers_per_process_metric.textproto", } python_library_host { name: "metrics-tests-utils", srcs: ["tests/utils/*.py"], Loading
packages/SystemUI/metrics/perfetto/metrics_specs/android_gralloc_buffers_per_process_metric.textproto 0 → 100644 +76 −0 Original line number Diff line number Diff line # Copyright (C) 2025 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 # # http://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. # There is a specific counter added to Perfetto trace of each process that tracks individual GrAlloc # allocations for each process. This metric monitors said counter. # We compute the duration of the current counter value by subtracting the current timestamp # from the timestamp of the next counter value. # The LEAD function is used to get the next timestamp. If there is no next timestamp, it uses the # end of the trace as the next timestamp. query: { id: "gralloc_buffers_counter_span" sql: { sql: "SELECT p.name as process_name, pct.name AS counter_name, value AS metric_val, LEAD(ts, 1, ( SELECT IFNULL( end_ts, trace_end() ) FROM process p WHERE p.upid = pct.upid) ) OVER(PARTITION BY track_id ORDER BY ts) - ts AS dur FROM counter c JOIN process_counter_track pct ON pct.id = c.track_id JOIN process p ON pct.upid = p.upid WHERE pct.name = 'mem.gralloc.buffers' AND pct.upid IS NOT NULL " column_names: "process_name" column_names: "counter_name" column_names: "metric_val" column_names: "dur" } } metric_template_spec: { id_prefix: "android_gralloc_buffers_per_process_metric" dimensions: "process_name" dimensions: "counter_name" value_columns: "min_val" value_columns: "max_val" value_columns: "avg_val" query: { inner_query_id: "gralloc_buffers_counter_span" group_by: { column_names: "process_name" column_names: "counter_name" aggregates: { column_name: "metric_val" op: MIN result_column_name: "min_val" } aggregates: { column_name: "metric_val" op: MAX result_column_name: "max_val" } aggregates: { column_name: "metric_val" op: DURATION_WEIGHTED_MEAN result_column_name: "avg_val" } } } }
packages/SystemUI/metrics/perfetto/metrics_specs/tests/data/android_gralloc_buffers_per_process_metric_output.txt 0 → 100644 +123 −0 Original line number Diff line number Diff line metric_bundles { row { values { double_value: 10.0 } values { double_value: 20.0 } values { double_value: 13.333333333333334 } dimension { string_value: "com.android.systemui" } dimension { string_value: "mem.gralloc.buffers" } } row { values { double_value: 15.0 } values { double_value: 25.0 } values { double_value: 15.0 } dimension { string_value: "com.google.android.apps.nexuslauncher" } dimension { string_value: "mem.gralloc.buffers" } } specs { id: "android_gralloc_buffers_per_process_metric_min_val" dimensions: "process_name" dimensions: "counter_name" value: "min_val" query { inner_query_id: "gralloc_buffers_counter_span" group_by { column_names: "process_name" column_names: "counter_name" aggregates { column_name: "metric_val" op: MIN result_column_name: "min_val" } aggregates { column_name: "metric_val" op: MAX result_column_name: "max_val" } aggregates { column_name: "metric_val" op: DURATION_WEIGHTED_MEAN result_column_name: "avg_val" } } } bundle_id: "android_gralloc_buffers_per_process_metric" } specs { id: "android_gralloc_buffers_per_process_metric_max_val" dimensions: "process_name" dimensions: "counter_name" value: "max_val" query { inner_query_id: "gralloc_buffers_counter_span" group_by { column_names: "process_name" column_names: "counter_name" aggregates { column_name: "metric_val" op: MIN result_column_name: "min_val" } aggregates { column_name: "metric_val" op: MAX result_column_name: "max_val" } aggregates { column_name: "metric_val" op: DURATION_WEIGHTED_MEAN result_column_name: "avg_val" } } } bundle_id: "android_gralloc_buffers_per_process_metric" } specs { id: "android_gralloc_buffers_per_process_metric_avg_val" dimensions: "process_name" dimensions: "counter_name" value: "avg_val" query { inner_query_id: "gralloc_buffers_counter_span" group_by { column_names: "process_name" column_names: "counter_name" aggregates { column_name: "metric_val" op: MIN result_column_name: "min_val" } aggregates { column_name: "metric_val" op: MAX result_column_name: "max_val" } aggregates { column_name: "metric_val" op: DURATION_WEIGHTED_MEAN result_column_name: "avg_val" } } } bundle_id: "android_gralloc_buffers_per_process_metric" } }
packages/SystemUI/metrics/perfetto/metrics_specs/tests/metrics_v2_test.py +13 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ from metrics_specs.tests.utils import android_bitmap_metric_trace from metrics_specs.tests.utils import android_sf_critical_work_main_thread_trace from metrics_specs.tests.utils import android_dmabuf_per_process_metric_trace from metrics_specs.tests.utils import android_sf_critical_work_region_sampling_trace from metrics_specs.tests.utils import android_gralloc_buffers_per_process_metric_trace from metrics_specs.tests.utils import test_helper import unittest Loading Loading @@ -73,5 +74,17 @@ class MetricsV2Test(unittest.TestCase): ] ) def test_android_gralloc_buffers_per_process_metric(self): self.helper.verify_metric( spec_file="android_gralloc_buffers_per_process_metric.textproto", trace_proto_bytes = android_gralloc_buffers_per_process_metric_trace.get_proto(), expected_output_file = "android_gralloc_buffers_per_process_metric_output.txt", metric_ids = [ "android_gralloc_buffers_per_process_metric_min_val", "android_gralloc_buffers_per_process_metric_max_val", "android_gralloc_buffers_per_process_metric_avg_val", ] ) if __name__ == '__main__': unittest.main()
packages/SystemUI/metrics/perfetto/metrics_specs/tests/utils/android_gralloc_buffers_per_process_metric_trace.py 0 → 100644 +48 −0 Original line number Diff line number Diff line #!/usr/bin/env python3 # Copyright (C) 2025 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 # # http://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. from metrics_specs.tests.utils import trace_proto_builder from perfetto.protos.perfetto.trace.perfetto_trace_pb2 import Trace def get_proto(): SYSUI_PID = 1000 SYSUI_PROCESS_NAME = "com.android.systemui" LAUNCHER_PID = 2000 LAUNCHER_PROCESS_NAME = "com.google.android.apps.nexuslauncher" trace = Trace() builder = trace_proto_builder.TraceProtoBuilder(trace) # Add all processes builder.add_packet() builder.add_process(pid=SYSUI_PID, ppid=SYSUI_PID, cmdline=SYSUI_PROCESS_NAME, uid=10001) builder.add_process(pid=LAUNCHER_PID, ppid=LAUNCHER_PID, cmdline=LAUNCHER_PROCESS_NAME, uid=20001) # Add counters in the com.android.systemui process builder.add_ftrace_packet(cpu=0) builder.add_atrace_counter(ts=1000, pid=SYSUI_PID, tid=SYSUI_PID, buf="mem.gralloc.buffers", cnt=10) builder.add_ftrace_packet(cpu=0) builder.add_atrace_counter(ts=2000, pid=SYSUI_PID, tid=SYSUI_PID, buf="mem.gralloc.buffers", cnt=20) builder.add_ftrace_packet(cpu=0) builder.add_atrace_counter(ts=1000, pid=SYSUI_PID, tid=SYSUI_PID, buf="Random Counter", cnt=111) # Add counters in the com.google.android.apps.nexuslauncher process builder.add_ftrace_packet(cpu=0) builder.add_atrace_counter(ts=1500, pid=LAUNCHER_PID, tid=LAUNCHER_PID, buf="mem.gralloc.buffers", cnt=15) builder.add_ftrace_packet(cpu=0) builder.add_atrace_counter(ts=2500, pid=LAUNCHER_PID, tid=LAUNCHER_PID, buf="mem.gralloc.buffers", cnt=25) return builder.trace.SerializeToString() No newline at end of file