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