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