• 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 '../TabPaneFilter';
19import { FilterData, TabPaneFilter } from '../TabPaneFilter';
20import { SelectionParam } from '../../../../bean/BoxSelection';
21import { PerfCallChainMerageData, PerfLevelStruct } from '../../../../bean/PerfProfile';
22import '../../../chart/FrameChart';
23import { FrameChart } from '../../../chart/FrameChart';
24import { ChartMode } from '../../../../bean/FrameChartStruct';
25import '../../../../../base-ui/slicer/lit-slicer';
26import '../../../../../base-ui/progress-bar/LitProgressBar';
27import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar';
28import { procedurePool } from '../../../../database/Procedure';
29import { showButtonMenu } from '../SheetUtils';
30import '../../../../../base-ui/headline/lit-headline';
31import { LitHeadLine } from '../../../../../base-ui/headline/lit-headline';
32import { TabPerfProfileHtml } from './TabPerfProfile.html';
33import { SpSystemTrace } from '../../../SpSystemTrace';
34
35const InvertOptionIndex: number = 0;
36const hideSystemLibraryOptionIndex: number = 1;
37const hideThreadOptionIndex: number = 3;
38const hideThreadStateOptionIndex: number = 4;
39const isOnlyKernelOptionIndex: number = 5;
40const callTreeValueNoSample: number[] = [InvertOptionIndex, hideSystemLibraryOptionIndex, hideThreadOptionIndex,
41  hideThreadStateOptionIndex, isOnlyKernelOptionIndex];
42
43@element('tabpane-perf-profile')
44export class TabpanePerfProfile extends BaseElement {
45  private perfProfilerTbl: LitTable | null | undefined;
46  private perfProfilerList: LitTable | null | undefined;
47  private perfProfileProgressEL: LitProgressBar | null | undefined;
48  private perfProfilerRightSource: Array<PerfCallChainMerageData> = [];
49  private perfProfilerFilter: TabPaneFilter | null | undefined;
50  private perfProfilerDataSource: unknown[] = [];
51  private perfProfileSortKey: string = 'weight';
52  private perfProfileSortType: number = 0;
53  private perfSelectedData: unknown = undefined;
54  private perfProfileFrameChart: FrameChart | null | undefined;
55  private isChartShow: boolean = false;
56  private systemRuleName: string = '/system/';
57  private perfProfileNumRuleName: string = '/max/min/';
58  private needShowMenu: boolean = true;
59  private searchValue: string = '';
60  private perfProfileLoadingPage: unknown;
61  private currentSelection: SelectionParam | undefined;
62  private currentRowClickData: unknown;
63  private initWidth: number = 0;
64  private _pieTitle: string = '';
65  private _cWidth: number = 0;
66  private _currentLevel: number = 0;
67  private _rowClickData: unknown = undefined;
68  private perfLevel: PerfLevelStruct | undefined | null;
69  private headLine: LitHeadLine | null | undefined;
70
71  set pieTitle(value: string) {
72    this._pieTitle = value;
73    if (this._pieTitle.length > 0) {
74      this.headLine!.isShow = true;
75      this.headLine!.titleTxt = this._pieTitle;
76      this.headLine!.closeCallback = (): void => {
77        this.restore();
78      };
79    }
80  }
81
82  set cWidth(value: number) {
83    this._cWidth = value;
84  }
85
86  set currentLevel(value: number) {
87    this._currentLevel = value;
88  }
89
90  set rowClickData(value: unknown) {
91    this._rowClickData = value;
92  }
93
94  set data(perfProfilerSelection: SelectionParam | unknown) {
95    if (perfProfilerSelection !== this.currentSelection && this._rowClickData === this.currentRowClickData) {
96      this._rowClickData = undefined;
97    }
98    if (perfProfilerSelection === this.currentSelection && !this.currentSelection?.isRowClick) {
99      return;
100    }
101    this.searchValue = ''; // @ts-ignore
102    this.currentSelection = perfProfilerSelection;
103    this.currentRowClickData = this._rowClickData;
104    this.perfProfilerTbl!.style.visibility = 'visible';
105    if (this.parentElement!.clientHeight > this.perfProfilerFilter!.clientHeight) {
106      this.perfProfilerFilter!.style.display = 'flex';
107    } else {
108      this.perfProfilerFilter!.style.display = 'none';
109    }
110    procedurePool.submitWithName('logic0', 'perf-reset', [], undefined, () => {});
111    this.perfProfilerFilter!.disabledTransfer(true);
112    this.perfProfilerFilter!.initializeFilterTree(true, true, true);
113    this.perfProfilerFilter!.filterValue = '';
114    this.perfProfileProgressEL!.loading = true; // @ts-ignore
115    this.perfProfileLoadingPage.style.visibility = 'visible'; // @ts-ignore
116    this.getDataByWorkAndUpDateCanvas(perfProfilerSelection);
117  }
118
119  getDataByWorkAndUpDateCanvas(perfProfilerSelection: SelectionParam): void {
120    if (this.clientWidth === 0) {
121      this.initWidth = this._cWidth;
122    } else {
123      this.initWidth = this.clientWidth;
124    }
125    if (this._rowClickData && this.currentRowClickData !== undefined && this.currentSelection?.isRowClick) {
126      // 点击表格的某一行跳转到火焰图
127      this.getDataByPieLevel(perfProfilerSelection.perfEventTypeId);
128    } else {
129      this.headLine!.isShow = false;
130      this.initGetData(perfProfilerSelection, this.initWidth, perfProfilerSelection.perfEventTypeId);
131    }
132  }
133
134  initGetData(
135    perfProfilerSelection: SelectionParam | unknown,
136    initWidth: number,
137    eventTypeId: undefined | number
138  ): void {
139    let perfProfileArgs: unknown[] = [];
140    perfProfileArgs.push(
141      {
142        funcName: 'setSearchValue',
143        funcArgs: [''],
144      },
145      {
146        funcName: 'getCurrentDataFromDb',
147        funcArgs: [perfProfilerSelection],
148      }
149    );
150
151    this.getDataByWorker(perfProfileArgs, (results: unknown[]) => {
152      this.setPerfProfilerLeftTableData(results);
153      this.perfProfilerList!.recycleDataSource = [];
154      if (eventTypeId === undefined) {
155        this.perfProfileFrameChart!.mode = ChartMode.Count;
156      } else {
157        this.perfProfileFrameChart!.mode = ChartMode.EventCount;
158      }
159      this.perfProfileFrameChart?.updateCanvas(true, initWidth); // @ts-ignore
160      this.perfProfileFrameChart!.totalRootData = this.perfProfilerDataSource;// @ts-ignore
161      this.perfProfileFrameChart!.data = this.perfProfilerDataSource;
162      this.switchFlameChart();
163      this.perfProfilerFilter!.icon = 'block';
164    });
165  }
166
167  private restore(): void {
168    this.searchValue = '';
169    this.perfProfilerFilter!.filterValue = '';
170    this.headLine!.isShow = false;
171    this._rowClickData = undefined;
172    this.initGetData(this.currentSelection, this.initWidth, this.currentSelection?.perfEventTypeId);
173  }
174
175  /**
176   * 根据饼图跳转过来的层级绘制对应的火焰图和表格
177   */
178  private getDataByPieLevel(eventTypeId: number | undefined): void {
179    this.perfLevel = new PerfLevelStruct();
180    this.perfLevel = {
181      // @ts-ignore
182      processId: this._rowClickData.pid, // @ts-ignore
183      threadId: this._rowClickData.tid, // @ts-ignore
184      libId: this._rowClickData.libId,
185    };
186    let args = [];
187    args.push({
188      funcName: 'getCurrentDataFromDb',
189      funcArgs: [this.currentSelection, this.perfLevel],
190    });
191    // @ts-ignore
192    if (this._rowClickData && this._rowClickData.libId !== undefined && this._currentLevel === 2) {
193      // @ts-ignore
194      this.perfLevel!.libName = this._rowClickData.tableName;
195      args.push({
196        funcName: 'showLibLevelData',
197        funcArgs: [this.perfLevel!.libId, this.perfLevel!.libName],
198      }); // @ts-ignore
199    } else if (this._rowClickData && this._rowClickData.symbolId !== undefined && this._currentLevel === 3) {
200      // @ts-ignore
201      this.perfLevel!.symbolId = this._rowClickData.symbolId; // @ts-ignore
202      this.perfLevel!.symbolName = this._rowClickData.tableName;
203      args.push({
204        funcName: 'showFunLevelData',
205        funcArgs: [this.perfLevel!.symbolId, this.perfLevel!.symbolName],
206      });
207    }
208
209    this.getDataByWorker(args, (results: unknown[]) => {
210      this.perfProfileProgressEL!.loading = false; // @ts-ignore
211      this.perfProfileLoadingPage.style.visibility = 'hidden';
212      this.setPerfProfilerLeftTableData(results);
213      this.perfProfilerList!.recycleDataSource = [];
214      if (eventTypeId === undefined) {
215        this.perfProfileFrameChart!.mode = ChartMode.Count;
216      } else {
217        this.perfProfileFrameChart!.mode = ChartMode.EventCount;
218      }
219      this.perfProfileFrameChart?.updateCanvas(true, this.initWidth); // @ts-ignore
220      this.perfProfileFrameChart!.data = this.perfProfilerDataSource;
221      this.switchFlameChart();
222      this.perfProfilerFilter!.icon = 'block';
223    });
224  }
225
226  getParentTree(
227    perfCallSrc: Array<PerfCallChainMerageData>,
228    target: PerfCallChainMerageData,
229    parentsData: Array<PerfCallChainMerageData>
230  ): boolean {
231    for (let perfCall of perfCallSrc) {
232      if (perfCall.id === target.id) {
233        parentsData.push(perfCall);
234        return true;
235      } else {
236        if (this.getParentTree(perfCall.children as Array<PerfCallChainMerageData>, target, parentsData)) {
237          parentsData.push(perfCall);
238          return true;
239        }
240      }
241    }
242    return false;
243  }
244
245  getChildTree(
246    perfCallSrc: Array<PerfCallChainMerageData>,
247    id: string,
248    children: Array<PerfCallChainMerageData>
249  ): boolean {
250    for (let perfCall of perfCallSrc) {
251      if (perfCall.id === id && perfCall.children.length === 0) {
252        children.push(perfCall);
253        return true;
254      } else {
255        if (this.getChildTree(perfCall.children as Array<PerfCallChainMerageData>, id, children)) {
256          children.push(perfCall);
257          return true;
258        }
259      }
260    }
261    return false;
262  }
263
264  setRightTableData(chainMerageData: PerfCallChainMerageData): void {
265    let parentsMerageData: Array<PerfCallChainMerageData> = [];
266    let childrenMerageData: Array<PerfCallChainMerageData> = []; // @ts-ignore
267    this.getParentTree(this.perfProfilerDataSource, chainMerageData, parentsMerageData);
268    let maxId = chainMerageData.id;
269    let maxDur = 0;
270
271    function findMaxStack(call: PerfCallChainMerageData): void {
272      if (call.children.length === 0) {
273        if (call.dur > maxDur) {
274          maxDur = call.dur;
275          maxId = call.id;
276        }
277      } else {
278        call.children.map((callChild): void => {
279          findMaxStack(<PerfCallChainMerageData>callChild);
280        });
281      }
282    }
283
284    findMaxStack(chainMerageData);
285    this.getChildTree(chainMerageData.children as Array<PerfCallChainMerageData>, maxId, childrenMerageData);
286    let perfProfileParentsList = parentsMerageData.reverse().concat(childrenMerageData.reverse());
287    for (let data of perfProfileParentsList) {
288      data.type = data.lib.endsWith('.so.1') || data.lib.endsWith('.dll') || data.lib.endsWith('.so') ? 0 : 1;
289    }
290    let len = perfProfileParentsList.length;
291    this.perfProfilerRightSource = perfProfileParentsList;
292    let rightSource: Array<unknown> = [];
293    if (len !== 0) {
294      rightSource = this.perfProfilerRightSource.filter((item): boolean => {
295        return item.canCharge;
296      });
297    }
298    this.perfProfilerList!.dataSource = rightSource;
299  }
300
301  initElements(): void {
302    this.headLine = this.shadowRoot?.querySelector<LitHeadLine>('.titleBox');
303    this.perfProfilerTbl = this.shadowRoot?.querySelector<LitTable>('#tb-perf-profile');
304    this.perfProfileProgressEL = this.shadowRoot?.querySelector('.perf-profile-progress') as LitProgressBar;
305    this.perfProfileFrameChart = this.shadowRoot?.querySelector<FrameChart>('#framechart');
306    this.perfProfileLoadingPage = this.shadowRoot?.querySelector('.perf-profile-loading');
307    let spApplication = document.querySelector('body > sp-application');
308    let spSystemTrace = spApplication?.shadowRoot?.querySelector(
309      'div > div.content > sp-system-trace'
310    ) as SpSystemTrace;
311    this.addEventListener('contextmenu', (event) => {
312      event.preventDefault(); // 阻止默认的上下文菜单弹框
313    });
314    this.perfProfileFrameChart!.addChartClickListener((needShowMenu: boolean): void => {
315      this.parentElement!.scrollTo(0, 0);
316      showButtonMenu(this.perfProfilerFilter, needShowMenu);
317      this.needShowMenu = needShowMenu;
318    });
319    this.perfProfilerTbl!.rememberScrollTop = true;
320    this.perfProfilerFilter = this.shadowRoot?.querySelector<TabPaneFilter>('#filter');
321    this.perfProfilerList = this.shadowRoot?.querySelector<LitTable>('#tb-perf-list');
322    this.initPerfProfilerDataAndListener();
323    this.perfProfilerFilter?.addEventListener('focus', () => {
324      spSystemTrace.focusTarget = 'bottomUpInput';
325    });
326    this.perfProfilerFilter?.addEventListener('blur', () => {
327      spSystemTrace.focusTarget = '';
328    });
329  }
330
331  private initPerfProfilerDataAndListener(): void {
332    this.perfProfilerTbl!.addEventListener('row-click', (evt: unknown): void => {
333      // @ts-ignore
334      let data = evt.detail.data as PerfCallChainMerageData;
335      document.dispatchEvent(
336        new CustomEvent('number_calibration', {
337          detail: { time: data.tsArray },
338        })
339      );
340      this.setRightTableData(data);
341      data.isSelected = true;
342      this.perfSelectedData = data;
343      this.perfProfilerList?.clearAllSelection(data);
344      this.perfProfilerList?.setCurrentSelection(data);
345      // @ts-ignore
346      if ((evt.detail as unknown).callBack) {
347        // @ts-ignore
348        (evt.detail as unknown).callBack(true);
349      }
350    });
351    this.perfProfilerList!.addEventListener('row-click', (evt: unknown): void => {
352      // @ts-ignore
353      let data = evt.detail.data as PerfCallChainMerageData;
354      this.perfProfilerTbl?.clearAllSelection(data); // @ts-ignore
355      (data as unknown).isSelected = true;
356      this.perfProfilerTbl!.scrollToData(data);
357      // @ts-ignore
358      if ((evt.detail as unknown).callBack) {
359        // @ts-ignore
360        (evt.detail as unknown).callBack(true);
361      }
362    });
363    this.perfProfilerFilter!.getDataLibrary(this.filterFunc.bind(this));
364    this.perfProfilerFilter!.getDataMining(this.filterFunc.bind(this));
365    this.perfProfilerFilter!.getCallTreeData(this.perfProfilerFilterGetCallTree.bind(this));
366    this.perfProfilerFilter!.getCallTreeConstraintsData(this.perfProfilerFilterGetCallTreeConstraints.bind(this));
367    this.perfProfilerFilter!.getFilterData(this.perfProfilerFilterGetFilter.bind(this));
368    this.perfProfilerTbl!.addEventListener('column-click', (evt): void => {
369      // @ts-ignore
370      this.perfProfileSortKey = evt.detail.key;
371      // @ts-ignore
372      this.perfProfileSortType = evt.detail.sort;
373      // @ts-ignore
374      this.setPerfProfilerLeftTableData(this.perfProfilerDataSource); // @ts-ignore
375      this.perfProfileFrameChart!.data = this.perfProfilerDataSource;
376    });
377  }
378
379  private filterFuncByCheckType(data: unknown, perfProfileFuncArgs: unknown[]): void {
380    // @ts-ignore
381    if (data.item.checked) {
382      perfProfileFuncArgs.push({
383        funcName: 'splitTree', // @ts-ignore
384        funcArgs: [data.item.name, data.item.select === '0', data.item.type === 'symbol'],
385      });
386    } else {
387      perfProfileFuncArgs.push({
388        funcName: 'resotreAllNode', // @ts-ignore
389        funcArgs: [[data.item.name]],
390      });
391      perfProfileFuncArgs.push({
392        funcName: 'resetAllNode',
393        funcArgs: [],
394      });
395      perfProfileFuncArgs.push({
396        funcName: 'clearSplitMapData', // @ts-ignore
397        funcArgs: [data.item.name],
398      });
399    }
400  }
401
402  private filterFuncBySelect(data: unknown, perfProfileFuncArgs: unknown[]): void {
403    perfProfileFuncArgs.push({
404      funcName: 'resotreAllNode', // @ts-ignore
405      funcArgs: [[data.item.name]],
406    });
407    perfProfileFuncArgs.push({
408      funcName: 'clearSplitMapData', // @ts-ignore
409      funcArgs: [data.item.name],
410    });
411    perfProfileFuncArgs.push({
412      funcName: 'splitTree', // @ts-ignore
413      funcArgs: [data.item.name, data.item.select === '0', data.item.type === 'symbol'],
414    });
415  }
416
417  private filterFuncByButton(data: unknown, perfProfileFuncArgs: unknown[]): void {
418    // @ts-ignore
419    if (data.item === 'symbol') {
420      // @ts-ignore
421      if (this.perfSelectedData && !this.perfSelectedData.canCharge) {
422        return;
423      }
424      if (this.perfSelectedData !== undefined) {
425        // @ts-ignore
426        this.perfProfilerFilter!.addDataMining({ name: this.perfSelectedData.symbolName }, data.item);
427        perfProfileFuncArgs.push({
428          funcName: 'splitTree', // @ts-ignore
429          funcArgs: [this.perfSelectedData.symbolName, false, true],
430        });
431      } else {
432        return;
433      } // @ts-ignore
434    } else if (data.item === 'library') {
435      // @ts-ignore
436      if (this.perfSelectedData && !this.perfSelectedData.canCharge) {
437        return;
438      } // @ts-ignore
439      if (this.perfSelectedData !== undefined && this.perfSelectedData.libName !== '') {
440        // @ts-ignore
441        this.perfProfilerFilter!.addDataMining({ name: this.perfSelectedData.libName }, data.item);
442        perfProfileFuncArgs.push({
443          funcName: 'splitTree', // @ts-ignore
444          funcArgs: [this.perfSelectedData.libName, false, false],
445        });
446      } else {
447        return;
448      } // @ts-ignore
449    } else if (data.item === 'restore') {
450      // @ts-ignore
451      if (data.remove !== undefined && data.remove.length > 0) {
452        // @ts-ignore
453        let list = data.remove.map((item: unknown) => {
454          // @ts-ignore
455          return item.name;
456        });
457        perfProfileFuncArgs.push({
458          funcName: 'resotreAllNode',
459          funcArgs: [list],
460        });
461        perfProfileFuncArgs.push({
462          funcName: 'resetAllNode',
463          funcArgs: [],
464        });
465        list.forEach((symbolName: string): void => {
466          perfProfileFuncArgs.push({
467            funcName: 'clearSplitMapData',
468            funcArgs: [symbolName],
469          });
470        });
471      }
472    }
473  }
474
475  private filterFunc(data: unknown): void {
476    let perfProfileFuncArgs: unknown[] = []; // @ts-ignore
477    if (data.type === 'check') {
478      this.filterFuncByCheckType(data, perfProfileFuncArgs); // @ts-ignore
479    } else if (data.type === 'select') {
480      this.filterFuncBySelect(data, perfProfileFuncArgs); // @ts-ignore
481    } else if (data.type === 'button') {
482      this.filterFuncByButton(data, perfProfileFuncArgs);
483    }
484    this.getDataByWorker(perfProfileFuncArgs, (result: unknown[]): void => {
485      this.setPerfProfilerLeftTableData(result); // @ts-ignore
486      this.perfProfileFrameChart!.data = this.perfProfilerDataSource;
487      if (this.isChartShow) {
488        this.perfProfileFrameChart?.calculateChartData();
489      }
490      this.perfProfilerTbl!.move1px();
491      if (this.perfSelectedData) {
492        // @ts-ignore
493        this.perfSelectedData.isSelected = false;
494        this.perfProfilerTbl?.clearAllSelection(this.perfSelectedData);
495        this.perfProfilerList!.recycleDataSource = [];
496        this.perfSelectedData = undefined;
497      }
498    });
499  }
500
501  private perfProfilerFilterGetFilter(data: FilterData): void {
502    if ((this.isChartShow && data.icon === 'tree') || (!this.isChartShow && data.icon === 'block')) {
503      this.switchFlameChart(data);
504    } else if (this.searchValue !== this.perfProfilerFilter!.filterValue) {
505      this.searchValue = this.perfProfilerFilter!.filterValue;
506      let perfArgs = [
507        {
508          funcName: 'setSearchValue',
509          funcArgs: [this.searchValue],
510        },
511        {
512          funcName: 'resetAllNode',
513          funcArgs: [],
514        },
515      ];
516      this.getDataByWorker(perfArgs, (result: unknown[]): void => {
517        this.perfProfilerTbl!.isSearch = true;
518        this.perfProfilerTbl!.setStatus(result, true);
519        this.setPerfProfilerLeftTableData(result); // @ts-ignore
520        this.perfProfileFrameChart!.data = this.perfProfilerDataSource;
521        this.switchFlameChart(data);
522      });
523    } else {
524      this.perfProfilerTbl!.setStatus(this.perfProfilerDataSource, true);
525      this.setPerfProfilerLeftTableData(this.perfProfilerDataSource);
526      this.switchFlameChart(data);
527    }
528  }
529
530  private perfProfilerFilterGetCallTreeConstraints(data: unknown): void {
531    let perfProfilerConstraintsArgs: unknown[] = [
532      {
533        funcName: 'resotreAllNode',
534        funcArgs: [[this.perfProfileNumRuleName]],
535      },
536      {
537        funcName: 'clearSplitMapData',
538        funcArgs: [this.perfProfileNumRuleName],
539      },
540    ]; // @ts-ignore
541    if (data.checked) {
542      perfProfilerConstraintsArgs.push({
543        funcName: 'hideNumMaxAndMin', // @ts-ignore
544        funcArgs: [parseInt(data.min), data.max],
545      });
546    }
547    perfProfilerConstraintsArgs.push({
548      funcName: 'resetAllNode',
549      funcArgs: [],
550    });
551    this.getDataByWorker(perfProfilerConstraintsArgs, (result: unknown[]): void => {
552      this.setPerfProfilerLeftTableData(result); // @ts-ignore
553      this.perfProfileFrameChart!.data = this.perfProfilerDataSource;
554      if (this.isChartShow) {
555        this.perfProfileFrameChart?.calculateChartData();
556      }
557    });
558  }
559
560  private perfProfilerFilterGetCallTree(data: unknown): void {
561    // @ts-ignore
562    if (callTreeValueNoSample.includes(data.value)) {
563      this.refreshAllNode({
564        ...this.perfProfilerFilter!.getFilterTreeData(), // @ts-ignore
565        callTree: data.checks,
566      });
567    } else {
568      let perfProfileArgs: unknown[] = []; // @ts-ignore
569      if (data.checks[1]) {
570        perfProfileArgs.push({
571          funcName: 'hideSystemLibrary',
572          funcArgs: [],
573        });
574      } else {
575        perfProfileArgs.push({
576          funcName: 'resotreAllNode',
577          funcArgs: [[this.systemRuleName]],
578        });
579        perfProfileArgs.push({
580          funcName: 'clearSplitMapData',
581          funcArgs: [this.systemRuleName],
582        });
583      }
584      perfProfileArgs.push({
585        funcName: 'resetAllNode',
586        funcArgs: [],
587      });
588      this.getDataByWorker(perfProfileArgs, (result: unknown[]): void => {
589        this.setPerfProfilerLeftTableData(result); // @ts-ignore
590        this.perfProfileFrameChart!.data = this.perfProfilerDataSource;
591        if (this.isChartShow) {
592          this.perfProfileFrameChart?.calculateChartData();
593        }
594      });
595    }
596  }
597
598  connectedCallback(): void {
599    super.connectedCallback();
600    this.parentElement!.onscroll = (): void => {
601      this.perfProfileFrameChart!.tabPaneScrollTop = this.parentElement!.scrollTop;
602    };
603    let filterHeight = 0;
604    new ResizeObserver((entries): void => {
605      let perfProfileTabFilter = this.shadowRoot!.querySelector('#filter') as HTMLElement;
606      if (perfProfileTabFilter.clientHeight > 0) {
607        filterHeight = perfProfileTabFilter.clientHeight;
608      }
609      if (this.parentElement!.clientHeight > filterHeight) {
610        perfProfileTabFilter.style.display = 'flex';
611      } else {
612        perfProfileTabFilter.style.display = 'none';
613      }
614      if (this.perfProfilerTbl!.style.visibility === 'hidden') {
615        perfProfileTabFilter.style.display = 'none';
616      }
617      if (this.parentElement?.clientHeight !== 0) {
618        if (this.isChartShow) {
619          this.perfProfileFrameChart?.updateCanvas(false, entries[0].contentRect.width);
620          this.perfProfileFrameChart?.calculateChartData();
621        }
622        let headLineHeight = 0;
623        if (this.headLine?.isShow) {
624          headLineHeight = this.headLine!.clientHeight;
625        }
626        // @ts-ignore
627        this.perfProfilerTbl?.shadowRoot.querySelector('.table').style.height =
628          // @ts-ignore
629          `${this.parentElement.clientHeight - 10 - 35 - headLineHeight}px`;
630        this.perfProfilerTbl?.reMeauseHeight();
631        // @ts-ignore
632        this.perfProfilerList?.shadowRoot.querySelector('.table').style.height =
633          // @ts-ignore
634          `${this.parentElement.clientHeight - 45 - 21 - headLineHeight}px`;
635        this.perfProfilerList?.reMeauseHeight(); // @ts-ignore
636        this.perfProfileLoadingPage.style.height = `${this.parentElement!.clientHeight - 24}px`;
637      }
638    }).observe(this.parentElement!);
639  }
640
641  switchFlameChart(data?: unknown): void {
642    let perfProfilerPageTab = this.shadowRoot?.querySelector('#show_table');
643    let perfProfilerPageChart = this.shadowRoot?.querySelector('#show_chart'); // @ts-ignore
644    if (!data || data.icon === 'block') {
645      perfProfilerPageChart?.setAttribute('class', 'show');
646      perfProfilerPageTab?.setAttribute('class', '');
647      this.isChartShow = true;
648      this.perfProfilerFilter!.disabledMining = true;
649      showButtonMenu(this.perfProfilerFilter, this.needShowMenu);
650      this.perfProfileFrameChart?.calculateChartData(); // @ts-ignore
651    } else if (data.icon === 'tree') {
652      perfProfilerPageChart?.setAttribute('class', '');
653      perfProfilerPageTab?.setAttribute('class', 'show');
654      showButtonMenu(this.perfProfilerFilter, true);
655      this.isChartShow = false;
656      this.perfProfilerFilter!.disabledMining = false;
657      this.perfProfileFrameChart!.clearCanvas();
658      this.perfProfilerTbl!.reMeauseHeight();
659    }
660  }
661
662  refreshAllNode(filterData: unknown): void {
663    let perfProfileArgs: unknown[] = []; // @ts-ignore
664    let isTopDown: boolean = !filterData.callTree[0]; // @ts-ignore
665    let isHideSystemLibrary: boolean = filterData.callTree[1]; // @ts-ignore
666    let isHideThread: boolean = filterData.callTree[3]; // @ts-ignore
667    let isHideThreadState: boolean = filterData.callTree[4]; // @ts-ignore
668    let isOnlyKernel: boolean = filterData.callTree[5]; // @ts-ignore
669    let list = filterData.dataMining.concat(filterData.dataLibrary);
670    perfProfileArgs.push({
671      funcName: 'hideThread',
672      funcArgs: [isHideThread],
673    });
674
675    perfProfileArgs.push({
676      funcName: 'hideThreadState',
677      funcArgs: [isHideThreadState],
678    });
679    perfProfileArgs.push({
680      funcName: 'onlyKernel',
681      funcArgs: [isOnlyKernel],
682    });
683    perfProfileArgs.push({
684      funcName: 'getCallChainsBySampleIds',
685      funcArgs: [isTopDown],
686    });
687    this.perfProfilerList!.recycleDataSource = [];
688    if (isHideSystemLibrary) {
689      perfProfileArgs.push({
690        funcName: 'hideSystemLibrary',
691        funcArgs: [],
692      });
693    } // @ts-ignore
694    if (filterData.callTreeConstraints.checked) {
695      perfProfileArgs.push({
696        funcName: 'hideNumMaxAndMin', // @ts-ignore
697        funcArgs: [parseInt(filterData.callTreeConstraints.inputs[0]), filterData.callTreeConstraints.inputs[1]],
698      });
699    }
700    perfProfileArgs.push({
701      funcName: 'splitAllProcess',
702      funcArgs: [list],
703    });
704    perfProfileArgs.push({
705      funcName: 'resetAllNode',
706      funcArgs: [],
707    });
708    // @ts-ignore
709    this.refreshAllNodeExtend(perfProfileArgs);
710  }
711
712  refreshAllNodeExtend(perfProfileArgs: unknown[]): void {
713    // @ts-ignore
714    if (this._rowClickData && this._rowClickData.libId !== undefined && this._currentLevel === 2) {
715      perfProfileArgs.push({
716        funcName: 'showLibLevelData',
717        funcArgs: [this.perfLevel!.libId, this.perfLevel!.libName],
718      }); // @ts-ignore
719    } else if (this._rowClickData && this._rowClickData.symbolId && this._currentLevel === 3) {
720      perfProfileArgs.push({
721        funcName: 'showFunLevelData',
722        funcArgs: [this.perfLevel!.symbolId, this.perfLevel!.symbolName],
723      });
724    }
725    this.getDataByWorker(perfProfileArgs, (result: unknown[]): void => {
726      this.setPerfProfilerLeftTableData(result); // @ts-ignore
727      this.perfProfileFrameChart!.data = this.perfProfilerDataSource;
728      if (this.isChartShow) {
729        this.perfProfileFrameChart?.calculateChartData();
730      }
731    });
732  }
733
734  setPerfProfilerLeftTableData(resultData: unknown[]): void {
735    this.perfProfilerDataSource = this.sortTree(resultData);
736    this.perfProfilerTbl!.recycleDataSource = this.perfProfilerDataSource;
737  }
738
739  sortTree(arr: Array<unknown>): Array<unknown> {
740    let perfProfileSortArr = arr.sort((perfProfileA, perfProfileB): number => {
741      if (this.perfProfileSortKey === 'selfDur') {
742        if (this.perfProfileSortType === 0) {
743          // @ts-ignore
744          return perfProfileB.dur - perfProfileA.dur;
745        } else if (this.perfProfileSortType === 1) {
746          // @ts-ignore
747          return perfProfileA.selfDur - perfProfileB.selfDur;
748        } else {
749          // @ts-ignore
750          return perfProfileB.selfDur - perfProfileA.selfDur;
751        }
752      } else {
753        if (this.perfProfileSortType === 0) {
754          // @ts-ignore
755          return perfProfileB.dur - perfProfileA.dur;
756        } else if (this.perfProfileSortType === 1) {
757          // @ts-ignore
758          return perfProfileA.dur - perfProfileB.dur;
759        } else {
760          // @ts-ignore
761          return perfProfileB.dur - perfProfileA.dur;
762        }
763      }
764    });
765    perfProfileSortArr.map((call: unknown): void => {
766      // @ts-ignore
767      call.children = this.sortTree(call.children);
768    });
769    return perfProfileSortArr;
770  }
771
772  getDataByWorker(args: unknown[], handler: Function): void {
773    this.perfProfileProgressEL!.loading = true; // @ts-ignore
774    this.perfProfileLoadingPage.style.visibility = 'visible';
775    procedurePool.submitWithName('logic0', 'perf-action', args, undefined, (results: unknown): void => {
776      handler(results);
777      this.perfProfileProgressEL!.loading = false; // @ts-ignore
778      this.perfProfileLoadingPage.style.visibility = 'hidden';
779    });
780  }
781
782  initHtml(): string {
783    return TabPerfProfileHtml;
784  }
785}
786