• 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 { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar';
19import { FrameChart } from '../../../chart/FrameChart';
20import { SelectionParam } from '../../../../bean/BoxSelection';
21import { ChartMode } from '../../../../bean/FrameChartStruct';
22import { FilterData, TabPaneFilter } from '../TabPaneFilter';
23import { procedurePool } from '../../../../database/Procedure';
24import { FileMerageBean } from '../../../../database/logic-worker/ProcedureLogicWorkerFileSystem';
25import { ParseExpression } from '../SheetUtils';
26import { FilterByAnalysis, NativeMemoryExpression } from '../../../../bean/NativeHook';
27import { SpSystemTrace } from '../../../SpSystemTrace';
28import '../../../../../base-ui/headline/lit-headline';
29import { LitHeadLine } from '../../../../../base-ui/headline/lit-headline';
30import { TabPaneNMCallTreeHtml } from './TabPaneNMCallTree.html';
31import { queryNativeHookStatisticSubType, queryNativeHookSubType } from '../../../../database/sql/NativeHook.sql';
32
33const InvertOpyionIndex: number = 0;
34const HideSystemSoOptionIndex: number = 1;
35const HideThreadOptionIndex: number = 3;
36
37@element('tabpane-nm-calltree')
38export class TabpaneNMCalltree extends BaseElement {
39  private nmCallTreeTbl: LitTable | null | undefined;
40  private filesystemTbr: LitTable | null | undefined;
41  private nmCallTreeProgressEL: LitProgressBar | null | undefined;
42  private nmCallTreeFilter: TabPaneFilter | null | undefined;
43  private nmCallTreeSource: unknown[] = [];
44  private nativeType: Array<string> = ['All Heap & Anonymous VM', 'All Heap', 'All Anonymous VM'];
45  private sortKey: string = 'heapSizeStr';
46  private sortType: number = 0;
47  private currentSelectedData: unknown = undefined;
48  private nmCallTreeFrameChart: FrameChart | null | undefined;
49  private isChartShow: boolean = false;
50  private systmeRuleName: string = '/system/';
51  private numRuleName: string = '/max/min/';
52  private needShowMenu: boolean = true;
53  private searchValue: string = '';
54  private loadingList: number[] = [];
55  private nmCallTreeLoadingPage: unknown;
56  private currentSelection: SelectionParam | undefined;
57  private filterAllocationType: string = '0';
58  private filterNativeType: string = '0';
59  private filterResponseType: number = -1;
60  private filterResponseSelect: string = '0';
61  private responseTypes: unknown[] = [];
62  private subTypeArr: number[] = [];
63  private lastIsExpression = false;
64  private currentNMCallTreeFilter: TabPaneFilter | undefined | null;
65  private expressionStruct: NativeMemoryExpression | null = null;
66  private isHideThread: boolean = false;
67  private currentSelectIPid = 1;
68  private headLine: LitHeadLine | null | undefined;
69  private _filterData: FilterByAnalysis | undefined;
70  private _analysisTabWidth: number = 0;
71  private _initFromAnalysis = false;
72
73  set analysisTabWidth(width: number) {
74    this._analysisTabWidth = width;
75  }
76
77  set titleTxt(value: string) {
78    this.headLine!.titleTxt = value;
79  }
80
81  set filterData(data: FilterByAnalysis) {
82    // click from analysis
83    this._filterData = data;
84  }
85
86  set titleBoxShow(value: Boolean) {
87    this.headLine!.isShow = value;
88  }
89
90  set initFromAnalysis(flag: boolean) {
91    this._initFromAnalysis = flag;
92  }
93
94  set data(nmCallTreeParam: SelectionParam) {
95    if (nmCallTreeParam === this.currentSelection) {
96      return;
97    }
98    // 火焰图数据
99    this.nmCallTreeSource = [];
100    // 框选内容赋值
101    this.currentSelection = nmCallTreeParam;
102    // 拿到框选的pid
103    this.currentSelectIPid = nmCallTreeParam.nativeMemoryCurrentIPid;
104    this.init(nmCallTreeParam);
105  }
106
107  private async init(nmCallTreeParam: SelectionParam): Promise<void> {
108    // 初始化样式
109    this.initUI();
110    // 初始化选择框内容
111    await this.initFilterTypes();
112    let types: Array<string | number> = [];
113    this.initTypes(nmCallTreeParam, types);
114    const initWidth = this._analysisTabWidth > 0 ? this._analysisTabWidth : this.clientWidth;
115    // 获取tab页数据
116    this.getDataByWorkerQuery(
117      {
118        leftNs: nmCallTreeParam.leftNs,
119        rightNs: nmCallTreeParam.rightNs,
120        // ['AllocEvent','MmapEvent']
121        types,
122      },
123      (results: unknown[]): void => {
124        this.setLTableData(results);
125        this.filesystemTbr!.recycleDataSource = [];
126
127        this.nmCallTreeFrameChart?.updateCanvas(true, initWidth);
128        if (this._initFromAnalysis) {
129          this.filterByAnalysis();
130        } else {
131          // @ts-ignore
132          this.nmCallTreeFrameChart!.data = this.nmCallTreeSource;
133          this.switchFlameChart();
134          this.nmCallTreeFilter!.icon = 'block';
135        }
136      }
137    );
138  }
139
140  initUI(): void {
141    this.headLine!.clear();
142    this.isHideThread = false;
143    this.searchValue = '';
144    this.nmCallTreeTbl!.style.visibility = 'visible';
145    if (this.parentElement!.clientHeight > this.nmCallTreeFilter!.clientHeight) {
146      this.nmCallTreeFilter!.style.display = 'flex';
147    } else {
148      this.nmCallTreeFilter!.style.display = 'none';
149    }
150    procedurePool.submitWithName('logic0', 'native-memory-reset', [], undefined, () => { });
151    this.nmCallTreeFilter!.disabledTransfer(true);
152    this.nmCallTreeFilter!.initializeFilterTree(true, true, this.currentSelection!.nativeMemory.length > 0);
153    this.nmCallTreeFilter!.filterValue = '';
154
155    this.nmCallTreeProgressEL!.loading = true; // @ts-ignore
156    this.nmCallTreeLoadingPage.style.visibility = 'visible';
157  }
158
159  initTypes(nmCallTreeParam: SelectionParam, types: Array<string | number>): void {
160    if (nmCallTreeParam.nativeMemory.length > 0) {
161      this.nmCallTreeFilter!.isStatisticsMemory = false;
162      if (nmCallTreeParam.nativeMemory.indexOf(this.nativeType[0]) !== -1) {
163        types.push("'AllocEvent'");
164        types.push("'MmapEvent'");
165      } else {
166        if (nmCallTreeParam.nativeMemory.indexOf(this.nativeType[1]) !== -1) {
167          types.push("'AllocEvent'");
168        }
169        if (nmCallTreeParam.nativeMemory.indexOf(this.nativeType[2]) !== -1) {
170          types.push("'MmapEvent'");
171        }
172      }
173    } else {
174      this.nmCallTreeFilter!.isStatisticsMemory = true;
175      if (nmCallTreeParam.nativeMemoryStatistic.indexOf(this.nativeType[0]) !== -1) {
176        types.push(0);
177        types.push(1);
178      } else {
179        if (nmCallTreeParam.nativeMemoryStatistic.indexOf(this.nativeType[1]) !== -1) {
180          types.push(0);
181        }
182        if (nmCallTreeParam.nativeMemoryStatistic.indexOf(this.nativeType[2]) !== -1) {
183          types.push(1);
184        }
185      }
186    }
187  }
188
189  setFilterType(selections: Array<unknown>, data: FilterByAnalysis): void {
190    if (data.type === 'AllocEvent') {
191      data.type = '1';
192    }
193    if (this.subTypeArr.length > 0) {
194      this.subTypeArr.map((memory): void => {
195        selections.push({
196          memoryTap: memory,
197        });
198        if (this.currentSelection?.nativeMemory && this.currentSelection.nativeMemory.length > 0) {
199          const typeName = SpSystemTrace.DATA_DICT.get(memory);
200          if ((data.type === 'MmapEvent' && memory === -1) || data.type === typeName) {
201            data.type = `${selections.length + 2}`;
202          }
203        } else {
204          if (
205            (data.type === 'MmapEvent' && memory === 1) ||
206            (data.type === 'FILE_PAGE_MSG' && memory === 2) ||
207            (data.type === 'MEMORY_USING_MSG' && memory === 3)
208          ) {
209            data.type = `${selections.length + 2}`;
210          }
211        }
212      });
213    }
214  }
215
216  filterByAnalysis(): void {
217    let filterContent: unknown[] = [];
218    let param = new Map<string, unknown>();
219    let selections: Array<unknown> = [];
220    this.setFilterType(selections, this._filterData!);
221    param.set('filterByTitleArr', this._filterData);
222    param.set('filterAllocType', '0');
223    param.set('statisticsSelection', selections);
224    param.set('leftNs', this.currentSelection?.leftNs);
225    param.set('rightNs', this.currentSelection?.rightNs);
226    filterContent.push(
227      {
228        funcName: 'groupCallchainSample',
229        funcArgs: [param],
230      },
231      {
232        funcName: 'getCallChainsBySampleIds',
233        funcArgs: [true],
234      }
235    );
236    this.getDataByWorker(filterContent, (result: unknown[]) => {
237      this.setLTableData(result); // @ts-ignore
238      this.nmCallTreeFrameChart!.data = this.nmCallTreeSource;
239      this.switchFlameChart();
240      this.nmCallTreeFilter!.icon = 'block';
241      this.initFromAnalysis = false;
242    });
243    this.banTypeAndLidSelect();
244  }
245
246  banTypeAndLidSelect(): void {
247    this.currentNMCallTreeFilter!.firstSelect = '0';
248    let secondSelect = this.shadowRoot
249      ?.querySelector('#nm-call-tree-filter')!
250      .shadowRoot!.querySelector('#second-select');
251    let thirdSelect = this.shadowRoot
252      ?.querySelector('#nm-call-tree-filter')!
253      .shadowRoot!.querySelector('#third-select');
254    thirdSelect?.setAttribute('disabled', '');
255    secondSelect?.setAttribute('disabled', '');
256  }
257
258  getParentTree(
259    nmCallTreeSrc: Array<FileMerageBean>,
260    nmCallTreeTarget: FileMerageBean,
261    parents: Array<FileMerageBean>
262  ): boolean {
263    for (let nmCallTreeBean of nmCallTreeSrc) {
264      if (nmCallTreeBean.id === nmCallTreeTarget.id) {
265        parents.push(nmCallTreeBean);
266        return true;
267      } else {
268        if (this.getParentTree(nmCallTreeBean.children as Array<FileMerageBean>, nmCallTreeTarget, parents)) {
269          parents.push(nmCallTreeBean);
270          return true;
271        }
272      }
273    }
274    return false;
275  }
276
277  getChildTree(nmCallTreeSrc: Array<FileMerageBean>, id: string, children: Array<FileMerageBean>): boolean {
278    for (let nmCallTreeBean of nmCallTreeSrc) {
279      if (nmCallTreeBean.id === id && nmCallTreeBean.children.length === 0) {
280        children.push(nmCallTreeBean);
281        return true;
282      } else {
283        if (this.getChildTree(nmCallTreeBean.children as Array<FileMerageBean>, id, children)) {
284          children.push(nmCallTreeBean);
285          return true;
286        }
287      }
288    }
289    return false;
290  }
291
292  setRightTableData(fileMerageBean: FileMerageBean): void {
293    let parents: Array<FileMerageBean> = [];
294    let children: Array<FileMerageBean> = []; // @ts-ignore
295    this.getParentTree(this.nmCallTreeSource, fileMerageBean, parents);
296    let maxId = fileMerageBean.id;
297    let maxDur = 0;
298
299    function findMaxStack(merageBean: unknown): void {
300      // @ts-ignore
301      if (merageBean.children.length === 0) {
302        // @ts-ignore
303        if (merageBean.heapSize > maxDur) {
304          // @ts-ignore
305          maxDur = merageBean.heapSize; // @ts-ignore
306          maxId = merageBean.id;
307        }
308      } else {
309        // @ts-ignore
310        merageBean.children.map((callChild: unknown): void => {
311          findMaxStack(<FileMerageBean>callChild);
312        });
313      }
314    }
315
316    findMaxStack(fileMerageBean);
317    this.getChildTree(fileMerageBean.children as Array<FileMerageBean>, maxId, children);
318    let resultValue = parents.reverse().concat(children.reverse());
319    for (let data of resultValue) {
320      data.type = data.lib.endsWith('.so.1') || data.lib.endsWith('.dll') || data.lib.endsWith('.so') ? 0 : 1;
321    }
322    let resultLength = resultValue.length;
323    this.filesystemTbr!.dataSource = resultLength === 0 ? [] : resultValue;
324  }
325
326  //底部的筛选菜单
327  showBottomMenu(isShow: boolean): void {
328    if (isShow) {
329      this.nmCallTreeFilter?.showThird(true);
330      this.nmCallTreeFilter?.setAttribute('first', '');
331      this.nmCallTreeFilter?.setAttribute('second', '');
332      this.nmCallTreeFilter?.setAttribute('tree', '');
333      this.nmCallTreeFilter?.setAttribute('input', '');
334      this.nmCallTreeFilter?.setAttribute('inputLeftText', '');
335    } else {
336      this.nmCallTreeFilter?.showThird(false);
337      this.nmCallTreeFilter?.removeAttribute('first');
338      this.nmCallTreeFilter?.removeAttribute('second');
339      this.nmCallTreeFilter?.removeAttribute('tree');
340      this.nmCallTreeFilter?.removeAttribute('input');
341      this.nmCallTreeFilter?.removeAttribute('inputLeftText');
342    }
343  }
344
345  async initFilterTypes(): Promise<void> {
346    this.currentNMCallTreeFilter = this.shadowRoot?.querySelector<TabPaneFilter>('#nm-call-tree-filter');
347    let secondFilterList = ['All Heap & Anonymous VM', 'All Heap', 'All Anonymous VM'];
348    const addSubType = (subTypeList: unknown): void => {
349      if (!subTypeList) {
350        return;
351      }
352      this.subTypeArr = []; // @ts-ignore
353      for (let data of subTypeList) {
354        secondFilterList.push(data.subType);
355        this.subTypeArr.push(data.subTypeId);
356      }
357    };
358    if (this.currentSelection!.nativeMemory!.length > 0) {
359      let subTypeList = await queryNativeHookSubType(
360        this.currentSelection!.leftNs,
361        this.currentSelection!.rightNs,
362        this.currentSelectIPid
363      );
364      addSubType(subTypeList);
365    } else {
366      let subTypeList = await queryNativeHookStatisticSubType(
367        this.currentSelection!.leftNs,
368        this.currentSelection!.rightNs,
369        this.currentSelectIPid
370      );
371      addSubType(subTypeList);
372    }
373    this.nMCallTreeFilterExtend(secondFilterList);
374  }
375
376  private nMCallTreeFilterExtend(secondFilterList: string[]): void {
377    procedurePool.submitWithName('logic0', 'native-memory-get-responseType', {}, undefined, (res: unknown) => {
378      // @ts-ignore
379      this.responseTypes = res;
380      let nullIndex = this.responseTypes.findIndex((item) => {
381        // @ts-ignore
382        return item.key === 0;
383      });
384      if (nullIndex !== -1) {
385        this.responseTypes.splice(nullIndex, 1);
386      }
387      this.currentNMCallTreeFilter!.setSelectList(
388        null,
389        secondFilterList,
390        'Allocation Lifespan',
391        'Allocation Type',
392        this.responseTypes.map((item: unknown) => {
393          // @ts-ignore
394          return item.value;
395        })
396      );
397      this.currentNMCallTreeFilter!.setFilterModuleSelect('#first-select', 'width', '150px');
398      this.currentNMCallTreeFilter!.setFilterModuleSelect('#second-select', 'width', '150px');
399      this.currentNMCallTreeFilter!.setFilterModuleSelect('#third-select', 'width', '150px');
400      this.currentNMCallTreeFilter!.firstSelect = '0';
401      this.currentNMCallTreeFilter!.secondSelect = '0';
402      this.currentNMCallTreeFilter!.thirdSelect = '0';
403      this.filterAllocationType = '0';
404      this.filterNativeType = '0';
405      this.filterResponseSelect = '0';
406      this.filterResponseType = -1;
407    });
408  }
409
410  initElements(): void {
411    this.headLine = this.shadowRoot?.querySelector<LitHeadLine>('.titleBox');
412    this.nmCallTreeTbl = this.shadowRoot?.querySelector<LitTable>('#tb-filesystem-calltree');
413    this.nmCallTreeProgressEL = this.shadowRoot?.querySelector('.nm-call-tree-progress') as LitProgressBar;
414    this.nmCallTreeFrameChart = this.shadowRoot?.querySelector<FrameChart>('#framechart');
415    this.nmCallTreeFrameChart!.mode = ChartMode.Byte;
416    this.nmCallTreeLoadingPage = this.shadowRoot?.querySelector('.nm-call-tree-loading');
417    this.nmCallTreeFrameChart!.addChartClickListener((needShowMenu: boolean): void => {
418      this.parentElement!.scrollTo(0, 0);
419      this.showBottomMenu(needShowMenu);
420      this.needShowMenu = needShowMenu;
421    });
422    this.nmCallTreeTbl!.rememberScrollTop = true;
423    this.nmCallTreeTbl!.exportTextHandleMap.set('heapSizeStr', (value) => {
424      // @ts-ignore
425      return `${value.size}`;
426    });
427    this.nmCallTreeFilter = this.shadowRoot?.querySelector<TabPaneFilter>('#nm-call-tree-filter');
428    this.filesystemTbr = this.shadowRoot?.querySelector<LitTable>('#tb-filesystem-list');
429    let filterFunc = (nmCallTreeFuncData: unknown): void => {
430      let nmCallTreeFuncArgs: unknown[] = []; // @ts-ignore
431      if (nmCallTreeFuncData.type === 'check') {
432        nmCallTreeFuncArgs = this.filterFuncByCheckType(nmCallTreeFuncData, nmCallTreeFuncArgs); // @ts-ignore
433      } else if (nmCallTreeFuncData.type === 'select') {
434        nmCallTreeFuncArgs = this.filterFuncBySelectType(nmCallTreeFuncData, nmCallTreeFuncArgs); // @ts-ignore
435      } else if (nmCallTreeFuncData.type === 'button') {
436        nmCallTreeFuncArgs = this.filterFuncByButtonType(nmCallTreeFuncData, nmCallTreeFuncArgs);
437      }
438      this.getDataByWorker(nmCallTreeFuncArgs, (result: unknown[]): void => {
439        this.setLTableData(result); // @ts-ignore
440        this.nmCallTreeFrameChart!.data = this.nmCallTreeSource;
441        if (this.isChartShow) {
442          this.nmCallTreeFrameChart?.calculateChartData();
443        }
444        this.nmCallTreeTbl!.move1px();
445        if (this.currentSelectedData) {
446          // @ts-ignore
447          this.currentSelectedData.isSelected = false;
448          this.nmCallTreeTbl?.clearAllSelection(this.currentSelectedData);
449          this.filesystemTbr!.recycleDataSource = [];
450          this.currentSelectedData = undefined;
451        }
452      });
453    };
454    this.nmCallTreeFilter!.getDataLibrary(filterFunc.bind(this));
455    this.nmCallTreeFilter!.getDataMining(filterFunc.bind(this));
456    this.nmCallTreeFilter!.getCallTreeData(this.getCallTreeByNMCallTreeFilter.bind(this));
457    this.nmCallTreeFilter!.getCallTreeConstraintsData(this.getCallTreeConByNMCallTreeFilter.bind(this));
458    this.nmCallTreeFilter!.getFilterData(this.getFilterDataByNMCallTreeFilter.bind(this));
459    this.initCloseCallBackByHeadLine();
460  }
461
462  private getFilterDataByNMCallTreeFilter(nmCallTreeData: FilterData): void {
463    if (
464      (this.isChartShow && nmCallTreeData.icon === 'tree') ||
465      (!this.isChartShow && nmCallTreeData.icon === 'block')
466    ) {
467      this.switchFlameChart(nmCallTreeData);
468    } else {
469      this.initGetFilterByNMCallTreeFilter(nmCallTreeData);
470    }
471  }
472
473  private getCallTreeConByNMCallTreeFilter(nmCallTreeConstraintsData: unknown): void {
474    let nmCallTreeConstraintsArgs: unknown[] = [
475      {
476        funcName: 'resotreAllNode',
477        funcArgs: [[this.numRuleName]],
478      },
479      {
480        funcName: 'clearSplitMapData',
481        funcArgs: [this.numRuleName],
482      },
483    ]; // @ts-ignore
484    if (nmCallTreeConstraintsData.checked) {
485      nmCallTreeConstraintsArgs.push({
486        funcName: 'hideNumMaxAndMin',
487        // @ts-ignore
488        funcArgs: [parseInt(nmCallTreeConstraintsData.min), nmCallTreeConstraintsData.max],
489      });
490    }
491    nmCallTreeConstraintsArgs.push({
492      funcName: 'resetAllNode',
493      funcArgs: [],
494    });
495    this.getDataByWorker(nmCallTreeConstraintsArgs, (result: unknown[]): void => {
496      this.setLTableData(result); // @ts-ignore
497      this.nmCallTreeFrameChart!.data = this.nmCallTreeSource;
498      if (this.isChartShow) {
499        this.nmCallTreeFrameChart?.calculateChartData();
500      }
501    });
502  }
503
504  private getCallTreeByNMCallTreeFilter(callTreeData: unknown): void {
505    // @ts-ignore
506    if ([InvertOpyionIndex, HideSystemSoOptionIndex, HideThreadOptionIndex].includes(callTreeData.value)) {
507      this.refreshAllNode({
508        ...this.nmCallTreeFilter!.getFilterTreeData(),
509        // @ts-ignore
510        callTree: callTreeData.checks,
511      });
512    } else {
513      let resultArgs: unknown[] = [];
514      // @ts-ignore
515      if (callTreeData.checks[1]) {
516        resultArgs.push({
517          funcName: 'hideSystemLibrary',
518          funcArgs: [],
519        });
520        resultArgs.push({
521          funcName: 'resetAllNode',
522          funcArgs: [],
523        });
524      } else {
525        resultArgs.push({
526          funcName: 'resotreAllNode',
527          funcArgs: [[this.systmeRuleName]],
528        });
529        resultArgs.push({
530          funcName: 'resetAllNode',
531          funcArgs: [],
532        });
533        resultArgs.push({
534          funcName: 'clearSplitMapData',
535          funcArgs: [this.systmeRuleName],
536        });
537      }
538      this.getDataByWorker(resultArgs, (result: unknown[]): void => {
539        this.setLTableData(result); // @ts-ignore
540        this.nmCallTreeFrameChart!.data = this.nmCallTreeSource;
541        if (this.isChartShow) {
542          this.nmCallTreeFrameChart?.calculateChartData();
543        }
544      });
545    }
546  }
547
548  private filterFuncByButtonType(nmCallTreeFuncData: unknown, nmCallTreeFuncArgs: unknown[]): unknown[] {
549    // @ts-ignore
550    if (nmCallTreeFuncData.item === 'symbol') {
551      // @ts-ignore
552      if (this.currentSelectedData && !this.currentSelectedData.canCharge) {
553        return nmCallTreeFuncArgs;
554      }
555      if (this.currentSelectedData !== undefined) {
556        // @ts-ignore
557        this.nmCallTreeFilter!.addDataMining({ name: this.currentSelectedData.symbol }, nmCallTreeFuncData.item);
558        nmCallTreeFuncArgs.push({
559          funcName: 'splitTree',
560          // @ts-ignore
561          funcArgs: [this.currentSelectedData.symbol, false, true],
562        });
563      } else {
564        return nmCallTreeFuncArgs;
565      } // @ts-ignore
566    } else if (nmCallTreeFuncData.item === 'library') {
567      // @ts-ignore
568      if (this.currentSelectedData && !this.currentSelectedData.canCharge) {
569        return nmCallTreeFuncArgs;
570      } // @ts-ignore
571      if (this.currentSelectedData !== undefined && this.currentSelectedData.libName !== '') {
572        // @ts-ignore
573        this.nmCallTreeFilter!.addDataMining({ name: this.currentSelectedData.libName }, nmCallTreeFuncData.item);
574        nmCallTreeFuncArgs.push({
575          funcName: 'splitTree',
576          // @ts-ignore
577          funcArgs: [this.currentSelectedData.libName, false, false],
578        });
579      } else {
580        return nmCallTreeFuncArgs;
581      } // @ts-ignore
582    } else if (nmCallTreeFuncData.item === 'restore') {
583      // @ts-ignore
584      if (nmCallTreeFuncData.remove !== undefined && nmCallTreeFuncData.remove.length > 0) {
585        // @ts-ignore
586        let list = nmCallTreeFuncData.remove.map((item: unknown): unknown => {
587          // @ts-ignore
588          return item.name;
589        });
590        nmCallTreeFuncArgs.push({ funcName: 'resotreAllNode', funcArgs: [list] });
591        nmCallTreeFuncArgs.push({ funcName: 'resetAllNode', funcArgs: [] });
592        list.forEach((symbol: string): void => {
593          nmCallTreeFuncArgs.push({ funcName: 'clearSplitMapData', funcArgs: [symbol] });
594        });
595      }
596    }
597    return nmCallTreeFuncArgs;
598  }
599
600  private filterFuncBySelectType(nmCallTreeFuncData: unknown, nmCallTreeFuncArgs: unknown[]): unknown[] {
601    nmCallTreeFuncArgs.push({
602      funcName: 'resotreAllNode',
603      // @ts-ignore
604      funcArgs: [[nmCallTreeFuncData.item.name]],
605    });
606    nmCallTreeFuncArgs.push({
607      funcName: 'clearSplitMapData',
608      // @ts-ignore
609      funcArgs: [nmCallTreeFuncData.item.name],
610    });
611    nmCallTreeFuncArgs.push({
612      funcName: 'splitTree',
613      funcArgs: [
614        // @ts-ignore
615        nmCallTreeFuncData.item.name, // @ts-ignore
616        nmCallTreeFuncData.item.select === '0', // @ts-ignore
617        nmCallTreeFuncData.item.type === 'symbol',
618      ],
619    });
620    return nmCallTreeFuncArgs;
621  }
622
623  private filterFuncByCheckType(nmCallTreeFuncData: unknown, nmCallTreeFuncArgs: unknown[]): unknown[] {
624    // @ts-ignore
625    if (nmCallTreeFuncData.item.checked) {
626      nmCallTreeFuncArgs.push({
627        funcName: 'splitTree',
628        funcArgs: [
629          // @ts-ignore
630          nmCallTreeFuncData.item.name, // @ts-ignore
631          nmCallTreeFuncData.item.select === '0', // @ts-ignore
632          nmCallTreeFuncData.item.type === 'symbol',
633        ],
634      });
635    } else {
636      nmCallTreeFuncArgs.push({
637        funcName: 'resotreAllNode', // @ts-ignore
638        funcArgs: [[nmCallTreeFuncData.item.name]],
639      });
640      nmCallTreeFuncArgs.push({
641        funcName: 'resetAllNode',
642        funcArgs: [],
643      });
644      nmCallTreeFuncArgs.push({
645        funcName: 'clearSplitMapData', // @ts-ignore
646        funcArgs: [nmCallTreeFuncData.item.name],
647      });
648    }
649    return nmCallTreeFuncArgs;
650  }
651
652  private initGetFilterByNMCallTreeFilter(nmCallTreeData: FilterData): void {
653    if (
654      this.filterAllocationType !== nmCallTreeData.firstSelect ||
655      this.filterNativeType !== nmCallTreeData.secondSelect ||
656      this.filterResponseSelect !== nmCallTreeData.thirdSelect
657    ) {
658      this.filterAllocationType = nmCallTreeData.firstSelect || '0';
659      this.filterNativeType = nmCallTreeData.secondSelect || '0';
660      this.filterResponseSelect = nmCallTreeData.thirdSelect || '0';
661      let thirdIndex = parseInt(nmCallTreeData.thirdSelect || '0');
662      if (this.responseTypes.length > thirdIndex) {
663        // @ts-ignore
664        this.filterResponseType = this.responseTypes[thirdIndex].key || -1;
665      }
666      this.searchValue = this.nmCallTreeFilter!.filterValue;
667      this.expressionStruct = new ParseExpression(this.searchValue).parse();
668      this.refreshAllNode(this.nmCallTreeFilter!.getFilterTreeData());
669    } else if (this.searchValue !== this.nmCallTreeFilter!.filterValue) {
670      this.searchValue = this.nmCallTreeFilter!.filterValue;
671      this.expressionStruct = new ParseExpression(this.searchValue).parse();
672      let nmArgs = [];
673      if (this.expressionStruct) {
674        this.refreshAllNode(this.nmCallTreeFilter!.getFilterTreeData());
675        this.lastIsExpression = true;
676        return;
677      } else {
678        if (this.lastIsExpression) {
679          this.refreshAllNode(this.nmCallTreeFilter!.getFilterTreeData());
680          this.lastIsExpression = false;
681          return;
682        }
683        nmArgs.push({ funcName: 'setSearchValue', funcArgs: [this.searchValue] });
684        nmArgs.push({ funcName: 'resetAllNode', funcArgs: [] });
685        this.lastIsExpression = false;
686      }
687      this.getDataByWorker(nmArgs, (result: unknown[]): void => {
688        this.nmCallTreeTbl!.isSearch = true;
689        this.nmCallTreeTbl!.setStatus(result, true);
690        this.setLTableData(result); // @ts-ignore
691        this.nmCallTreeFrameChart!.data = this.nmCallTreeSource;
692        this.switchFlameChart(nmCallTreeData);
693        result = [];
694      });
695    } else {
696      this.nmCallTreeTbl!.setStatus(this.nmCallTreeSource, true);
697      this.setLTableData(this.nmCallTreeSource);
698      this.switchFlameChart(nmCallTreeData);
699    }
700  }
701
702  private initCloseCallBackByHeadLine(): void {
703    //点击之后删除掉筛选条件  将所有重置  将目前的title隐藏 高度恢复
704    this.headLine!.closeCallback = (): void => {
705      this.headLine!.clear();
706      this.searchValue = '';
707      this.currentNMCallTreeFilter!.filterValue = '';
708      this._filterData = undefined;
709      this.currentNMCallTreeFilter!.firstSelect = '0';
710      this.currentNMCallTreeFilter!.secondSelect = '0';
711      this.currentNMCallTreeFilter!.thirdSelect = '0';
712      this.filterAllocationType = '0';
713      this.refreshAllNode(this.nmCallTreeFilter!.getFilterTreeData(), true);
714      this.initFilterTypes();
715      this.nmCallTreeFrameChart?.resizeChange();
716    };
717  }
718
719  connectedCallback(): void {
720    super.connectedCallback();
721    this.nmCallTreeTbl!.addEventListener('row-click', this.nmCallTreeTblRowClickHandler);
722    this.filesystemTbr!.addEventListener('row-click', this.filesystemTbrRowClickHandler);
723    this.nmCallTreeTbl!.addEventListener('column-click', this.nmCallTreeTblColumnClickHandler);
724    let filterHeight = 0;
725    new ResizeObserver((entries: ResizeObserverEntry[]): void => {
726      let nmCallTreeTabFilter = this.shadowRoot!.querySelector('#nm-call-tree-filter') as HTMLElement;
727      if (nmCallTreeTabFilter.clientHeight > 0) {
728        filterHeight = nmCallTreeTabFilter.clientHeight;
729      }
730      if (this.parentElement!.clientHeight > filterHeight) {
731        nmCallTreeTabFilter.style.display = 'flex';
732      } else {
733        nmCallTreeTabFilter.style.display = 'none';
734      }
735      if (this.nmCallTreeTbl!.style.visibility === 'hidden') {
736        nmCallTreeTabFilter.style.display = 'none';
737      }
738      if (this.parentElement?.clientHeight !== 0) {
739        if (this.isChartShow) {
740          this.nmCallTreeFrameChart?.updateCanvas(false, entries[0].contentRect.width);
741          this.nmCallTreeFrameChart?.calculateChartData();
742        }
743        let headLineHeight = 0;
744        if (this.headLine?.isShow) {
745          headLineHeight = this.headLine!.clientHeight;
746        }
747        if (this.nmCallTreeTbl) {
748          // @ts-ignore
749          this.nmCallTreeTbl.shadowRoot.querySelector('.table').style.height = `${this.parentElement!.clientHeight - 10 - 35 - headLineHeight
750            }px`;
751        }
752        this.nmCallTreeTbl?.reMeauseHeight();
753        if (this.filesystemTbr) {
754          // @ts-ignore
755          this.filesystemTbr.shadowRoot.querySelector('.table').style.height = `${this.parentElement!.clientHeight - 45 - 21 - headLineHeight
756            }px`;
757        }
758        this.filesystemTbr?.reMeauseHeight(); // @ts-ignore
759        this.nmCallTreeLoadingPage.style.height = `${this.parentElement!.clientHeight - 24}px`;
760      }
761    }).observe(this.parentElement!);
762    this.parentElement!.onscroll = (): void => {
763      this.nmCallTreeFrameChart!.tabPaneScrollTop = this.parentElement!.scrollTop;
764    };
765  }
766
767  disconnectedCallback(): void {
768    super.disconnectedCallback();
769    this.nmCallTreeTbl!.removeEventListener('row-click', this.nmCallTreeTblRowClickHandler);
770    this.filesystemTbr!.removeEventListener('row-click', this.filesystemTbrRowClickHandler);
771    this.nmCallTreeTbl!.removeEventListener('column-click', this.nmCallTreeTblColumnClickHandler);
772  }
773
774  filesystemTbrRowClickHandler = (event: unknown): void => {
775    // @ts-ignore
776    let data = event.detail.data as FileMerageBean;
777    this.nmCallTreeTbl?.clearAllSelection(data); // @ts-ignore
778    (data as unknown).isSelected = true;
779    this.nmCallTreeTbl!.scrollToData(data); // @ts-ignore
780    if ((event.detail as unknown).callBack) {
781      // @ts-ignore
782      (event.detail as unknown).callBack(true);
783    }
784  };
785
786  nmCallTreeTblColumnClickHandler = (event: unknown): void => {
787    // @ts-ignore
788    this.sortKey = event.detail.key; // @ts-ignore
789    this.sortType = event.detail.sort;
790    this.setLTableData(this.nmCallTreeSource, true); // @ts-ignore
791    this.nmCallTreeFrameChart!.data = this.nmCallTreeSource;
792  };
793
794  nmCallTreeTblRowClickHandler = (event: unknown): void => {
795    // @ts-ignore
796    let nmCallTreeData = event.detail.data as FileMerageBean;
797    this.setRightTableData(nmCallTreeData);
798    nmCallTreeData.isSelected = true;
799    this.currentSelectedData = nmCallTreeData;
800    this.filesystemTbr?.clearAllSelection(nmCallTreeData);
801    this.filesystemTbr?.setCurrentSelection(nmCallTreeData);
802    // @ts-ignore
803    if ((event.detail as unknown).callBack) {
804      // @ts-ignore
805      (event.detail as unknown).callBack(true);
806    }
807    document.dispatchEvent(
808      new CustomEvent('number_calibration', {
809        // @ts-ignore
810        detail: { time: event.detail.tsArray, counts: event.detail.countArray },
811      })
812    );
813  };
814
815  private switchFlameChart(flameChartData?: unknown): void {
816    // 树状图
817    let nmCallTreePageTab = this.shadowRoot?.querySelector('#show_table');
818    // 火焰图
819    let nmCallTreePageChart = this.shadowRoot?.querySelector('#show_chart'); // @ts-ignore
820    if (!flameChartData || flameChartData.icon === 'block') {
821      nmCallTreePageChart?.setAttribute('class', 'show');
822      nmCallTreePageTab?.setAttribute('class', '');
823      this.isChartShow = true;
824      this.nmCallTreeFilter!.disabledMining = true;
825      this.showBottomMenu(this.needShowMenu);
826      this.nmCallTreeFrameChart?.calculateChartData(); // @ts-ignore
827    } else if (flameChartData.icon === 'tree') {
828      nmCallTreePageChart?.setAttribute('class', '');
829      nmCallTreePageTab?.setAttribute('class', 'show');
830      this.showBottomMenu(true);
831      this.isChartShow = false;
832      this.nmCallTreeFilter!.disabledMining = false;
833      this.nmCallTreeFrameChart!.clearCanvas();
834      this.nmCallTreeTbl!.reMeauseHeight();
835    }
836  }
837
838  private refreshAllNode(filterData: unknown, isAnalysisReset?: boolean): void {
839    let nmCallTreeArgs: unknown[] = []; // @ts-ignore
840    let isTopDown: boolean = !filterData.callTree[0]; // @ts-ignore
841    let isHideSystemLibrary = filterData.callTree[1]; // @ts-ignore
842    this.isHideThread = filterData.callTree[3]; // @ts-ignore
843    let list = filterData.dataMining.concat(filterData.dataLibrary);
844    let groupArgs = this.setGroupArgsByRefreshAllNode();
845    if ((this.lastIsExpression && !this.expressionStruct) || isAnalysisReset) {
846      nmCallTreeArgs.push({ funcName: 'setSearchValue', funcArgs: [this.searchValue] });
847    }
848    nmCallTreeArgs.push({ funcName: 'hideThread', funcArgs: [this.isHideThread] });
849    nmCallTreeArgs.push(
850      {
851        funcName: 'groupCallchainSample',
852        funcArgs: [groupArgs],
853      },
854      {
855        funcName: 'getCallChainsBySampleIds',
856        funcArgs: [isTopDown],
857      }
858    );
859    this.filesystemTbr!.recycleDataSource = [];
860    if (isHideSystemLibrary) {
861      nmCallTreeArgs.push({
862        funcName: 'hideSystemLibrary',
863        funcArgs: [],
864      });
865    } // @ts-ignore
866    if (filterData.callTreeConstraints.checked) {
867      nmCallTreeArgs.push({
868        funcName: 'hideNumMaxAndMin', // @ts-ignore
869        funcArgs: [parseInt(filterData.callTreeConstraints.inputs[0]), filterData.callTreeConstraints.inputs[1]],
870      });
871    }
872    nmCallTreeArgs.push({ funcName: 'splitAllProcess', funcArgs: [list] });
873    nmCallTreeArgs.push({ funcName: 'resetAllNode', funcArgs: [] });
874    this.getDataByWorker(nmCallTreeArgs, (result: unknown[]) => {
875      this.setLTableData(result); // @ts-ignore
876      this.nmCallTreeFrameChart!.data = this.nmCallTreeSource;
877      if (this.isChartShow) {
878        this.nmCallTreeFrameChart?.calculateChartData();
879      }
880    });
881  }
882
883  private setGroupArgsByRefreshAllNode(): Map<string, unknown> {
884    let groupArgs = new Map<string, unknown>();
885    groupArgs.set('filterAllocType', this.filterAllocationType);
886    groupArgs.set('filterEventType', this.filterNativeType);
887    if (this.expressionStruct) {
888      groupArgs.set('filterExpression', this.expressionStruct);
889      groupArgs.set('filterResponseType', -1);
890      this.currentNMCallTreeFilter!.thirdSelect = '0';
891    } else {
892      groupArgs.set('filterResponseType', this.filterResponseType);
893    }
894    groupArgs.set('leftNs', this.currentSelection?.leftNs || 0);
895    groupArgs.set('rightNs', this.currentSelection?.rightNs || 0);
896    let selections: Array<unknown> = [];
897    if (this.subTypeArr.length > 0) {
898      this.subTypeArr.map((memory): void => {
899        selections.push({
900          memoryTap: memory,
901        });
902      });
903    }
904    groupArgs.set('statisticsSelection', selections);
905    if (this._filterData) {
906      groupArgs.set('filterByTitleArr', this._filterData);
907    }
908    groupArgs.set(
909      'nativeHookType',
910      this.currentSelection!.nativeMemory.length > 0 ? 'native-hook' : 'native-hook-statistic'
911    );
912    return groupArgs;
913  }
914
915  setLTableData(resultData: unknown[], sort?: boolean): void {
916    if (sort) {
917      this.nmCallTreeSource = this.sortTree(resultData);
918    } else {
919      if (resultData && resultData[0]) {
920        this.nmCallTreeSource =
921          this.currentSelection!.nativeMemory.length > 0 && !this.isHideThread
922            ? this.sortTree(resultData) // @ts-ignore
923            : this.sortTree(resultData[0].children || []);
924      } else {
925        this.nmCallTreeSource = [];
926      }
927    }
928    this.nmCallTreeTbl!.recycleDataSource = this.nmCallTreeSource;
929  }
930
931  sortTree(arr: Array<unknown>): Array<unknown> {
932    let nmCallTreeSortArr = arr.sort((callTreeLeftData, callTreeRightData): number => {
933      if (this.sortKey === 'heapSizeStr' || this.sortKey === 'heapPercent') {
934        if (this.sortType === 0) {
935          // @ts-ignore
936          return callTreeRightData.size - callTreeLeftData.size;
937        } else if (this.sortType === 1) {
938          // @ts-ignore
939          return callTreeLeftData.size - callTreeRightData.size;
940        } else {
941          // @ts-ignore
942          return callTreeRightData.size - callTreeLeftData.size;
943        }
944      } else {
945        if (this.sortType === 0) {
946          // @ts-ignore
947          return callTreeRightData.count - callTreeLeftData.count;
948        } else if (this.sortType === 1) {
949          // @ts-ignore
950          return callTreeLeftData.count - callTreeRightData.count;
951        } else {
952          // @ts-ignore
953          return callTreeRightData.count - callTreeLeftData.count;
954        }
955      }
956    });
957    nmCallTreeSortArr.map((call): void => {
958      // @ts-ignore
959      call.children = this.sortTree(call.children);
960    });
961    return nmCallTreeSortArr;
962  }
963
964  getDataByWorker(args: unknown[], handler: Function): void {
965    this.loadingList.push(1);
966    this.nmCallTreeProgressEL!.loading = true; // @ts-ignore
967    this.nmCallTreeLoadingPage.style.visibility = 'visible';
968    procedurePool.submitWithName(
969      'logic0',
970      'native-memory-calltree-action',
971      args,
972      undefined,
973      (callTreeActionResults: unknown): void => {
974        handler(callTreeActionResults);
975        this.loadingList.splice(0, 1);
976        if (this.loadingList.length === 0) {
977          this.nmCallTreeProgressEL!.loading = false; // @ts-ignore
978          this.nmCallTreeLoadingPage.style.visibility = 'hidden';
979        }
980      }
981    );
982  }
983
984  getDataByWorkerQuery(args: unknown, handler: Function): void {
985    // 加载中样式设置
986    this.loadingList.push(1);
987    this.nmCallTreeProgressEL!.loading = true; // @ts-ignore
988    this.nmCallTreeLoadingPage.style.visibility = 'visible';
989    procedurePool.submitWithName(
990      'logic0',
991      this.currentSelection!.nativeMemory!.length > 0
992        ? 'native-memory-queryCallchainsSamples'
993        : 'native-memory-queryStatisticCallchainsSamples',
994      args,
995      undefined,
996      (callChainsResults: unknown): void => {
997        handler(callChainsResults);
998        this.loadingList.splice(0, 1);
999        if (this.loadingList.length === 0) {
1000          this.nmCallTreeProgressEL!.loading = false; // @ts-ignore
1001          this.nmCallTreeLoadingPage.style.visibility = 'hidden';
1002        }
1003      }
1004    );
1005  }
1006
1007  initHtml(): string {
1008    return TabPaneNMCallTreeHtml;
1009  }
1010}
1011