tp: Metric v2 implementation for Wattson Implemented Wattson metric v2. Refactored and moved essential logics to stdlib, exposing metric-specific logics in metric_specs. Wattson metric v1 protos are heavily nested. v2 flattened the metric proto structure and put most essential data into flat views for metricv2 consumption. bug: 477599147
diff --git a/Android.bp b/Android.bp index f3fa09e..7496e3d 100644 --- a/Android.bp +++ b/Android.bp
@@ -15874,6 +15874,10 @@ "src/trace_processor/perfetto_sql/stdlib/wattson/estimates.sql", "src/trace_processor/perfetto_sql/stdlib/wattson/gpu/estimates.sql", "src/trace_processor/perfetto_sql/stdlib/wattson/gpu/freq_idle.sql", + "src/trace_processor/perfetto_sql/stdlib/wattson/metrics/aggregation.sql", + "src/trace_processor/perfetto_sql/stdlib/wattson/metrics/rails_metrics.sql", + "src/trace_processor/perfetto_sql/stdlib/wattson/metrics/threads_metrics.sql", + "src/trace_processor/perfetto_sql/stdlib/wattson/metrics/windows.sql", "src/trace_processor/perfetto_sql/stdlib/wattson/tasks/attribution.sql", "src/trace_processor/perfetto_sql/stdlib/wattson/tasks/idle_transitions_attribution.sql", "src/trace_processor/perfetto_sql/stdlib/wattson/tasks/task_slices.sql",
diff --git a/BUILD b/BUILD index efea722..caed96d 100644 --- a/BUILD +++ b/BUILD
@@ -3871,6 +3871,10 @@ "src/trace_processor/perfetto_sql/stdlib/wattson/estimates.sql", "src/trace_processor/perfetto_sql/stdlib/wattson/gpu/estimates.sql", "src/trace_processor/perfetto_sql/stdlib/wattson/gpu/freq_idle.sql", + "src/trace_processor/perfetto_sql/stdlib/wattson/metrics/aggregation.sql", + "src/trace_processor/perfetto_sql/stdlib/wattson/metrics/rails_metrics.sql", + "src/trace_processor/perfetto_sql/stdlib/wattson/metrics/threads_metrics.sql", + "src/trace_processor/perfetto_sql/stdlib/wattson/metrics/windows.sql", "src/trace_processor/perfetto_sql/stdlib/wattson/tasks/attribution.sql", "src/trace_processor/perfetto_sql/stdlib/wattson/tasks/idle_transitions_attribution.sql", "src/trace_processor/perfetto_sql/stdlib/wattson/tasks/task_slices.sql",
diff --git a/src/trace_processor/perfetto_sql/stdlib/wattson/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/wattson/BUILD.gn index 264ac9c..9f4f10e 100644 --- a/src/trace_processor/perfetto_sql/stdlib/wattson/BUILD.gn +++ b/src/trace_processor/perfetto_sql/stdlib/wattson/BUILD.gn
@@ -37,6 +37,10 @@ "estimates.sql", "gpu/estimates.sql", "gpu/freq_idle.sql", + "metrics/aggregation.sql", + "metrics/rails_metrics.sql", + "metrics/threads_metrics.sql", + "metrics/windows.sql", "tasks/attribution.sql", "tasks/idle_transitions_attribution.sql", "tasks/task_slices.sql",
diff --git a/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/aggregation.sql b/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/aggregation.sql new file mode 100644 index 0000000..9bc30ab --- /dev/null +++ b/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/aggregation.sql
@@ -0,0 +1,427 @@ +-- +-- Copyright 2026 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. + +INCLUDE PERFETTO MODULE intervals.intersect; + +INCLUDE PERFETTO MODULE wattson.cpu.idle; + +INCLUDE PERFETTO MODULE wattson.device_infos; + +INCLUDE PERFETTO MODULE wattson.estimates; + +INCLUDE PERFETTO MODULE wattson.tasks.attribution; + +INCLUDE PERFETTO MODULE wattson.tasks.idle_transitions_attribution; + +INCLUDE PERFETTO MODULE wattson.utils; + +-- ======================================================== +-- MACRO: _wattson_threads_build_flat_view +-- +-- Calculates energy and power attribution per thread/process for the +-- given time windows. +-- +-- Input: +-- window_table: A table with columns (ts, dur, period_id). +-- +-- Output: +-- Flat table with columns: +-- period_id, period_dur, utid, tid, pid, +-- thread_name, process_name, +-- estimated_mws, estimated_mw, idle_transitions_mws, total_mws +-- ======================================================== +CREATE PERFETTO MACRO _wattson_threads_build_flat_view( + window_table TableOrSubquery +) +RETURNS TableOrSubquery AS +( + -- Active Power Intersection (Intersection of Task Power & Window) + WITH + windowed_active_state AS ( + SELECT + ii.dur, + ii.id_1 AS period_id, + tasks.estimated_mw, + tasks.thread_name, + tasks.process_name, + tasks.tid, + tasks.pid, + tasks.utid + FROM _interval_intersect!( + ( + _ii_subquery!(_estimates_w_tasks_attribution), + (SELECT period_id AS id, * FROM $window_table) + ), + () + ) AS ii + JOIN _estimates_w_tasks_attribution AS tasks + ON tasks._auto_id = id_0 + ), + -- Aggregate Active Power per Thread per Period + active_summary AS ( + SELECT + period_id, + utid, + -- Metadata (take min/max as they are constant per utid) + min(thread_name) AS thread_name, + min(process_name) AS process_name, + min(tid) AS tid, + min(pid) AS pid, + -- Calculations + sum(estimated_mw * dur) / 1e9 AS active_mws, + -- Keep for power calc + sum(estimated_mw * dur) AS total_mw_ns + FROM windowed_active_state + GROUP BY + period_id, + utid + ), + -- Calculate Idle Cost (Join against the specific window constraints) + idle_summary AS ( + SELECT + w.period_id, + cost.utid, + sum(cost.idle_cost_mws) AS idle_mws + FROM $window_table AS w, _filter_idle_attribution(w.ts, w.dur) AS cost + GROUP BY + w.period_id, + cost.utid + ) + -- Final Join & Calculation + SELECT + a.period_id, + w.dur AS period_dur, + a.utid, + a.tid, + a.pid, + coalesce(a.thread_name, 'Thread ' || a.tid) AS thread_name, + coalesce(a.process_name, '') AS process_name, + -- Metrics + a.active_mws AS estimated_mws, + -- Power = Energy / Window Duration + ( + a.total_mw_ns / w.dur + ) AS estimated_mw, + coalesce(i.idle_mws, 0) AS idle_transitions_mws, + ( + a.active_mws + coalesce(i.idle_mws, 0) + ) AS total_mws + FROM active_summary AS a + JOIN $window_table AS w + ON a.period_id = w.period_id + LEFT JOIN idle_summary AS i + ON a.period_id = i.period_id AND a.utid = i.utid +); + +-- ======================================================== +-- MACRO: _wattson_base_components_avg_mw +-- +-- Low-level macro to calculate base power components average mW. +-- +-- Input: +-- window_table: A table with columns (ts, dur, period_id). +-- +-- Output: +-- Wide table with CPU policy, average power per core, DSU, and GPU. +-- ======================================================== +CREATE PERFETTO MACRO _wattson_base_components_avg_mw( + window_table TableOrSubquery +) +RETURNS TableOrSubquery AS +( + SELECT + ( + SELECT + m.policy + FROM _dev_cpu_policy_map AS m + WHERE + m.cpu = 0 + ) AS cpu0_poli, + ( + SELECT + m.policy + FROM _dev_cpu_policy_map AS m + WHERE + m.cpu = 1 + ) AS cpu1_poli, + ( + SELECT + m.policy + FROM _dev_cpu_policy_map AS m + WHERE + m.cpu = 2 + ) AS cpu2_poli, + ( + SELECT + m.policy + FROM _dev_cpu_policy_map AS m + WHERE + m.cpu = 3 + ) AS cpu3_poli, + ( + SELECT + m.policy + FROM _dev_cpu_policy_map AS m + WHERE + m.cpu = 4 + ) AS cpu4_poli, + ( + SELECT + m.policy + FROM _dev_cpu_policy_map AS m + WHERE + m.cpu = 5 + ) AS cpu5_poli, + ( + SELECT + m.policy + FROM _dev_cpu_policy_map AS m + WHERE + m.cpu = 6 + ) AS cpu6_poli, + ( + SELECT + m.policy + FROM _dev_cpu_policy_map AS m + WHERE + m.cpu = 7 + ) AS cpu7_poli, + sum(ii.dur * ss.cpu0_mw) / nullif(sum(ii.dur), 0) AS cpu0_mw, + sum(ii.dur * ss.cpu1_mw) / nullif(sum(ii.dur), 0) AS cpu1_mw, + sum(ii.dur * ss.cpu2_mw) / nullif(sum(ii.dur), 0) AS cpu2_mw, + sum(ii.dur * ss.cpu3_mw) / nullif(sum(ii.dur), 0) AS cpu3_mw, + sum(ii.dur * ss.cpu4_mw) / nullif(sum(ii.dur), 0) AS cpu4_mw, + sum(ii.dur * ss.cpu5_mw) / nullif(sum(ii.dur), 0) AS cpu5_mw, + sum(ii.dur * ss.cpu6_mw) / nullif(sum(ii.dur), 0) AS cpu6_mw, + sum(ii.dur * ss.cpu7_mw) / nullif(sum(ii.dur), 0) AS cpu7_mw, + sum(ii.dur * ss.dsu_scu_mw) / nullif(sum(ii.dur), 0) AS dsu_scu_mw, + sum(ii.dur * ss.gpu_mw) / nullif(sum(ii.dur), 0) AS gpu_mw, + sum(ii.dur) AS period_dur, + ii.id_0 AS period_id + FROM _interval_intersect!( + ( + (SELECT period_id AS id, * FROM $window_table), + _ii_subquery!(_system_state_mw) + ), + () + ) AS ii + JOIN _system_state_mw AS ss + ON ss._auto_id = id_1 + GROUP BY + period_id +); + +-- ======================================================== +-- MACRO: _wattson_rail_build_flat_view +-- +-- Flattening and unpivoting of rail data into a standard breakdown. +-- +-- Input: +-- window_table: A table with columns (ts, dur, period_id). +-- +-- Output: +-- Flat breakdown including CORE, POLICY, DSU and SUBSYSTEM TOTAL. +-- ======================================================== +CREATE PERFETTO MACRO _wattson_rail_build_flat_view( + window_table TableOrSubquery +) +RETURNS TableOrSubquery AS +( + -- 1. Cache base components + WITH + base_components AS ( + SELECT + * + FROM _wattson_base_components_avg_mw!($window_table) + ), + -- 2. Unpivot CPU columns + cpu_unpivoted AS ( + SELECT + period_id, + period_dur, + 0 AS cpu_id, + cpu0_poli AS policy_id, + cpu0_mw AS mw + FROM base_components + WHERE + cpu0_mw IS NOT NULL + UNION ALL + SELECT + period_id, + period_dur, + 1, + cpu1_poli, + cpu1_mw + FROM base_components + WHERE + cpu1_mw IS NOT NULL + UNION ALL + SELECT + period_id, + period_dur, + 2, + cpu2_poli, + cpu2_mw + FROM base_components + WHERE + cpu2_mw IS NOT NULL + UNION ALL + SELECT + period_id, + period_dur, + 3, + cpu3_poli, + cpu3_mw + FROM base_components + WHERE + cpu3_mw IS NOT NULL + UNION ALL + SELECT + period_id, + period_dur, + 4, + cpu4_poli, + cpu4_mw + FROM base_components + WHERE + cpu4_mw IS NOT NULL + UNION ALL + SELECT + period_id, + period_dur, + 5, + cpu5_poli, + cpu5_mw + FROM base_components + WHERE + cpu5_mw IS NOT NULL + UNION ALL + SELECT + period_id, + period_dur, + 6, + cpu6_poli, + cpu6_mw + FROM base_components + WHERE + cpu6_mw IS NOT NULL + UNION ALL + SELECT + period_id, + period_dur, + 7, + cpu7_poli, + cpu7_mw + FROM base_components + WHERE + cpu7_mw IS NOT NULL + ), + -- 3. Build basic Flat View (encapsulate in CTE to reuse logic for Total calculation) + flat_view_raw AS ( + -- A. CPU Cores + SELECT + CAST(c.period_id AS STRING) AS period_name, + 'CPU' AS subsystem, + 'CORE' AS breakdown_type, + c.cpu_id AS component_id, + c.policy_id AS parent_id, + c.mw AS estimated_mw, + ( + c.mw * c.period_dur / 1e9 + ) AS estimated_mws + FROM cpu_unpivoted AS c + UNION ALL + -- B. CPU Policies + SELECT + CAST(c.period_id AS STRING) AS period_name, + 'CPU' AS subsystem, + 'POLICY' AS breakdown_type, + c.policy_id AS component_id, + NULL AS parent_id, + sum(c.mw) AS estimated_mw, + sum(c.mw * c.period_dur / 1e9) AS estimated_mws + FROM cpu_unpivoted AS c + GROUP BY + c.period_id, + c.period_dur, + c.policy_id + UNION ALL + -- C. DSU/SCU + SELECT + CAST(base.period_id AS STRING) AS period_name, + 'CPU' AS subsystem, + 'DSU' AS breakdown_type, + NULL AS component_id, + NULL AS parent_id, + base.dsu_scu_mw AS estimated_mw, + ( + base.dsu_scu_mw * base.period_dur / 1e9 + ) AS estimated_mws + FROM base_components AS base + WHERE + base.dsu_scu_mw IS NOT NULL + UNION ALL + -- D. GPU Subsystem + SELECT + CAST(base.period_id AS STRING) AS period_name, + 'GPU' AS subsystem, + 'TOTAL' AS breakdown_type, + NULL AS component_id, + NULL AS parent_id, + base.gpu_mw AS estimated_mw, + ( + base.gpu_mw * base.period_dur / 1e9 + ) AS estimated_mws + FROM base_components AS base + WHERE + base.gpu_mw IS NOT NULL + ) + -- 4. Final output: Raw Data + Computed CPU Total + SELECT + * + FROM flat_view_raw + UNION ALL + -- E. CPU TOTAL (Auto-calculated) + -- Sum only Policy and DSU (exclude Cores to avoid double counting) + SELECT + period_name, + subsystem, + 'TOTAL' AS breakdown_type, + NULL AS component_id, + NULL AS parent_id, + sum(estimated_mw) AS estimated_mw, + sum(estimated_mws) AS estimated_mws + FROM flat_view_raw + WHERE + subsystem = 'CPU' AND breakdown_type IN ('POLICY', 'DSU') + GROUP BY + period_name, + subsystem +); + +-- ======================================================== +-- VIEW: _wattson_metric_metadata +-- +-- Shared metadata for all Wattson metrics. +-- ======================================================== +CREATE PERFETTO VIEW _wattson_metric_metadata AS +SELECT + 4 AS metric_version, + 1 AS power_model_version, + CAST(NOT EXISTS( + SELECT + 1 + FROM _wattson_cpuidle_counters_exist + ) AS INTEGER) AS is_crude_estimate;
diff --git a/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/rails_metrics.sql b/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/rails_metrics.sql new file mode 100644 index 0000000..3d29d1f --- /dev/null +++ b/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/rails_metrics.sql
@@ -0,0 +1,46 @@ +-- +-- Copyright 2026 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. + +INCLUDE PERFETTO MODULE wattson.metrics.aggregation; + +INCLUDE PERFETTO MODULE wattson.metrics.windows; + +-- ======================================================== +-- Wattson rail aggregation views for various time windows. +-- ======================================================== + +-- Wattson rail aggregation for Marker window +CREATE PERFETTO VIEW _wattson_rails_marker AS +SELECT + * +FROM _wattson_rail_build_flat_view!(_wattson_window_marker); + +-- Wattson rail aggregation for Full Trace +CREATE PERFETTO VIEW _wattson_rails_trace AS +SELECT + * +FROM _wattson_rail_build_flat_view!(_wattson_window_trace); + +-- Wattson rail aggregation for Startup +CREATE PERFETTO VIEW _wattson_rails_startup AS +SELECT + * +FROM _wattson_rail_build_flat_view!(_wattson_window_startup); + +-- Wattson rail aggregation for CUJ +CREATE PERFETTO VIEW _wattson_rails_cuj AS +SELECT + * +FROM _wattson_rail_build_flat_view!(_wattson_window_cuj);
diff --git a/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/threads_metrics.sql b/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/threads_metrics.sql new file mode 100644 index 0000000..3caaa54 --- /dev/null +++ b/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/threads_metrics.sql
@@ -0,0 +1,46 @@ +-- +-- Copyright 2026 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. + +INCLUDE PERFETTO MODULE wattson.metrics.aggregation; + +INCLUDE PERFETTO MODULE wattson.metrics.windows; + +-- ======================================================== +-- Wattson thread aggregation views for various time windows. +-- ======================================================== + +-- Wattson thread aggregation for Marker window +CREATE PERFETTO VIEW _wattson_threads_marker AS +SELECT + * +FROM _wattson_threads_build_flat_view!(_wattson_window_marker); + +-- Wattson thread aggregation for Full Trace +CREATE PERFETTO VIEW _wattson_threads_trace AS +SELECT + * +FROM _wattson_threads_build_flat_view!(_wattson_window_trace); + +-- Wattson thread aggregation for Startup +CREATE PERFETTO VIEW _wattson_threads_startup AS +SELECT + * +FROM _wattson_threads_build_flat_view!(_wattson_window_startup); + +-- Wattson thread aggregation for CUJ +CREATE PERFETTO VIEW _wattson_threads_cuj AS +SELECT + * +FROM _wattson_threads_build_flat_view!(_wattson_window_cuj);
diff --git a/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/windows.sql b/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/windows.sql new file mode 100644 index 0000000..905a2ee --- /dev/null +++ b/src/trace_processor/perfetto_sql/stdlib/wattson/metrics/windows.sql
@@ -0,0 +1,55 @@ +-- +-- Copyright 2026 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. + +INCLUDE PERFETTO MODULE android.cujs.base; + +INCLUDE PERFETTO MODULE android.startup.startups; + +INCLUDE PERFETTO MODULE wattson.utils; + +-- ======================================================== +-- Window definitions for Wattson metric analysis. +-- ======================================================== + +-- Standardized window for Wattson markers +CREATE PERFETTO VIEW _wattson_window_marker AS +SELECT + ts, + dur, + 1 AS period_id +FROM _wattson_markers_window; + +-- Standardized window for the full trace duration +CREATE PERFETTO VIEW _wattson_window_trace AS +SELECT + trace_start() AS ts, + trace_dur() AS dur, + 1 AS period_id; + +-- Standardized window for Android app startups +CREATE PERFETTO VIEW _wattson_window_startup AS +SELECT + ts, + dur, + startup_id AS period_id +FROM android_startups; + +-- Standardized window for Android CUJs +CREATE PERFETTO VIEW _wattson_window_cuj AS +SELECT + ts, + dur, + cuj_id AS period_id +FROM android_jank_cuj;
diff --git a/src/trace_processor/perfetto_sql/stdlib/wattson/textprotos/rails.textproto b/src/trace_processor/perfetto_sql/stdlib/wattson/textprotos/rails.textproto new file mode 100644 index 0000000..b2d03ae --- /dev/null +++ b/src/trace_processor/perfetto_sql/stdlib/wattson/textprotos/rails.textproto
@@ -0,0 +1,319 @@ +# +# Copyright 2026 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. + +metric_spec { + id: "wattson_metadata" + dimensions: "metric_version" + dimensions: "power_model_version" + value: "is_crude_estimate" + query: { + table: { + table_name: "_wattson_metric_metadata" + } + referenced_modules: "wattson.metrics.aggregation" + } +} + +metric_template_spec { + id_prefix: "wattson_rails_marker" + + # ========================================================== + # Dimensions + # ========================================================== + + # 1. Period Identifier + dimensions_specs { + name: "period_name" + type: STRING + } + + # 2. Hardware Subsystem + dimensions_specs { + name: "subsystem" + type: STRING + } + + # 3. Hierarchy Type + dimensions_specs { + name: "breakdown_type" + type: STRING + } + + # 4. Component Identifier + dimensions_specs { + name: "component_id" + type: INT64 + display_name: "ID" + } + + # 5. Parent Relation + dimensions_specs { + name: "parent_id" + type: INT64 + display_name: "Cluster ID" + } + + # ========================================================== + # Values + # ========================================================== + + # Metric 1: Energy + value_column_specs { + name: "estimated_mws" + display_name: "Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + + # Metric 2: Power + value_column_specs { + name: "estimated_mw" + display_name: "Average Power" + unit: MILLI_WATTS + polarity: LOWER_IS_BETTER + } + + # ========================================================== + # Query (Data Source) + # ========================================================== + + query { + table { + table_name: "_wattson_rails_marker" + } + referenced_modules: "wattson.metrics.rails_metrics" + } + + dimension_uniqueness: UNIQUE +} + +metric_template_spec { + id_prefix: "wattson_rails_trace" + + # ========================================================== + # Dimensions + # ========================================================== + + # 1. Period Identifier + dimensions_specs { + name: "period_name" + type: STRING + } + + # 2. Hardware Subsystem + dimensions_specs { + name: "subsystem" + type: STRING + } + + # 3. Hierarchy Type + dimensions_specs { + name: "breakdown_type" + type: STRING + } + + # 4. Component Identifier + dimensions_specs { + name: "component_id" + type: INT64 + display_name: "ID" + } + + # 5. Parent Relation + dimensions_specs { + name: "parent_id" + type: INT64 + display_name: "Cluster ID" + } + + # ========================================================== + # Values + # ========================================================== + + # Metric 1: Energy + value_column_specs { + name: "estimated_mws" + display_name: "Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + + # Metric 2: Power + value_column_specs { + name: "estimated_mw" + display_name: "Average Power" + unit: MILLI_WATTS + polarity: LOWER_IS_BETTER + } + + # ========================================================== + # Query (Data Source) + # ========================================================== + + query { + table { + table_name: "_wattson_rails_trace" + } + referenced_modules: "wattson.metrics.rails_metrics" + } + + dimension_uniqueness: UNIQUE +} + +metric_template_spec { + id_prefix: "wattson_rails_startup" + + # ========================================================== + # Dimensions + # ========================================================== + + # 1. Period Identifier + dimensions_specs { + name: "period_name" + type: STRING + } + + # 2. Hardware Subsystem + dimensions_specs { + name: "subsystem" + type: STRING + } + + # 3. Hierarchy Type + dimensions_specs { + name: "breakdown_type" + type: STRING + } + + # 4. Component Identifier + dimensions_specs { + name: "component_id" + type: INT64 + display_name: "ID" + } + + # 5. Parent Relation + dimensions_specs { + name: "parent_id" + type: INT64 + display_name: "Cluster ID" + } + + # ========================================================== + # Values + # ========================================================== + + # Metric 1: Energy + value_column_specs { + name: "estimated_mws" + display_name: "Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + + # Metric 2: Power + value_column_specs { + name: "estimated_mw" + display_name: "Average Power" + unit: MILLI_WATTS + polarity: LOWER_IS_BETTER + } + + # ========================================================== + # Query (Data Source) + # ========================================================== + + query { + table { + table_name: "_wattson_rails_startup" + } + referenced_modules: "wattson.metrics.rails_metrics" + } + + dimension_uniqueness: UNIQUE +} + +metric_template_spec { + id_prefix: "wattson_rails_cuj" + + # ========================================================== + # Dimensions + # ========================================================== + + # 1. Period Identifier + dimensions_specs { + name: "period_name" + type: STRING + } + + # 2. Hardware Subsystem + dimensions_specs { + name: "subsystem" + type: STRING + } + + # 3. Hierarchy Type + dimensions_specs { + name: "breakdown_type" + type: STRING + } + + # 4. Component Identifier + dimensions_specs { + name: "component_id" + type: INT64 + display_name: "ID" + } + + # 5. Parent Relation + dimensions_specs { + name: "parent_id" + type: INT64 + display_name: "Cluster ID" + } + + # ========================================================== + # Values + # ========================================================== + + # Metric 1: Energy + value_column_specs { + name: "estimated_mws" + display_name: "Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + + # Metric 2: Power + value_column_specs { + name: "estimated_mw" + display_name: "Average Power" + unit: MILLI_WATTS + polarity: LOWER_IS_BETTER + } + + # ========================================================== + # Query (Data Source) + # ========================================================== + + query { + table { + table_name: "_wattson_rails_cuj" + } + referenced_modules: "wattson.metrics.rails_metrics" + } + + dimension_uniqueness: UNIQUE +}
diff --git a/src/trace_processor/perfetto_sql/stdlib/wattson/textprotos/threads.textproto b/src/trace_processor/perfetto_sql/stdlib/wattson/textprotos/threads.textproto new file mode 100644 index 0000000..79386dc --- /dev/null +++ b/src/trace_processor/perfetto_sql/stdlib/wattson/textprotos/threads.textproto
@@ -0,0 +1,227 @@ +# +# Copyright 2026 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. + +metric_spec { + id: "wattson_metadata" + dimensions: "metric_version" + dimensions: "power_model_version" + value: "is_crude_estimate" + query: { + table: { + table_name: "_wattson_metric_metadata" + } + referenced_modules: "wattson.metrics.aggregation" + } +} + +# Marker +metric_template_spec { + id_prefix: "wattson_threads_marker" + + # --- Dimensions --- + # 1. Period + dimensions_specs { name: "period_name" type: STRING } + dimensions_specs { name: "period_id" type: INT64 } + + # 2. Process Info + dimensions_specs { name: "process_name" type: STRING } + dimensions_specs { name: "pid" type: INT64 } + + # 3. Thread Info + dimensions_specs { name: "thread_name" type: STRING } + dimensions_specs { name: "tid" type: INT64 } + + # --- Values --- + value_column_specs { + name: "estimated_mws" + display_name: "Active Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "estimated_mw" + display_name: "Active Power" + unit: MILLI_WATTS + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "idle_transitions_mws" + display_name: "Idle Overhead (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "total_mws" + display_name: "Total Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + + # --- Source --- + query { + table { table_name: "_wattson_threads_marker" } + referenced_modules: "wattson.metrics.threads_metrics" + } +} + +# Full Trace +metric_template_spec { + id_prefix: "wattson_threads_trace" + + # --- Dimensions --- + # 1. Period + dimensions_specs { name: "period_name" type: STRING } + dimensions_specs { name: "period_id" type: INT64 } + + # 2. Process Info + dimensions_specs { name: "process_name" type: STRING } + dimensions_specs { name: "pid" type: INT64 } + + # 3. Thread Info + dimensions_specs { name: "thread_name" type: STRING } + dimensions_specs { name: "tid" type: INT64 } + + # --- Values --- + value_column_specs { + name: "estimated_mws" + display_name: "Active Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "estimated_mw" + display_name: "Active Power" + unit: MILLI_WATTS + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "idle_transitions_mws" + display_name: "Idle Overhead (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "total_mws" + display_name: "Total Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + + # --- Source --- + query { + table { table_name: "_wattson_threads_trace" } + referenced_modules: "wattson.metrics.threads_metrics" + } +} + +# App Startup +metric_template_spec { + id_prefix: "wattson_threads_startup" + + # --- Dimensions --- + # 1. Period + dimensions_specs { name: "period_name" type: STRING } + dimensions_specs { name: "period_id" type: INT64 } + + # 2. Process Info + dimensions_specs { name: "process_name" type: STRING } + dimensions_specs { name: "pid" type: INT64 } + + # 3. Thread Info + dimensions_specs { name: "thread_name" type: STRING } + dimensions_specs { name: "tid" type: INT64 } + + # --- Values --- + value_column_specs { + name: "estimated_mws" + display_name: "Active Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "estimated_mw" + display_name: "Active Power" + unit: MILLI_WATTS + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "idle_transitions_mws" + display_name: "Idle Overhead (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "total_mws" + display_name: "Total Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + + # --- Source --- + query { + table { table_name: "_wattson_threads_startup" } + referenced_modules: "wattson.metrics.threads_metrics" + } +} + +# CUJ +metric_template_spec { + id_prefix: "wattson_threads_cuj" + + # --- Dimensions --- + # 1. Period + dimensions_specs { name: "period_name" type: STRING } + dimensions_specs { name: "period_id" type: INT64 } + + # 2. Process Info + dimensions_specs { name: "process_name" type: STRING } + dimensions_specs { name: "pid" type: INT64 } + + # 3. Thread Info + dimensions_specs { name: "thread_name" type: STRING } + dimensions_specs { name: "tid" type: INT64 } + + # --- Values --- + value_column_specs { + name: "estimated_mws" + display_name: "Active Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "estimated_mw" + display_name: "Active Power" + unit: MILLI_WATTS + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "idle_transitions_mws" + display_name: "Idle Overhead (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + value_column_specs { + name: "total_mws" + display_name: "Total Energy (mWs)" + custom_unit: "mWs" + polarity: LOWER_IS_BETTER + } + + # --- Source --- + query { + table { table_name: "_wattson_threads_cuj" } + referenced_modules: "wattson.metrics.threads_metrics" + } +}