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 { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar'; 20import { resizeObserver } from '../SheetUtils'; 21import { SpSystemTrace } from '../../../SpSystemTrace'; 22import { drawLines } from '../../../../database/ui-worker/ProcedureWorkerCommon'; 23import { TraceRow } from '../../base/TraceRow'; 24import { CpuFreqStruct } from '../../../../database/ui-worker/ProcedureWorkerFreq'; 25import { CpuStateStruct } from '../../../../database/ui-worker/cpu/ProcedureWorkerCpuState'; 26import { getTabPaneCounterSampleData } from '../../../../database/sql/Cpu.sql'; 27 28@element('tabpane-counter-sample') 29export class TabPaneCounterSample extends BaseElement { 30 private counterSampleTbl: LitTable | null | undefined; 31 private range: HTMLLabelElement | null | undefined; 32 private loadDataInCache: boolean = true; 33 private selectionParam: SelectionParam | null | undefined; 34 private sampleProgressEL: LitProgressBar | null | undefined; 35 private counterLoadingPage: unknown; 36 private counterLoadingList: number[] = []; 37 private counterSampleSource: unknown[] = []; 38 private counterSortKey: string = 'counter'; 39 private counterSortType: number = 0; 40 private systemTrace: SpSystemTrace | undefined | null; 41 // @ts-ignore 42 private _rangeRow: Array<TraceRow<unknown>> | undefined | null; 43 44 set data(counterSampleValue: SelectionParam | unknown) { 45 if (counterSampleValue === this.selectionParam) { 46 return; 47 } 48 this.sampleProgressEL!.loading = true; 49 // @ts-ignore 50 this.counterLoadingPage.style.visibility = 'visible'; 51 // @ts-ignore 52 this.selectionParam = counterSampleValue; 53 if (this.counterSampleTbl) { 54 // @ts-ignore 55 this.counterSampleTbl.shadowRoot.querySelector('.table').style.height = `${ 56 this.parentElement!.clientHeight - 25 57 }px`; 58 } 59 this.queryDataByDB(counterSampleValue); 60 } 61 // @ts-ignore 62 set rangeTraceRow(rangeRow: Array<TraceRow<unknown>> | undefined) { 63 this._rangeRow = rangeRow; 64 } 65 66 initElements(): void { 67 this.sampleProgressEL = this.shadowRoot!.querySelector<LitProgressBar>('.progressCounter'); 68 this.counterLoadingPage = this.shadowRoot!.querySelector('.loadingCounter'); 69 this.counterSampleTbl = this.shadowRoot!.querySelector<LitTable>('#tb-counter-sample'); 70 this.systemTrace = document 71 .querySelector('body > sp-application') 72 ?.shadowRoot!.querySelector<SpSystemTrace>('#sp-system-trace'); 73 this.counterSampleTbl!.addEventListener('column-click', (evt): void => { 74 // @ts-ignore 75 this.counterSortKey = evt.detail.key; 76 // @ts-ignore 77 this.counterSortType = evt.detail.sort; 78 // @ts-ignore 79 this.sortTable(evt.detail.key, evt.detail.sort); 80 }); 81 this.rowClickEvent(); 82 } 83 84 private rowClickEvent(): void { 85 this.counterSampleTbl!.addEventListener('row-click', (evt): void => { 86 // @ts-ignore 87 let data = evt.detail.data; 88 let path = new Path2D(); 89 if (this._rangeRow && this._rangeRow!.length > 0) { 90 let rangeTraceRow = this._rangeRow!.filter(function (item) { 91 return item.name.includes('State'); 92 }); 93 let cpuStateFilter = []; 94 for (let row of rangeTraceRow!) { 95 let context = row.collect ? this.systemTrace!.canvasFavoritePanelCtx! : this.systemTrace!.canvasPanelCtx!; 96 cpuStateFilter.push(...row.dataListCache); 97 row.canvasSave(context); // @ts-ignore 98 context.clearRect(row.frame.x, row.frame.y, row.frame.width, row.frame.height); // @ts-ignore 99 drawLines(context!, TraceRow.range?.xs || [], row.frame.height, this.systemTrace!.timerShaftEL!.lineColor()); 100 if (row.name.includes('State') && parseInt(row.name.replace(/[^\d]/g, ' ')) === data.cpu) { 101 CpuFreqStruct.hoverCpuFreqStruct = undefined; 102 for (let i = 0; i < cpuStateFilter!.length; i++) { 103 if ( 104 // @ts-ignore 105 cpuStateFilter[i].value === data.value && 106 // @ts-ignore 107 cpuStateFilter[i].cpu === data.cpu && 108 // @ts-ignore 109 Math.max(TraceRow.rangeSelectObject?.startNS!, cpuStateFilter[i].startTs!) < 110 // @ts-ignore 111 Math.min(TraceRow.rangeSelectObject?.endNS!, cpuStateFilter[i].startTs! + cpuStateFilter[i].dur!) 112 ) { 113 // @ts-ignore 114 CpuStateStruct.hoverStateStruct = cpuStateFilter[i]; 115 } 116 // @ts-ignore 117 if (cpuStateFilter[i].cpu === data.cpu) { 118 // @ts-ignore 119 CpuStateStruct.draw(context, path, cpuStateFilter[i]); 120 } 121 } 122 } else { 123 for (let i = 0; i < cpuStateFilter!.length; i++) { 124 if ( 125 row.name.includes('State') && 126 // @ts-ignore 127 cpuStateFilter[i].cpu !== data.cpu && 128 // @ts-ignore 129 cpuStateFilter[i].cpu === parseInt(row.name.replace(/[^\d]/g, ' ')) 130 ) { 131 // @ts-ignore 132 CpuStateStruct.draw(context, path, cpuStateFilter[i]); 133 } 134 } 135 } 136 row.canvasRestore(context, this.systemTrace); 137 } 138 } 139 }); 140 } 141 142 connectedCallback(): void { 143 super.connectedCallback(); 144 // @ts-ignore 145 resizeObserver(this.parentElement!, this.counterSampleTbl!, 25, this.counterLoadingPage, 24); 146 } 147 148 queryDataByDB(counterSampleParam: SelectionParam | unknown): void { 149 this.counterLoadingList.push(1); 150 this.sampleProgressEL!.loading = true; 151 // @ts-ignore 152 this.counterLoadingPage.style.visibility = 'visible'; 153 154 getTabPaneCounterSampleData( 155 // @ts-ignore 156 counterSampleParam.leftNs + counterSampleParam.recordStartNs, 157 // @ts-ignore 158 counterSampleParam.rightNs + counterSampleParam.recordStartNs, 159 // @ts-ignore 160 counterSampleParam.cpuStateFilterIds 161 ).then((result) => { 162 this.counterLoadingList.splice(0, 1); 163 if (this.counterLoadingList.length === 0) { 164 this.sampleProgressEL!.loading = false; 165 // @ts-ignore 166 this.counterLoadingPage.style.visibility = 'hidden'; 167 } 168 let sampleMap = new Map<unknown, unknown>(); 169 // @ts-ignore 170 counterSampleParam.cpuStateFilterIds.forEach((a: number): void => { 171 this.getInitTime( 172 //@ts-ignore 173 result.filter((f) => f.filterId === a), 174 sampleMap, 175 // @ts-ignore 176 counterSampleParam 177 ); 178 }); 179 // @ts-ignore 180 let counterSampleList: Array<unknown> = []; 181 sampleMap.forEach((a) => { 182 // @ts-ignore 183 a.timeStr = parseFloat((a.time / 1000000.0).toFixed(6)); 184 counterSampleList.push(a); 185 }); 186 this.counterSampleSource = counterSampleList; 187 this.sortTable(this.counterSortKey, this.counterSortType); 188 }); 189 } 190 // @ts-ignore 191 getInitTime(initCounterResultList: Array<unknown>, sampleMap: Map<unknown, unknown>, val: SelectionParam): void { 192 let leftNs = val.leftNs + val.recordStartNs; 193 let rightNs = val.rightNs + val.recordStartNs; 194 if (initCounterResultList.length === 0) { 195 return; 196 } 197 // @ts-ignore 198 let idx = initCounterResultList.findIndex((a) => a.ts >= leftNs); 199 if (idx !== 0) { 200 initCounterResultList = initCounterResultList.slice( 201 idx === -1 ? initCounterResultList.length - 1 : idx - 1, 202 initCounterResultList.length 203 ); 204 } 205 // @ts-ignore 206 if (initCounterResultList[0].ts < leftNs && idx !== 0) { 207 // @ts-ignore 208 initCounterResultList[0].ts = leftNs; 209 } 210 initCounterResultList.forEach((item, idx): void => { 211 if (idx + 1 === initCounterResultList.length) { 212 // @ts-ignore 213 item.time = rightNs - item.ts; 214 } else { 215 // @ts-ignore 216 item.time = initCounterResultList[idx + 1].ts - item.ts; 217 } 218 // @ts-ignore 219 if (sampleMap.has(`${item.filterId}-${item.value}`)) { 220 // @ts-ignore 221 let obj = sampleMap.get(`${item.filterId}-${item.value}`); 222 // @ts-ignore 223 obj.time += item.time; 224 } else { 225 // @ts-ignore 226 sampleMap.set(`${item.filterId}-${item.value}`, { 227 // @ts-ignore 228 ...item, 229 // @ts-ignore 230 counter: `Cpu ${item.cpu}`, 231 // @ts-ignore 232 count: initCounterResultList.filter((ele) => ele.value === item.value).length, 233 }); 234 } 235 }); 236 } 237 238 sortTable(key: string, type: number): void { 239 if (type === 0) { 240 this.counterSampleTbl!.recycleDataSource = this.counterSampleSource; 241 } else { 242 let arr = Array.from(this.counterSampleSource); 243 arr.sort((sortByColumnLeftData, sortByColumnRightData): number => { 244 if (key === 'timeStr') { 245 if (type === 1) { 246 // @ts-ignore 247 return sortByColumnLeftData.time - sortByColumnRightData.time; 248 } else { 249 // @ts-ignore 250 return sortByColumnRightData.time - sortByColumnLeftData.time; 251 } 252 } else if (key === 'counter') { 253 // @ts-ignore 254 if (sortByColumnLeftData.counter > sortByColumnRightData.counter) { 255 return type === 2 ? -1 : 1; 256 // @ts-ignore 257 } else if (sortByColumnLeftData.counter === sortByColumnRightData.counter) { 258 return 0; 259 } else { 260 return type === 2 ? 1 : -1; 261 } 262 } else if (key === 'value') { 263 if (type === 1) { 264 // @ts-ignore 265 return sortByColumnLeftData.value - sortByColumnRightData.value; 266 } else { 267 // @ts-ignore 268 return sortByColumnRightData.value - sortByColumnLeftData.value; 269 } 270 } else { 271 return 0; 272 } 273 }); 274 this.counterSampleTbl!.recycleDataSource = arr; 275 } 276 } 277 278 initHtml(): string { 279 return ` 280 <style> 281 .progressCounter{ 282 height: 1px; 283 left: 0; 284 right: 0; 285 bottom: 5px; 286 position: absolute; 287 } 288 :host{ 289 display: flex; 290 padding: 10px 10px; 291 flex-direction: column; 292 } 293 .loadingCounter{ 294 left: 0; 295 right: 0; 296 width:100%; 297 bottom: 0; 298 position: absolute; 299 background:transparent; 300 z-index: 999999; 301 } 302 .counter-sample-table{ 303 height: auto; 304 } 305 </style> 306 <lit-table id="tb-counter-sample" class="counter-sample-table"> 307 <lit-table-column class="counter-sample-column" width="20%" order data-index="counter" key="counter" align="flex-start" title="Cpu" > 308 </lit-table-column> 309 <lit-table-column class="counter-sample-column" width="1fr" order data-index="timeStr" key="timeStr" align="flex-start" title="Time(ms)" > 310 </lit-table-column> 311 <lit-table-column class="counter-sample-column" width="1fr" order data-index="value" key="value" align="flex-start" title="Value" > 312 </lit-table-column> 313 <lit-table-column class="counter-sample-column" width="1fr" order data-index="count" key="count" align="flex-start" title="Count" > 314 </lit-table-column> 315 </lit-table> 316 <lit-progress-bar class="progressCounter"></lit-progress-bar> 317 <div class="loadingCounter"></div> 318 `; 319 } 320} 321