• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2024 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import {exists} from '../../base/utils';
16import {ColumnDef, Sorting} from '../../public/aggregation';
17import {AreaSelection, AreaSelectionAggregator} from '../../public/selection';
18import {CPU_SLICE_TRACK_KIND} from '../../public/track_kinds';
19import {Engine} from '../../trace_processor/engine';
20
21export class WattsonProcessSelectionAggregator
22  implements AreaSelectionAggregator
23{
24  readonly id = 'wattson_plugin_process_aggregation';
25
26  async createAggregateView(engine: Engine, area: AreaSelection) {
27    await engine.query(`drop view if exists ${this.id};`);
28
29    const selectedCpus: number[] = [];
30    for (const trackInfo of area.tracks) {
31      trackInfo?.tags?.kind === CPU_SLICE_TRACK_KIND &&
32        exists(trackInfo.tags.cpu) &&
33        selectedCpus.push(trackInfo.tags.cpu);
34    }
35    if (selectedCpus.length === 0) return false;
36
37    const cpusCsv = `(` + selectedCpus.join() + `)`;
38    const duration = area.end - area.start;
39
40    // Prerequisite tables are already generated by Wattson thread aggregation,
41    // which is run prior to execution of this module
42    engine.query(`
43      INCLUDE PERFETTO MODULE wattson.curves.idle_attribution;
44      INCLUDE PERFETTO MODULE wattson.curves.estimates;
45
46      -- Only get idle attribution in user defined window and filter by selected
47      -- CPUs and GROUP BY process
48      CREATE OR REPLACE PERFETTO TABLE
49      wattson_plugin_per_process_idle_attribution AS
50      SELECT
51        SUM(idle_cost_mws) as idle_cost_mws,
52        upid
53      FROM _filter_idle_attribution(${area.start}, ${duration})
54      WHERE cpu in ${cpusCsv}
55      GROUP BY upid;
56
57      -- Grouped by UPID and made CPU agnostic
58      CREATE PERFETTO VIEW ${this.id} AS
59      WITH base AS (
60        SELECT
61          ROUND(SUM(total_pws) / ${duration}, 3) as active_mw,
62          ROUND(SUM(total_pws) / 1000000000, 3) as active_mws,
63          ROUND(COALESCE(idle_cost_mws, 0), 3) as idle_cost_mws,
64          ROUND(
65            COALESCE(idle_cost_mws, 0) + SUM(total_pws) / 1000000000,
66            3
67          ) as total_mws,
68          pid,
69          process_name
70        FROM wattson_plugin_unioned_per_cpu_total
71        LEFT JOIN wattson_plugin_per_process_idle_attribution USING (upid)
72        GROUP BY upid
73      ),
74      secondary AS (
75        SELECT pid,
76          ROUND(100 * (total_mws) / (SUM(total_mws) OVER()), 3)
77            AS percent_of_total_energy
78        FROM base
79        GROUP BY pid
80      )
81      select *
82        from base INNER JOIN secondary
83        USING (pid);
84    `);
85
86    return true;
87  }
88
89  getColumnDefinitions(): ColumnDef[] {
90    return [
91      {
92        title: 'Process Name',
93        kind: 'STRING',
94        columnConstructor: Uint16Array,
95        columnId: 'process_name',
96      },
97      {
98        title: 'PID',
99        kind: 'NUMBER',
100        columnConstructor: Uint16Array,
101        columnId: 'pid',
102      },
103      {
104        title: 'Active power (estimated mW)',
105        kind: 'NUMBER',
106        columnConstructor: Float64Array,
107        columnId: 'active_mw',
108        sum: true,
109      },
110      {
111        title: 'Active energy (estimated mWs)',
112        kind: 'NUMBER',
113        columnConstructor: Float64Array,
114        columnId: 'active_mws',
115        sum: true,
116      },
117      {
118        title: 'Idle transitions overhead (estimated mWs)',
119        kind: 'NUMBER',
120        columnConstructor: Float64Array,
121        columnId: 'idle_cost_mws',
122        sum: false,
123      },
124      {
125        title: 'Total energy (estimated mWs)',
126        kind: 'NUMBER',
127        columnConstructor: Float64Array,
128        columnId: 'total_mws',
129        sum: true,
130      },
131      {
132        title: '% of total energy',
133        kind: 'PERCENT',
134        columnConstructor: Float64Array,
135        columnId: 'percent_of_total_energy',
136        sum: false,
137      },
138    ];
139  }
140
141  async getExtra() {}
142
143  getTabName() {
144    return 'Wattson by process';
145  }
146
147  getDefaultSorting(): Sorting {
148    return {column: 'active_mws', direction: 'DESC'};
149  }
150}
151