xref: /aosp_15_r20/external/perfetto/ui/src/plugins/org.kernel.Wattson/process_aggregator.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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_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 _per_process_idle_attribution AS
49      SELECT
50        ROUND(SUM(idle_cost_mws), 2) as idle_cost_mws,
51        upid
52      FROM _filter_idle_attribution(${area.start}, ${duration})
53      WHERE cpu in ${cpusCsv}
54      GROUP BY upid;
55
56      -- Grouped by UPID and made CPU agnostic
57      CREATE VIEW ${this.id} AS
58      SELECT
59        ROUND(SUM(total_pws) / ${duration}, 2) as active_mw,
60        ROUND(SUM(total_pws) / 1000000000, 2) as active_mws,
61        COALESCE(idle_cost_mws, 0) as idle_cost_mws,
62        ROUND(
63          COALESCE(idle_cost_mws, 0) + SUM(total_pws) / 1000000000,
64          2
65        ) as total_mws,
66        pid,
67        process_name
68      FROM _unioned_per_cpu_total
69      LEFT JOIN _per_process_idle_attribution USING (upid)
70      GROUP BY upid;
71    `);
72
73    return true;
74  }
75
76  getColumnDefinitions(): ColumnDef[] {
77    return [
78      {
79        title: 'Process Name',
80        kind: 'STRING',
81        columnConstructor: Uint16Array,
82        columnId: 'process_name',
83      },
84      {
85        title: 'PID',
86        kind: 'NUMBER',
87        columnConstructor: Uint16Array,
88        columnId: 'pid',
89      },
90      {
91        title: 'Active power (estimated mW)',
92        kind: 'NUMBER',
93        columnConstructor: Float64Array,
94        columnId: 'active_mw',
95        sum: true,
96      },
97      {
98        title: 'Active energy (estimated mWs)',
99        kind: 'NUMBER',
100        columnConstructor: Float64Array,
101        columnId: 'active_mws',
102        sum: true,
103      },
104      {
105        title: 'Idle transitions overhead (estimated mWs)',
106        kind: 'NUMBER',
107        columnConstructor: Float64Array,
108        columnId: 'idle_cost_mws',
109        sum: true,
110      },
111      {
112        title: 'Total energy (estimated mWs)',
113        kind: 'NUMBER',
114        columnConstructor: Float64Array,
115        columnId: 'total_mws',
116        sum: true,
117      },
118    ];
119  }
120
121  async getExtra() {}
122
123  getTabName() {
124    return 'Wattson by process';
125  }
126
127  getDefaultSorting(): Sorting {
128    return {column: 'active_mws', direction: 'DESC'};
129  }
130}
131