1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 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 */ 15 16import { BaseElement, element } from '../../../../../base-ui/BaseElement'; 17import { LitTable } from '../../../../../base-ui/table/lit-table'; 18import { SelectionParam } from '../../../../bean/BoxSelection'; 19import { XpowerGpuFreqStruct } from '../../../../database/ui-worker/ProcedureWorkerXpowerGpuFreq'; 20import { SpSystemTrace } from '../../../SpSystemTrace'; 21import { SpChartList } from '../../SpChartList'; 22import { TraceRow } from '../../base/TraceRow'; 23import { SortDetail, resizeObserver } from '../SheetUtils'; 24 25@element('tabpane-xpower-gpu-freq') 26export class TabPaneXpowerGpuFreq extends BaseElement { 27 private XpowerGpuFreqTbl: LitTable | null | undefined; 28 private XpowerGpuFreqRange: HTMLLabelElement | null | undefined; 29 private XpowerGpuFreqSource: Array<TabXpowerGpuFreqStruct> = []; 30 private sumCount: number = 0; 31 private tabTitle: HTMLDivElement | undefined | null; 32 private traceRow: TraceRow<XpowerGpuFreqStruct> | undefined | null; 33 private checked: boolean[] = []; 34 private checkedValue: string[] = []; 35 private systemTrace: SpSystemTrace | undefined | null; 36 private spChartList: SpChartList | undefined | null; 37 38 set data(XpowerGpuFreqValue: SelectionParam) { 39 this.init(); 40 this.XpowerGpuFreqTbl!.shadowRoot!.querySelector<HTMLDivElement>('.table')!.style!.height = `${ 41 this.parentElement!.clientHeight - 45 42 }px`; 43 this.XpowerGpuFreqRange!.textContent = `Selected range: ${parseFloat( 44 ((XpowerGpuFreqValue.rightNs - XpowerGpuFreqValue.leftNs) / 1000000.0).toFixed(5) 45 )} ms`; 46 this.traceRow = this.systemTrace!.shadowRoot?.querySelector<TraceRow<XpowerGpuFreqStruct>>( 47 "trace-row[row-id='gpu-frequency']" 48 ); 49 if (!this.traceRow) { 50 this.spChartList = this.systemTrace!.shadowRoot?.querySelector('div > sp-chart-list'); 51 this.traceRow = this.spChartList?.shadowRoot!.querySelector(".root > div > trace-row[row-id='gpu-frequency']"); 52 } 53 this.checked = this.traceRow!.rowSettingCheckedBoxList!; 54 this.checkedValue = this.traceRow!.rowSettingCheckBoxList!; 55 this.getGpuFreqData(XpowerGpuFreqValue).then(); 56 } 57 58 async getGpuFreqData(XpowerGpuFreqValue: SelectionParam): Promise<void> { 59 this.sumCount = 0; 60 let dataSource: Array<TabXpowerGpuFreqStruct> = []; 61 let collect = XpowerGpuFreqValue.xpowerGpuFreqMapData; 62 this.XpowerGpuFreqTbl!.loading = true; 63 for (let key of collect.keys()) { 64 let gpuFreqs = collect.get(key); 65 let res = (await gpuFreqs?.({ 66 startNS: XpowerGpuFreqValue.leftNs, 67 endNS: XpowerGpuFreqValue.rightNs, 68 queryAll: true, 69 })) as XpowerGpuFreqStruct[]; 70 res = res.filter((item) => this.checked[this.checkedValue?.indexOf(item.frequency.toString())]); 71 let sd = this.createTabXpowerGpuFreqStruct(res || []); 72 dataSource = dataSource.concat(sd); 73 } 74 this.XpowerGpuFreqTbl!.loading = false; 75 this.XpowerGpuFreqSource = dataSource; 76 this.XpowerGpuFreqTbl!.recycleDataSource = dataSource; 77 } 78 79 private init(): void { 80 const thTable = this.tabTitle!.querySelector('.th'); 81 const list = thTable!.querySelectorAll('div'); 82 if (this.tabTitle!.hasAttribute('sort')) { 83 this.tabTitle!.removeAttribute('sort'); 84 list.forEach((item) => { 85 item.querySelectorAll('svg').forEach((svg) => { 86 svg.style.display = 'none'; 87 }); 88 }); 89 } 90 } 91 92 initElements(): void { 93 this.systemTrace = document 94 .querySelector('body > sp-application') 95 ?.shadowRoot!.querySelector<SpSystemTrace>('#sp-system-trace'); 96 this.XpowerGpuFreqTbl = this.shadowRoot?.querySelector<LitTable>('#tb-gpu-freq'); 97 this.tabTitle = this.XpowerGpuFreqTbl!.shadowRoot?.querySelector('.thead') as HTMLDivElement; 98 this.XpowerGpuFreqRange = this.shadowRoot?.querySelector('#time-range'); 99 this.XpowerGpuFreqTbl!.addEventListener('column-click', (evt): void => { 100 // @ts-ignore 101 this.sortByColumn(evt.detail); 102 }); 103 } 104 105 connectedCallback(): void { 106 super.connectedCallback(); 107 resizeObserver(this.parentElement!, this.XpowerGpuFreqTbl!); 108 } 109 110 initHtml(): string { 111 return ` 112 <style> 113 .xpower-gpu-freq-label{ 114 margin-bottom: 5px; 115 } 116 :host{ 117 padding: 10px 10px; 118 display: flex; 119 flex-direction: column; 120 } 121 </style> 122 <label id="time-range" class="xpower-gpu-freq-label" style="width: 100%;height: 20px;text-align: end;font-size: 10pt;">Selected range:0.0 ms</label> 123 <lit-table id="tb-gpu-freq" style="height: auto"> 124 <lit-table-column title="Frequency" data-index="frequency" key="frequency" align="flex-start" width="25%" order> 125 </lit-table-column> 126 <lit-table-column title="Count" data-index="count" key="count" align="flex-start" width="1fr" order> 127 </lit-table-column> 128 <lit-table-column title="Avg RunTime(ms)" data-index="avgRunTime" key="avgRunTime" align="flex-start" width="1fr" order> 129 </lit-table-column> 130 <lit-table-column title="Max RunTime(ms)" data-index="maxRunTime" key="maxRunTime" align="flex-start" width="1fr" order> 131 </lit-table-column> 132 <lit-table-column title="Min RunTime(ms)" data-index="minRunTime" key="minRunTime" align="flex-start" width="1fr" order> 133 </lit-table-column> 134 <lit-table-column title="Avg IdleTime(ms)" data-index="avgIdleTime" key="avgIdleTime" align="flex-start" width="1fr" order> 135 </lit-table-column> 136 <lit-table-column title="Max IdleTime(ms)" data-index="maxIdleTime" key="maxIdleTime" align="flex-start" width="1fr" order> 137 </lit-table-column> 138 <lit-table-column title="Min IdleTime(ms)" data-index="minIdleTime" key="minIdleTime" align="flex-start" width="1fr" order> 139 </lit-table-column> 140 </lit-table> 141 `; 142 } 143 144 private setGpuFreqMap(list: Array<XpowerGpuFreqStruct>): Map<number, XpowerGpuFreqStruct[]> { 145 let gpuFreqMap = new Map(); 146 list.forEach((item) => { 147 if (gpuFreqMap.has(item.frequency)) { 148 const data = gpuFreqMap.get(item.frequency)!; 149 data.push(item); 150 } else { 151 const data: XpowerGpuFreqStruct[] = []; 152 data.push(item); 153 gpuFreqMap.set(item.frequency, data); 154 } 155 }); 156 return gpuFreqMap; 157 } 158 159 private setTabXpowerGpuFreqStruct( 160 runTimeValue: number, 161 idleTimeValue: number, 162 tabXpowerGpuFreqStruct: TabXpowerGpuFreqStruct 163 ): TabXpowerGpuFreqStruct { 164 tabXpowerGpuFreqStruct.avgRunTime = parseFloat(runTimeValue.toFixed(2)); 165 tabXpowerGpuFreqStruct.maxRunTime = runTimeValue; 166 tabXpowerGpuFreqStruct.minRunTime = runTimeValue; 167 tabXpowerGpuFreqStruct.avgIdleTime = parseFloat(idleTimeValue.toFixed(2)); 168 tabXpowerGpuFreqStruct.maxIdleTime = idleTimeValue; 169 tabXpowerGpuFreqStruct.minIdleTime = idleTimeValue; 170 return tabXpowerGpuFreqStruct; 171 } 172 private getRunTimeMax(itemArray: XpowerGpuFreqStruct[]): number { 173 let max = itemArray 174 .map((item: { runTime: number }) => item.runTime) 175 .reduce((a: number, b: number) => Math.max(a, b)); 176 return max; 177 } 178 179 private getRunTimeMin(itemArray: XpowerGpuFreqStruct[]): number { 180 let min = itemArray 181 .map((item: { runTime: number }) => item.runTime) 182 .reduce((a: number, b: number) => Math.min(a, b)); 183 return min; 184 } 185 186 private getIdleTimeMax(itemArray: XpowerGpuFreqStruct[]): number { 187 let max = itemArray 188 .map((item: { idleTime: number }) => item.idleTime) 189 .reduce((a: number, b: number) => Math.max(a, b)); 190 return max; 191 } 192 193 private getIdleTimeMin(itemArray: XpowerGpuFreqStruct[]): number { 194 let min = itemArray 195 .map((item: { idleTime: number }) => item.idleTime) 196 .reduce((a: number, b: number) => Math.min(a, b)); 197 return min; 198 } 199 200 createTabXpowerGpuFreqStruct(list: Array<XpowerGpuFreqStruct>): TabXpowerGpuFreqStruct[] { 201 let SelectGpuFreqArray: TabXpowerGpuFreqStruct[] = []; 202 if (list.length > 0) { 203 let gpuFreqMap = this.setGpuFreqMap(list); 204 for (let itemArray of gpuFreqMap.values()) { 205 let tabXpowerGpuFreqStruct = new TabXpowerGpuFreqStruct(); 206 tabXpowerGpuFreqStruct.frequency = itemArray[0].frequency; 207 tabXpowerGpuFreqStruct.count = itemArray.length; 208 if (itemArray.length > 1) { 209 let maxRunTime = this.getRunTimeMax(itemArray); 210 let minRunTime = this.getRunTimeMin(itemArray); // @ts-ignore 211 let sumRunTime: unknown = itemArray.reduce((acc: unknown, obj: { runTime: unknown }) => acc + obj.runTime, 0); // @ts-ignore 212 tabXpowerGpuFreqStruct.avgRunTime = parseFloat((sumRunTime / itemArray.length).toFixed(2)); 213 tabXpowerGpuFreqStruct.maxRunTime = maxRunTime; 214 tabXpowerGpuFreqStruct.minRunTime = minRunTime; 215 let maxIdleTime = this.getIdleTimeMax(itemArray); 216 let minIdleTime = this.getIdleTimeMin(itemArray); // @ts-ignore 217 let sumIdleTime: unknown = itemArray.reduce((acc: unknown, obj: { idleTime: unknown }) => acc + obj.idleTime, 0); // @ts-ignore 218 tabXpowerGpuFreqStruct.avgIdleTime = parseFloat((sumIdleTime / itemArray.length).toFixed(2)); 219 tabXpowerGpuFreqStruct.maxIdleTime = maxIdleTime; 220 tabXpowerGpuFreqStruct.minIdleTime = minIdleTime; 221 } else if (itemArray.length === 1) { 222 tabXpowerGpuFreqStruct = this.setTabXpowerGpuFreqStruct( 223 itemArray[0].runTime, 224 itemArray[0].idleTime, 225 tabXpowerGpuFreqStruct 226 ); 227 } 228 this.sumCount += itemArray.length; 229 SelectGpuFreqArray.push(tabXpowerGpuFreqStruct); 230 } 231 } 232 return SelectGpuFreqArray; 233 } 234 235 private sortByColumn(detail: SortDetail): void { 236 function compare(property: string, sort: number, type: string) { 237 return function ( 238 xpowerCounterLeftData: TabXpowerGpuFreqStruct, 239 xpowerCounterRightData: TabXpowerGpuFreqStruct 240 ): number { 241 if (!xpowerCounterLeftData.frequency || !xpowerCounterRightData.frequency) { 242 return 0; 243 } 244 if (type === 'number') { 245 return sort === 2 // @ts-ignore 246 ? parseFloat(xpowerCounterRightData[property]) - parseFloat(xpowerCounterLeftData[property]) // @ts-ignore 247 : parseFloat(xpowerCounterLeftData[property]) - parseFloat(xpowerCounterRightData[property]); 248 } else { 249 // @ts-ignore 250 if (xpowerCounterRightData[property] > xpowerCounterLeftData[property]) { 251 return sort === 2 ? 1 : -1; 252 } else { 253 // @ts-ignore 254 if (xpowerCounterRightData[property] === xpowerCounterLeftData[property]) { 255 return 0; 256 } else { 257 return sort === 2 ? -1 : 1; 258 } 259 } 260 } 261 }; 262 } 263 this.XpowerGpuFreqSource.sort(compare(detail.key, detail.sort, 'number')); 264 this.XpowerGpuFreqTbl!.recycleDataSource = this.XpowerGpuFreqSource; 265 } 266} 267 268export class TabXpowerGpuFreqStruct { 269 frequency: number = 0; 270 count: number = 0; 271 avgRunTime: number = 0; 272 maxRunTime: number = 0; 273 minRunTime: number = 0; 274 avgIdleTime: number = 0; 275 maxIdleTime: number = 0; 276 minIdleTime: number = 0; 277} 278