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