• 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 { 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      counterSampleList.sort((a, b): number => {
187        // @ts-ignore
188        let countLeftData = Number(a.counter.toString().replace('Cpu', ''));
189        // @ts-ignore
190        let countRightData = Number(b.counter.toString().replace('Cpu', ''));
191        if (countLeftData > countRightData) {
192          return 1;
193        } else {
194          return -1;
195        }
196      });
197      this.counterSampleSource = counterSampleList;
198      this.sortTable(this.counterSortKey, this.counterSortType);
199    });
200  }
201  // @ts-ignore
202  getInitTime(initCounterResultList: Array<unknown>, sampleMap: Map<unknown, unknown>, val: SelectionParam): void {
203    let leftNs = val.leftNs + val.recordStartNs;
204    let rightNs = val.rightNs + val.recordStartNs;
205    if (initCounterResultList.length === 0) {
206      return;
207    }
208    // @ts-ignore
209    let idx = initCounterResultList.findIndex((a) => a.ts >= leftNs);
210    if (idx !== 0) {
211      initCounterResultList = initCounterResultList.slice(
212        idx === -1 ? initCounterResultList.length - 1 : idx - 1,
213        initCounterResultList.length
214      );
215    }
216    // @ts-ignore
217    if (initCounterResultList[0].ts < leftNs && idx !== 0) {
218      // @ts-ignore
219      initCounterResultList[0].ts = leftNs;
220    }
221    initCounterResultList.forEach((item, idx): void => {
222      if (idx + 1 === initCounterResultList.length) {
223        // @ts-ignore
224        item.time = rightNs - item.ts;
225      } else {
226        // @ts-ignore
227        item.time = initCounterResultList[idx + 1].ts - item.ts;
228      }
229      // @ts-ignore
230      if (sampleMap.has(`${item.filterId}-${item.value}`)) {
231        // @ts-ignore
232        let obj = sampleMap.get(`${item.filterId}-${item.value}`);
233        // @ts-ignore
234        obj.time += item.time;
235      } else {
236        // @ts-ignore
237        sampleMap.set(`${item.filterId}-${item.value}`, {
238          // @ts-ignore
239          ...item,
240          // @ts-ignore
241          counter: `Cpu ${item.cpu}`,
242          // @ts-ignore
243          count: initCounterResultList.filter((ele) => ele.value === item.value).length,
244        });
245      }
246    });
247  }
248
249  sortTable(key: string, type: number): void {
250    if (type === 0) {
251      this.counterSampleTbl!.recycleDataSource = this.counterSampleSource;
252    } else {
253      let arr = Array.from(this.counterSampleSource);
254      arr.sort((sortByColumnLeftData, sortByColumnRightData): number => {
255        if (key === 'timeStr') {
256          if (type === 1) {
257            // @ts-ignore
258            return sortByColumnLeftData.time - sortByColumnRightData.time;
259          } else {
260            // @ts-ignore
261            return sortByColumnRightData.time - sortByColumnLeftData.time;
262          }
263        } else if (key === 'counter') {
264          // @ts-ignore
265          let countLeftData = Number(sortByColumnLeftData.counter.toString().replace('Cpu', ''));
266          // @ts-ignore
267          let countRightData = Number(sortByColumnRightData.counter.toString().replace('Cpu', ''));
268          if (type === 1) {
269            return countLeftData - countRightData;
270          } else {
271            return countRightData - countLeftData;
272          }
273        } else if (key === 'value') {
274          if (type === 1) {
275            // @ts-ignore
276            return sortByColumnLeftData.value - sortByColumnRightData.value;
277          } else {
278            // @ts-ignore
279            return sortByColumnRightData.value - sortByColumnLeftData.value;
280          }
281        } else if (key === 'count') {
282          if (type === 1) {
283            // @ts-ignore
284            return sortByColumnLeftData.count - sortByColumnRightData.count;
285          } else {
286            // @ts-ignore
287            return sortByColumnRightData.count - sortByColumnLeftData.count;
288          }
289        } else {
290          return 0;
291        }
292      });
293      this.counterSampleTbl!.recycleDataSource = arr;
294    }
295  }
296
297  initHtml(): string {
298    return `
299        <style>
300        .progressCounter{
301            height: 1px;
302            left: 0;
303            right: 0;
304            bottom: 5px;
305            position: absolute;
306        }
307        :host{
308            display: flex;
309            padding: 10px 10px;
310            flex-direction: column;
311        }
312        .loadingCounter{
313            left: 0;
314            right: 0;
315            width:100%;
316            bottom: 0;
317            position: absolute;
318            background:transparent;
319            z-index: 999999;
320        }
321        .counter-sample-table{
322            height: auto;
323        }
324        </style>
325        <lit-table id="tb-counter-sample" class="counter-sample-table">
326            <lit-table-column class="counter-sample-column" width="20%" order data-index="counter" key="counter" align="flex-start" title="Cpu" >
327            </lit-table-column>
328            <lit-table-column class="counter-sample-column" width="1fr" order data-index="timeStr" key="timeStr" align="flex-start" title="Time(ms)" >
329            </lit-table-column>
330            <lit-table-column class="counter-sample-column" width="1fr" order data-index="value" key="value" align="flex-start" title="Value" >
331            </lit-table-column>
332            <lit-table-column class="counter-sample-column" width="1fr" order data-index="count" key="count" align="flex-start" title="Count" >
333            </lit-table-column>
334        </lit-table>
335        <lit-progress-bar class="progressCounter"></lit-progress-bar>
336        <div class="loadingCounter"></div>
337        `;
338  }
339}
340