• 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 {ColumnDef, Sorting} from '../../public/aggregation';
16import {Area, AreaSelection} from '../../public/selection';
17import {Engine} from '../../trace_processor/engine';
18import {CPUSS_ESTIMATE_TRACK_KIND} from '../../public/track_kinds';
19import {AreaSelectionAggregator} from '../../public/selection';
20import {exists} from '../../base/utils';
21
22export class WattsonEstimateSelectionAggregator
23  implements AreaSelectionAggregator
24{
25  readonly id = 'wattson_plugin_estimate_aggregation';
26
27  async createAggregateView(engine: Engine, area: AreaSelection) {
28    await engine.query(`drop view if exists ${this.id};`);
29
30    const estimateTracks: string[] = [];
31    for (const trackInfo of area.tracks) {
32      if (
33        trackInfo?.tags?.kind === CPUSS_ESTIMATE_TRACK_KIND &&
34        exists(trackInfo.tags?.wattson)
35      ) {
36        estimateTracks.push(`${trackInfo.tags.wattson}`);
37      }
38    }
39    if (estimateTracks.length === 0) return false;
40
41    const query = this.getEstimateTracksQuery(area, estimateTracks);
42    engine.query(query);
43
44    return true;
45  }
46
47  getEstimateTracksQuery(
48    area: Area,
49    estimateTracks: ReadonlyArray<string>,
50  ): string {
51    const duration = area.end - area.start;
52    let query = `
53      INCLUDE PERFETTO MODULE wattson.curves.estimates;
54
55      CREATE OR REPLACE PERFETTO TABLE wattson_plugin_ui_selection_window AS
56      SELECT
57        ${area.start} as ts,
58        ${duration} as dur;
59
60      DROP TABLE IF EXISTS wattson_plugin_windowed_cpuss_estimate;
61      CREATE VIRTUAL TABLE wattson_plugin_windowed_cpuss_estimate
62      USING
63        SPAN_JOIN(wattson_plugin_ui_selection_window, _system_state_mw);
64
65      CREATE PERFETTO VIEW ${this.id} AS
66    `;
67
68    // Convert average power track to total energy in UI window, then divide by
69    // duration of window to get average estimated power of the window
70    estimateTracks.forEach((estimateTrack, i) => {
71      if (i != 0) {
72        query += `UNION ALL `;
73      }
74      query += `
75        SELECT
76        '${estimateTrack}' as name,
77        ROUND(SUM(${estimateTrack}_mw * dur) / ${duration}, 3) as power,
78        ROUND(SUM(${estimateTrack}_mw * dur) / 1000000000, 3) as energy
79        FROM wattson_plugin_windowed_cpuss_estimate
80      `;
81    });
82    query += `;`;
83
84    return query;
85  }
86
87  getColumnDefinitions(): ColumnDef[] {
88    return [
89      {
90        title: 'Name',
91        kind: 'STRING',
92        columnConstructor: Uint16Array,
93        columnId: 'name',
94      },
95      {
96        title: 'Power (estimated mW)',
97        kind: 'NUMBER',
98        columnConstructor: Float64Array,
99        columnId: 'power',
100        sum: true,
101      },
102      {
103        title: 'Energy (estimated mWs)',
104        kind: 'NUMBER',
105        columnConstructor: Float64Array,
106        columnId: 'energy',
107        sum: true,
108      },
109    ];
110  }
111
112  async getExtra() {}
113
114  getTabName() {
115    return 'Wattson estimates';
116  }
117
118  getDefaultSorting(): Sorting {
119    return {column: 'name', direction: 'ASC'};
120  }
121}
122