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