• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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