• 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 */
15import { BaseElement, element } from '../../../../../base-ui/BaseElement';
16import { LitTable } from '../../../../../base-ui/table/lit-table';
17import { SelectionParam } from '../../../../bean/BoxSelection';
18import { LitChartPie } from '../../../../../base-ui/chart/pie/LitChartPie';
19import '../../../../../base-ui/chart/pie/LitChartPie';
20import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar';
21import { Utils } from '../../base/Utils';
22import { SpSystemTrace } from '../../../SpSystemTrace';
23import { procedurePool } from '../../../../database/Procedure';
24import { TabPaneFilter } from '../TabPaneFilter';
25import { LitCheckBox } from '../../../../../base-ui/checkbox/LitCheckBox';
26import { initSort } from '../SheetUtils';
27import { TabpaneNMCalltree } from './TabPaneNMCallTree';
28import { FilterByAnalysis } from '../../../../bean/NativeHook';
29import { InitAnalysis } from '../../../../database/logic-worker/ProcedureLogicWorkerCommon';
30import { TabPaneNMStatisticAnalysisHtml } from './TabPaneNMStatisticAnalysis.html';
31
32const TYPE_ALLOC_STRING = 'AllocEvent';
33const TYPE_MAP_STRING = 'MmapEvent';
34const TYPE_OTHER_MMAP = 'Other MmapEvent';
35
36const TYPE_ALLOC = 0;
37const TYPE_MAP = 1;
38const TYPE_FREE = 2;
39const TYPE_UN_MAP = 3;
40const PIE_CHART_LIMIT = 20;
41
42class AnalysisObj {
43  tName?: string;
44  tid?: number;
45  typeName?: string;
46  typeId?: number;
47  libName?: string;
48  libId?: number;
49  symbolName?: string;
50  symbolId?: number;
51
52  tableName = '';
53
54  applySize: number;
55  applySizeFormat: string;
56  applyCount: number;
57  releaseSize: number;
58  releaseSizeFormat: string;
59  releaseCount: number;
60  existSize: number;
61  existSizeFormat: string;
62  existCount: number;
63
64  applySizePercent?: string;
65  applyCountPercent?: string;
66  releaseSizePercent?: string;
67  releaseCountPercent?: string;
68  existSizePercent?: string;
69  existCountPercent?: string;
70
71  constructor(applySize: number, applyCount: number, releaseSize: number, releaseCount: number) {
72    this.applySize = applySize;
73    this.applyCount = applyCount;
74    this.releaseSize = releaseSize;
75    this.releaseCount = releaseCount;
76    this.existSize = applySize - releaseSize;
77    this.existCount = applyCount - releaseCount;
78    this.applySizeFormat = Utils.getBinaryByteWithUnit(this.applySize);
79    this.releaseSizeFormat = Utils.getBinaryByteWithUnit(this.releaseSize);
80    this.existSizeFormat = Utils.getBinaryByteWithUnit(this.existSize);
81  }
82}
83
84class SizeObj {
85  applySize = 0;
86  applyCount = 0;
87  releaseSize = 0;
88  releaseCount = 0;
89}
90
91@element('tabpane-nm-statistic-analysis')
92export class TabPaneNMStatisticAnalysis extends BaseElement {
93  private currentSelection: SelectionParam | unknown;
94  private nmPieChart: LitChartPie | null | undefined;
95  private nmTableBox: HTMLDivElement | undefined | null;
96  private processData!: Array<unknown>;
97  private eventTypeData!: Array<AnalysisObj>;
98  private threadData!: Array<AnalysisObj>;
99  private soData!: Array<AnalysisObj>;
100  private functionData!: Array<AnalysisObj>;
101  private typeUsageTbl: LitTable | null | undefined;
102  private threadUsageTbl: LitTable | null | undefined;
103  private soUsageTbl: LitTable | null | undefined;
104  private functionUsageTbl: LitTable | null | undefined;
105  private range: HTMLLabelElement | null | undefined;
106  private nmBack: HTMLDivElement | null | undefined;
107  private threadName: string = '';
108  private tabName: HTMLDivElement | null | undefined;
109  private progressEL: LitProgressBar | null | undefined;
110  private type: string = '';
111  private isStatistic = false;
112  private typeMap!: Map<number, Array<unknown>>;
113  private currentLevel = -1;
114  private currentLevelApplySize = 0;
115  private currentLevelReleaseSize = 0;
116  private currentLevelExistSize = 0;
117  private currentLevelApplyCount = 0;
118  private currentLevelReleaseCount = 0;
119  private currentLevelExistCount = 0;
120  private currentLevelData!: Array<unknown>;
121  private typeStatisticsData!: {};
122  private threadStatisticsData!: {};
123  private libStatisticsData!: {};
124  private functionStatisticsData!: {};
125  private nmTableArray: NodeListOf<LitTable> | undefined | null;
126  private nmSortColumn: string = '';
127  private nmSortType: number = 0;
128  private titleEl: HTMLDivElement | undefined | null;
129  private filterEl: TabPaneFilter | undefined | null;
130  private hideThreadCheckBox: LitCheckBox | undefined | null;
131
132  get titleTxt(): string | null {
133    return this.titleEl!.textContent;
134  }
135
136  set data(statisticAnalysisParam: SelectionParam) {
137    if (statisticAnalysisParam === this.currentSelection) {
138      if (this.eventTypeData) {
139        // @ts-ignore
140        this.eventTypeData.unshift(this.typeStatisticsData);
141        this.typeUsageTbl!.recycleDataSource = this.eventTypeData;
142        // @ts-ignore
143        this.eventTypeData.shift(this.typeStatisticsData);
144      }
145      return;
146    }
147    if (this.nmTableArray) {
148      for (let table of this.nmTableArray) {
149        initSort(table!, this.nmSortColumn, this.nmSortType);
150      }
151    }
152    this.hideThreadCheckBox!.checked = false;
153    if (statisticAnalysisParam.nativeMemoryStatistic.length > 0) {
154      Utils.getInstance().setCurrentSelectIPid(statisticAnalysisParam.nativeMemoryCurrentIPid);
155      Utils.getInstance().initResponseTypeList(statisticAnalysisParam);
156    }
157    this.resizeTable();
158    this.reset(this.typeUsageTbl!, false);
159    this.currentSelection = statisticAnalysisParam;
160    this.titleEl!.textContent = '';
161    this.tabName!.textContent = '';
162    this.range!.textContent = `Selected range: ${parseFloat(
163      ((statisticAnalysisParam.rightNs - statisticAnalysisParam.leftNs) / 1000000.0).toFixed(5)
164    )}  ms`;
165    this.isStatistic = statisticAnalysisParam.nativeMemory.length === 0;
166    if (this.isStatistic) {
167      this.threadName = '';
168    }
169    this.getNMEventTypeSize(statisticAnalysisParam);
170    this.showAssignLevel(this.typeUsageTbl!, this.functionUsageTbl!, 0, this.eventTypeData);
171  }
172
173  initNmTableArray(): void {
174    this.nmTableArray = this.shadowRoot!.querySelectorAll('lit-table') as NodeListOf<LitTable>;
175    for (let nmTable of this.nmTableArray) {
176      nmTable!.addEventListener('contextmenu', function (event) {
177        event.preventDefault(); // 阻止默认的上下文菜单弹框
178      });
179      nmTable!.addEventListener('column-click', (evt) => {
180        // @ts-ignore
181        this.nmSortColumn = evt.detail.key;
182        // @ts-ignore
183        this.nmSortType = evt.detail.sort;
184        this.sortByColumn();
185      });
186      nmTable!.addEventListener('row-hover', (evt) => {
187        // @ts-ignore
188        let detail = evt.detail;
189        if (detail.data) {
190          let data = detail.data;
191          data.isHover = true;
192          if (detail.callBack) {
193            detail.callBack(true);
194          }
195        }
196        this.nmPieChart?.showHover();
197        this.nmPieChart?.hideTip();
198      });
199    }
200    this.threadUsageTbl!.addEventListener('row-click', (evt) => {
201      // @ts-ignore
202      let button = evt.detail.button;
203      // @ts-ignore
204      let data = evt.detail.data;
205      if (button === 0) {
206        if (data.tableName !== '' && data.existSize !== 0) {
207          this.nativeThreadLevelClickEvent(data);
208        }
209      } else if (button === 2) {
210        let title = `${this.titleEl!.textContent}/${data.tName}`;
211        this.clickRight(evt, title);
212      }
213    });
214  }
215
216  initTable(): void {
217    this.typeUsageTbl!.addEventListener('row-click', (evt) => {
218      // @ts-ignore
219      let button = evt.detail.button;
220      // @ts-ignore
221      let data = evt.detail.data;
222      if (button === 0) {
223        if (data.tableName !== '' && data.existSize !== 0) {
224          this.nativeProcessLevelClickEvent(data);
225        }
226      } else if (button === 2) {
227        const typeName = data.typeName === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : data.typeName;
228        this.clickRight(evt, typeName);
229      }
230    });
231    this.soUsageTbl!.addEventListener('row-click', (evt) => {
232      // @ts-ignore
233      let button = evt.detail.button;
234      // @ts-ignore
235      let data = evt.detail.data;
236      if (button === 0) {
237        if (data.tableName !== '' && data.existSize !== 0) {
238          this.nativeSoLevelClickEvent(data);
239        }
240      } else if (button === 2) {
241        let title = `${this.titleEl!.textContent}/${data.libName}`;
242        this.clickRight(evt, title);
243      }
244    });
245  }
246
247  initElements(): void {
248    this.range = this.shadowRoot?.querySelector('#time-range');
249    this.nmPieChart = this.shadowRoot!.querySelector<LitChartPie>('#nm-chart-pie');
250    this.nmTableBox = this.shadowRoot!.querySelector<HTMLDivElement>('.nm-table-box');
251    this.typeUsageTbl = this.shadowRoot!.querySelector<LitTable>('#tb-eventtype-usage');
252    this.threadUsageTbl = this.shadowRoot!.querySelector<LitTable>('#tb-thread-usage');
253    this.soUsageTbl = this.shadowRoot!.querySelector<LitTable>('#tb-so-usage');
254    this.functionUsageTbl = this.shadowRoot!.querySelector<LitTable>('#tb-function-usage');
255    this.nmBack = this.shadowRoot!.querySelector<HTMLDivElement>('.nm-go-back');
256    this.tabName = this.shadowRoot!.querySelector<HTMLDivElement>('.nm-subheading');
257    this.progressEL = this.shadowRoot?.querySelector('.nm-progress') as LitProgressBar;
258    this.getBack();
259    this.titleEl = this.shadowRoot!.querySelector<HTMLDivElement>('.title');
260    this.filterEl = this.shadowRoot?.querySelector('#filter');
261    this.filterEl!.setOptionsList(['Hide Thread']);
262    let popover = this.filterEl!.shadowRoot!.querySelector('#check-popover');
263    this.hideThreadCheckBox = popover!!.querySelector<LitCheckBox>('div > #hideThread');
264    this.hideThreadCheckBox?.addEventListener('change', () => {
265      this.reset(this.typeUsageTbl!, false);
266      this.showAssignLevel(this.typeUsageTbl!, this.functionUsageTbl!, 0, this.eventTypeData); // @ts-ignore
267      this.getNMTypeSize(this.currentSelection, this.processData);
268    });
269    this.initNmTableArray();
270    this.initTable();
271    this.functionUsageTbl?.addEventListener('row-click', (evt) => {
272      // @ts-ignore
273      let title = `${this.titleEl!.textContent}/${evt.detail.data.symbolName}`;
274      this.clickRight(evt, title);
275    });
276    let exportHandlerMap = new Map<string, (value: unknown) => string>();
277    exportHandlerMap.set('existSizeFormat', (value) => {
278      // @ts-ignore
279      return `${value.existSize}`;
280    });
281    exportHandlerMap.set('applySizeFormat', (value) => {
282      // @ts-ignore
283      return `${value.applySize}`;
284    });
285    exportHandlerMap.set('releaseSizeFormat', (value) => {
286      // @ts-ignore
287      return `${value.releaseSize}`;
288    });
289    this.typeUsageTbl!.exportTextHandleMap = exportHandlerMap;
290    this.threadUsageTbl!.exportTextHandleMap = exportHandlerMap;
291    this.soUsageTbl!.exportTextHandleMap = exportHandlerMap;
292    this.functionUsageTbl!.exportTextHandleMap = exportHandlerMap;
293  }
294
295  private clickRight(evt: unknown, title: string): void {
296    // @ts-ignore
297    if (evt.detail.button === 2 && evt.detail.tableName && evt.detail.tableName !== '') {
298      let treeTab = this.parentElement?.parentElement?.querySelector<TabpaneNMCalltree>(
299        '#box-native-calltree > tabpane-nm-calltree'
300      );
301      treeTab!.analysisTabWidth = this.clientWidth; // @ts-ignore
302      const data = evt.detail.data as AnalysisObj;
303      treeTab!.filterData = new FilterByAnalysis(
304        data.typeId,
305        data.typeName,
306        data.tName,
307        data.tid,
308        data.libId,
309        data.libName,
310        data.symbolId,
311        data.symbolName
312      );
313      // 首次打开初始化数据 非首次初始化UI
314      if (!InitAnalysis.getInstance().isInitAnalysis) {
315        treeTab?.initUI();
316        treeTab?.filterByAnalysis();
317      } else {
318        treeTab!.initFromAnalysis = true; // @ts-ignore
319        treeTab!.data = this.currentSelection;
320        InitAnalysis.getInstance().isInitAnalysis = false;
321      }
322
323      treeTab!.banTypeAndLidSelect();
324      treeTab!.titleBoxShow = true;
325      treeTab!.titleTxt = title;
326    }
327  }
328
329  private getDataFromWorker(val: SelectionParam, typeFilter: Array<number | string>): void {
330    this.getDataByWorkerQuery(
331      {
332        leftNs: val.leftNs,
333        rightNs: val.rightNs,
334        types: typeFilter,
335        isStatistic: this.isStatistic,
336      },
337      (results: unknown) => {
338        this.processData = JSON.parse(JSON.stringify(results));
339        this.getNMTypeSize(val, this.processData);
340      }
341    );
342  }
343
344  private getDataByWorkerQuery(args: unknown, handler: Function): void {
345    this.progressEL!.loading = true;
346    procedurePool.submitWithName('logic0', 'native-memory-queryAnalysis', args, undefined, (results: unknown) => {
347      handler(results);
348      this.progressEL!.loading = false;
349    });
350  }
351
352  private reset(showTable: LitTable, isShowBack: boolean): void {
353    this.clearData();
354    if (isShowBack) {
355      this.nmBack!.style.visibility = 'visible';
356    } else {
357      this.nmBack!.style.visibility = 'hidden';
358    }
359    if (this.nmTableArray) {
360      for (let table of this.nmTableArray) {
361        if (table === showTable) {
362          initSort(table, this.nmSortColumn, this.nmSortType);
363          table.style.display = 'grid';
364          table!.removeAttribute('hideDownload');
365        } else {
366          table!.style.display = 'none';
367          table.setAttribute('hideDownload', '');
368        }
369      }
370    }
371  }
372
373  private clearData(): void {
374    this.nmPieChart!.dataSource = [];
375    this.typeUsageTbl!.recycleDataSource = [];
376    this.threadUsageTbl!.recycleDataSource = [];
377    this.soUsageTbl!.recycleDataSource = [];
378    this.functionUsageTbl!.recycleDataSource = [];
379  }
380
381  private showAssignLevel(
382    showNMTable: LitTable,
383    hideNMTable: LitTable,
384    currentLevel: number,
385    currentLevelData: Array<unknown>
386  ): void {
387    showNMTable!.style.display = 'grid';
388    hideNMTable!.style.display = 'none';
389    hideNMTable.setAttribute('hideDownload', '');
390    showNMTable?.removeAttribute('hideDownload');
391    this.currentLevel = currentLevel;
392    this.currentLevelData = currentLevelData;
393  }
394
395  private getBack(): void {
396    this.nmBack!.addEventListener('click', () => {
397      if (this.tabName!.textContent === 'Statistic By Thread Existing') {
398        this.showAssignLevel(this.typeUsageTbl!, this.threadUsageTbl!, 0, this.eventTypeData);
399        this.nmBack!.style.visibility = 'hidden';
400        this.typePieChart();
401      } else if (this.tabName!.textContent === 'Statistic By Library Existing') {
402        if (this.hideThreadCheckBox?.checked || this.isStatistic) {
403          this.showAssignLevel(this.typeUsageTbl!, this.soUsageTbl!, 0, this.eventTypeData);
404          this.nmBack!.style.visibility = 'hidden';
405          this.typePieChart();
406        } else {
407          this.showAssignLevel(this.threadUsageTbl!, this.soUsageTbl!, 1, this.threadData);
408          this.threadPieChart();
409        }
410      } else if (this.tabName!.textContent === 'Statistic By Function Existing') {
411        this.showAssignLevel(this.soUsageTbl!, this.functionUsageTbl!, 2, this.soData);
412        this.libraryPieChart();
413      }
414    });
415  }
416
417  private typePieChart(): void {
418    this.nmPieChart!.config = {
419      appendPadding: 0,
420      data: this.getPieChartData(this.eventTypeData),
421      angleField: 'existSize',
422      colorField: 'tableName',
423      radius: 1,
424      label: {
425        type: 'outer',
426      },
427      tip: (typeTipValue): string => {
428        // @ts-ignore
429        const obj = typeTipValue.obj as AnalysisObj;
430        return `<div>
431                    <div>Memory Type:${obj.tableName}</div>
432                    <div>Existing:${obj.existSizeFormat} (${obj.existSizePercent}%)</div>
433                    <div># Existing:${obj.existCount} (${obj.existCountPercent}%)</div>
434                    <div>Total Bytes:${obj.applySizeFormat} (${obj.applySizePercent}%)</div>
435                    <div># Total:${obj.applyCount} (${obj.applyCountPercent}%)</div>
436                    <div>Transient:${obj.releaseSizeFormat} (${obj.releaseSizePercent}%)</div>
437                    <div># Transient:${obj.releaseCount} (${obj.releaseCountPercent}%)</div>
438                </div>`;
439      },
440      angleClick: (it): void => {
441        // @ts-ignore
442        if (it.tableName !== 'other') {
443          this.nativeProcessLevelClickEvent(it);
444        }
445      },
446      hoverHandler: (nmData): void => {
447        if (nmData) {
448          this.typeUsageTbl!.setCurrentHover(nmData);
449        } else {
450          this.typeUsageTbl!.mouseOut();
451        }
452      },
453      interactions: [
454        {
455          type: 'element-active',
456        },
457      ],
458    };
459
460    this.titleEl!.textContent = '';
461    this.tabName!.textContent = 'Statistic By Event Type Existing';
462    // @ts-ignore
463    this.eventTypeData.unshift(this.typeStatisticsData);
464    this.typeUsageTbl!.recycleDataSource = this.eventTypeData;
465    // @ts-ignore
466    this.eventTypeData.shift(this.typeStatisticsData);
467    this.typeUsageTbl?.reMeauseHeight();
468    this.currentLevelData = this.eventTypeData;
469  }
470
471  private threadPieChart(): void {
472    this.nmPieChart!.config = {
473      appendPadding: 0,
474      data: this.getPieChartData(this.threadData),
475      angleField: 'existSize',
476      colorField: 'tableName',
477      radius: 1,
478      label: {
479        type: 'outer',
480      },
481      tip: (threadTipValue): string => {
482        // @ts-ignore
483        const obj = threadTipValue.obj as AnalysisObj;
484        return `<div>
485                    <div>Thread:${obj.tableName}</div>
486                    <div>Existing:${obj.existSizeFormat} (${obj.existSizePercent}%)</div>
487                    <div># Existing:${obj.existCount} (${obj.existCountPercent}%)</div>
488                    <div>Total Bytes:${obj.applySizeFormat} (${obj.applySizePercent}%)</div>
489                    <div># Total:${obj.applyCount} (${obj.applyCountPercent}%)</div>
490                    <div>Transient:${obj.releaseSizeFormat} (${obj.releaseSizePercent}%)</div>
491                    <div># Transient:${obj.releaseCount} (${obj.releaseCountPercent}%)</div>
492                </div>`;
493      },
494      angleClick: (it: unknown): void => {
495        // @ts-ignore
496        if (it.tid !== 'other') {
497          // @ts-ignore
498          this.nativeThreadLevelClickEvent(it);
499        }
500      },
501      hoverHandler: (data): void => {
502        if (data) {
503          this.threadUsageTbl!.setCurrentHover(data);
504        } else {
505          this.threadUsageTbl!.mouseOut();
506        }
507      },
508      interactions: [
509        {
510          type: 'element-active',
511        },
512      ],
513    };
514    const typeName = this.type === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : this.type;
515    this.titleEl!.textContent = typeName + '';
516    this.tabName!.textContent = 'Statistic By Thread Existing';
517    // @ts-ignore
518    this.threadData.unshift(this.threadStatisticsData);
519    this.threadUsageTbl!.recycleDataSource = this.threadData;
520    // @ts-ignore
521    this.threadData.shift(this.threadStatisticsData);
522    this.currentLevelData = this.threadData;
523    this.threadUsageTbl?.reMeauseHeight();
524  }
525
526  private getLibraryTipValue(libraryTipValue: unknown): string {
527    // @ts-ignore
528    const obj = libraryTipValue.obj as AnalysisObj;
529    return `<div>
530                    <div>Library:${obj.libName}</div>
531                    <div>Existing:${obj.existSizeFormat}
532                    (${obj.existSizePercent}%)</div>
533                    <div># Existing:${obj.existCount}
534                    (${obj.existCountPercent}%)</div>
535                    <div>Total Bytes:${obj.applySizeFormat}
536                    (${obj.applySizePercent}%)</div>
537                    <div># Total:${obj.applyCount}
538                    (${obj.applyCountPercent}%)</div>
539                    <div>Transient:${obj.releaseSizeFormat}
540                    (${obj.releaseSizePercent}%)</div>
541                    <div># Transient:${obj.releaseCount}
542                    (${obj.releaseCountPercent}%)</div>
543                </div>`;
544  }
545
546  private libraryPieChart(item?: unknown): void {
547    this.nmPieChart!.config = {
548      appendPadding: 0,
549      data: this.getPieChartData(this.soData),
550      angleField: 'existSize',
551      colorField: 'tableName',
552      radius: 1,
553      label: {
554        type: 'outer',
555      },
556      tip: (libraryTipValue): string => {
557        return this.getLibraryTipValue(libraryTipValue);
558      },
559      angleClick: (it): void => {
560        // @ts-ignore
561        if (it.tableName !== 'other') {
562          this.nativeSoLevelClickEvent(it);
563        }
564      },
565      hoverHandler: (data): void => {
566        if (data) {
567          this.soUsageTbl!.setCurrentHover(data);
568        } else {
569          this.soUsageTbl!.mouseOut();
570        }
571      },
572      interactions: [
573        {
574          type: 'element-active',
575        },
576      ],
577    };
578    const typeName = this.type === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : this.type;
579    let title = typeName;
580    if (!this.hideThreadCheckBox?.checked && this.threadName.length > 0) {
581      title += ' / ' + this.threadName;
582    }
583    this.titleEl!.textContent = title;
584    this.tabName!.textContent = 'Statistic By Library Existing';
585    // @ts-ignore
586    this.soData.unshift(this.libStatisticsData);
587    this.soUsageTbl!.recycleDataSource = this.soData;
588    // @ts-ignore
589    this.soData.shift(this.libStatisticsData);
590    this.currentLevelData = this.soData;
591    this.soUsageTbl?.reMeauseHeight();
592  }
593
594  private functionPieChart(): void {
595    this.nmPieChart!.config = {
596      appendPadding: 0,
597      data: this.getPieChartData(this.functionData),
598      angleField: 'existSize',
599      colorField: 'tableName',
600      radius: 1,
601      label: {
602        type: 'outer',
603      },
604      tip: (functionTipValue): string => {
605        // @ts-ignore
606        const obj = functionTipValue.obj as AnalysisObj;
607        return `<div>
608                    <div>Function:${obj.symbolName}</div>
609                    <div>Existing:${obj.existSizeFormat}
610                    (${obj.existSizePercent}%)</div>
611                    <div># Existing:${obj.existCount}
612                    (${obj.existCountPercent}%)</div>
613                    <div>Total Bytes:${obj.applySizeFormat}
614                    (${obj.applySizePercent}%)</div>
615                    <div># Total:${obj.applyCount}
616                    (${obj.applyCountPercent}%)</div>
617                    <div>Transient:${obj.releaseSizeFormat}
618                    (${obj.releaseSizePercent}%)</div>
619                    <div># Transient:${obj.releaseCount}
620                    (${obj.releaseCountPercent}%)</div>
621                </div>`;
622      },
623      hoverHandler: (data): void => {
624        if (data) {
625          this.functionUsageTbl!.setCurrentHover(data);
626        } else {
627          this.functionUsageTbl!.mouseOut();
628        }
629      },
630      interactions: [
631        {
632          type: 'element-active',
633        },
634      ],
635    };
636    // @ts-ignore
637    this.functionData.unshift(this.functionStatisticsData);
638    this.functionUsageTbl!.recycleDataSource = this.functionData;
639    // @ts-ignore
640    this.functionData.shift(this.functionStatisticsData);
641    this.currentLevelData = this.functionData;
642    this.functionUsageTbl?.reMeauseHeight();
643  }
644
645  private nativeProcessLevelClickEvent(it: unknown): void {
646    if (this.hideThreadCheckBox?.checked || this.isStatistic) {
647      this.reset(this.soUsageTbl!, true);
648      this.showAssignLevel(this.soUsageTbl!, this.typeUsageTbl!, 1, this.eventTypeData);
649      this.getNMLibSize(it);
650    } else {
651      this.reset(this.threadUsageTbl!, true);
652      this.showAssignLevel(this.threadUsageTbl!, this.typeUsageTbl!, 1, this.eventTypeData);
653      this.getNMThreadSize(it);
654    } // @ts-ignore
655    const typeName = it.typeName === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : it.typeName;
656    this.titleEl!.textContent = typeName;
657    // @ts-ignore
658    this.type = it.typeName;
659    this.nmPieChart?.hideTip();
660  }
661
662  private nativeThreadLevelClickEvent(it: AnalysisObj): void {
663    this.reset(this.soUsageTbl!, true);
664    this.showAssignLevel(this.soUsageTbl!, this.threadUsageTbl!, 2, this.eventTypeData);
665    this.getNMLibSize(it);
666    const typeName = this.type === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : this.type;
667
668    // @ts-ignore
669    let title = typeName;
670    if (!this.hideThreadCheckBox?.checked) {
671      this.threadName = `${it.tableName}`;
672      title += ` / ${this.threadName}`;
673    }
674    this.titleEl!.textContent = title;
675    this.nmPieChart?.hideTip();
676  }
677
678  private nativeSoLevelClickEvent(it: unknown): void {
679    this.reset(this.functionUsageTbl!, true);
680    this.showAssignLevel(this.functionUsageTbl!, this.soUsageTbl!, 3, this.eventTypeData);
681    this.getNMFunctionSize(it);
682    const typeName = this.type === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : this.type;
683    // @ts-ignore
684    let title = typeName || '';
685    if (!this.hideThreadCheckBox?.checked && this.threadName.length > 0) {
686      title += ` / ${this.threadName}`;
687    } // @ts-ignore
688    if (it.libName.length > 0) {
689      // @ts-ignore
690      title += ` / ${it.libName}`;
691    }
692    this.titleEl!.textContent = title;
693    this.nmPieChart?.hideTip();
694  }
695
696  private getNMEventTypeSize(val: SelectionParam): void {
697    this.progressEL!.loading = true;
698    let typeFilter = [];
699    if (this.isStatistic) {
700      for (let type of val.nativeMemoryStatistic) {
701        if (type === 'All Heap & Anonymous VM') {
702          typeFilter = [0, 1];
703          break;
704        } else if (type === 'All Heap') {
705          typeFilter.push(0);
706        } else {
707          typeFilter.push(1);
708        }
709      }
710      this.getDataFromWorker(val, typeFilter);
711    } else {
712      for (let type of val.nativeMemory) {
713        if (type === 'All Heap & Anonymous VM') {
714          typeFilter = [];
715          typeFilter.push(...["'AllocEvent'", "'FreeEvent'", "'MmapEvent'", "'MunmapEvent'"]);
716          break;
717        } else if (type === 'All Heap') {
718          typeFilter.push(...["'AllocEvent'", "'FreeEvent'"]);
719        } else {
720          typeFilter.push(...["'MmapEvent'", "'MunmapEvent'"]);
721        }
722      }
723      this.getDataFromWorker(val, typeFilter);
724    }
725  }
726
727  private getNMTypeSize(val: SelectionParam, result: unknown): void {
728    this.resetCurrentLevelData(); // @ts-ignore
729    this.typeMap = this.typeSizeGroup(this.processData);
730    this.currentLevelExistSize = this.currentLevelApplySize - this.currentLevelReleaseSize;
731    this.currentLevelExistCount = this.currentLevelApplyCount - this.currentLevelReleaseCount;
732    this.eventTypeData = [];
733    if (this.typeMap.has(TYPE_ALLOC)) {
734      let allocType = this.setTypeMap(this.typeMap, TYPE_ALLOC, TYPE_ALLOC_STRING);
735      if (allocType) {
736        this.calPercent(allocType);
737        this.eventTypeData.push(allocType);
738      }
739    }
740    if (this.typeMap.has(TYPE_MAP)) {
741      let subTypeMap = new Map<string, Array<number | string>>();
742      for (let item of this.typeMap.get(TYPE_MAP)!) {
743        // @ts-ignore
744        if (item.subType) {
745          // @ts-ignore
746          if (subTypeMap.has(item.subType)) {
747            // @ts-ignore
748            subTypeMap.get(item.subType)?.push(item);
749          } else {
750            let dataArray: Array<number | string> = []; // @ts-ignore
751            dataArray.push(item); // @ts-ignore
752            subTypeMap.set(item.subType, dataArray);
753          }
754        } else {
755          if (subTypeMap.has(TYPE_MAP_STRING)) {
756            // @ts-ignore
757            subTypeMap.get(TYPE_MAP_STRING)?.push(item);
758          } else {
759            let dataArray: Array<number | string> = []; // @ts-ignore
760            dataArray.push(item);
761            subTypeMap.set(TYPE_MAP_STRING, dataArray);
762          }
763        }
764      }
765      subTypeMap.forEach((arr: Array<number | string>, subType: string) => {
766        let mapType = this.setTypeMap(this.typeMap, TYPE_MAP, subType);
767        if (mapType) {
768          this.calPercent(mapType);
769          this.eventTypeData.push(mapType);
770        }
771      });
772    }
773    this.eventTypeData.sort((a, b) => b.existSize - a.existSize);
774    this.typeStatisticsData = this.totalData(this.typeStatisticsData);
775    this.progressEL!.loading = false;
776    this.currentLevel = 0;
777    this.typePieChart();
778  }
779
780  private getNMThreadSize(item: unknown): void {
781    this.progressEL!.loading = true;
782    let threadMap = new Map<number, Array<number | string>>(); // @ts-ignore
783    let types = this.getTypes(item); // @ts-ignore
784    let typeName = item.typeName;
785    this.resetCurrentLevelData(item);
786    for (let itemData of this.processData) {
787      // @ts-ignore
788      if (this.shouldSkipItem(typeName, types, itemData)) {
789        continue;
790      } // @ts-ignore
791      if (threadMap.has(itemData.tid)) {
792        // @ts-ignore
793        threadMap.get(itemData.tid)?.push(itemData);
794      } else {
795        let itemArray: Array<number | string> = []; // @ts-ignore
796        itemArray.push(itemData); // @ts-ignore
797        threadMap.set(itemData.tid, itemArray);
798      }
799    }
800    this.threadData = [];
801    threadMap.forEach((dbData: Array<unknown>, tid: number) => {
802      const sizeObj = this.calSizeObj(dbData);
803      let analysis = new AnalysisObj(sizeObj.applySize, sizeObj.applyCount, sizeObj.releaseSize, sizeObj.releaseCount);
804      this.calPercent(analysis); // @ts-ignore
805      analysis.typeId = item.typeId; // @ts-ignore
806      analysis.typeName = item.typeName;
807      analysis.tid = tid; // @ts-ignore
808      if (dbData[0].threadName && dbData[0].threadName.length > 0) {
809        // @ts-ignore
810        analysis.tName = `${dbData[0].threadName}(${tid})`;
811      } else {
812        analysis.tName = `Thread ${tid}`;
813      }
814      analysis.tableName = analysis.tName;
815      this.threadData.push(analysis);
816    });
817    this.threadData.sort((a, b) => b.existSize - a.existSize);
818    this.threadStatisticsData = this.totalData(this.threadStatisticsData);
819    this.currentLevel = 1;
820    this.currentLevelData = this.threadData;
821    this.progressEL!.loading = false;
822    this.threadPieChart();
823  }
824
825  private shouldSkipItem(typeName: string, types: Array<number | string>, itemData: unknown): boolean {
826    if (typeName === TYPE_ALLOC_STRING) {
827      // @ts-ignore
828      return !types.includes(itemData.type);
829    } else if (typeName === TYPE_MAP_STRING) {
830      if (this.isStatistic) {
831        // @ts-ignore
832        if (itemData.subType) {
833          // @ts-ignore
834          return !types.includes(itemData.subType) || !types.includes(itemData.type);
835        } else {
836          return true;
837        }
838      } else {
839        // @ts-ignore
840        if (!itemData.subType) {
841          // @ts-ignore
842          return !types.includes(itemData.type);
843        } else {
844          return true;
845        }
846      }
847    } else {
848      // @ts-ignore
849      if (itemData.subType) {
850        // @ts-ignore
851        return !types.includes(itemData.subType) || !types.includes(itemData.type);
852      } else {
853        return true;
854      }
855    }
856  }
857
858  private getNMLibSize(item: unknown): void {
859    this.progressEL!.loading = true; // @ts-ignore
860    let typeId = item.typeId; // @ts-ignore
861    let typeName = item.typeName; // @ts-ignore
862    let tid = item.tid;
863    let libMap = new Map<number, Array<number | string>>();
864    this.resetCurrentLevelData(item); // @ts-ignore
865    let types = this.getTypes(item);
866    this.soData = [];
867    if (!this.processData) {
868      return;
869    }
870    for (let itemData of this.processData) {
871      if (this.shouldSkipItem(typeName, types, itemData)) {
872        continue;
873      } // @ts-ignore
874      if (tid !== undefined && tid !== itemData.tid) {
875        continue;
876      } // @ts-ignore
877      let libId = itemData.libId;
878      if (libMap.has(libId)) {
879        // @ts-ignore
880        libMap.get(libId)?.push(itemData);
881      } else {
882        let dataArray: Array<number | string> = []; // @ts-ignore
883        dataArray.push(itemData);
884        libMap.set(libId, dataArray);
885      }
886    }
887    this.soData = [];
888    libMap.forEach((libItems, libId) => {
889      let libPath = SpSystemTrace.DATA_DICT.get(libId)?.split('/');
890      let libName = '';
891      if (libPath) {
892        libName = libPath[libPath.length - 1];
893      }
894      const sizeObj = this.calSizeObj(libItems);
895      let analysis = new AnalysisObj(sizeObj.applySize, sizeObj.applyCount, sizeObj.releaseSize, sizeObj.releaseCount);
896      this.calPercent(analysis);
897      analysis.typeId = typeId;
898      analysis.typeName = typeName;
899      analysis.tid = tid;
900      analysis.tName = 'Thread ' + tid;
901      analysis.libId = libId;
902      analysis.libName = libName;
903      analysis.tableName = analysis.libName;
904      this.soData.push(analysis);
905    });
906    this.baseSort(this.soData);
907    this.libraryPieChart(item);
908  }
909
910  private getNMFunctionSize(item: unknown): void {
911    this.progressEL!.loading = true;
912    this.shadowRoot!.querySelector<HTMLDivElement>('.nm-subheading')!.textContent = 'Statistic By Function Existing';
913    // @ts-ignore
914    let typeId = item.typeId; // @ts-ignore
915    let typeName = item.typeName; // @ts-ignore
916    let tid = item.tid; // @ts-ignore
917    let libId = item.libId; // @ts-ignore
918    let symbolMap = new Map<number, Array<number | string>>();
919    this.resetCurrentLevelData(item); // @ts-ignore
920    let types = this.getTypes(item);
921    if (!this.processData) {
922      return;
923    }
924    for (let data of this.processData) {
925      if (this.skipItemByType(typeName, types, data, libId)) {
926        continue;
927      } // @ts-ignore
928      if (tid !== undefined && tid !== data.tid) {
929        continue;
930      } // @ts-ignore
931      if (symbolMap.has(data.symbolId)) {
932        // @ts-ignore
933        symbolMap.get(data.symbolId)?.push(data);
934      } else {
935        let dataArray: Array<number | string> = []; // @ts-ignore
936        dataArray.push(data); // @ts-ignore
937        symbolMap.set(data.symbolId, dataArray);
938      }
939    }
940    this.functionData = [];
941    symbolMap.forEach((symbolItems, symbolId) => {
942      let symbolPath = SpSystemTrace.DATA_DICT.get(symbolId)?.split('/');
943      let symbolName = symbolPath ? symbolPath[symbolPath.length - 1] : 'null';
944      const sizeObj = this.calSizeObj(symbolItems);
945      let analysis = new AnalysisObj(sizeObj.applySize, sizeObj.applyCount, sizeObj.releaseSize, sizeObj.releaseCount);
946      this.calPercent(analysis);
947      analysis.typeId = typeId;
948      analysis.typeName = typeName;
949      analysis.tid = tid;
950      analysis.tName = 'Thread ' + tid;
951      analysis.libId = libId; // @ts-ignore
952      analysis.libName = item.libName;
953      analysis.symbolId = symbolId;
954      analysis.symbolName = symbolName;
955      analysis.tableName = analysis.symbolName;
956      this.functionData.push(analysis);
957    });
958    this.baseSort(this.functionData);
959    this.functionPieChart();
960  }
961
962  private skipItemByType(typeName: string, types: Array<string | number>, data: unknown, libId: number): boolean {
963    if (typeName === TYPE_ALLOC_STRING) {
964      // @ts-ignore
965      if (!types.includes(data.type) || data.libId !== libId) {
966        return true;
967      }
968    } else if (typeName === TYPE_MAP_STRING) {
969      if (this.isStatistic) {
970        // @ts-ignore
971        if (data.subType) {
972          // @ts-ignore
973          if (!types.includes(data.subType) || !types.includes(data.type) || data.libId !== libId) {
974            return true;
975          }
976        } else {
977          return true;
978        }
979      } else {
980        // @ts-ignore
981        if (!data.subType) {
982          // @ts-ignore
983          if (!types.includes(data.type) || data.libId !== libId) {
984            return true;
985          }
986        } else {
987          return true;
988        }
989      }
990    } else {
991      // @ts-ignore
992      if (data.subType) {
993        // @ts-ignore
994        if (!types.includes(data.subType) || !types.includes(data.type) || data.libId !== libId) {
995          return true;
996        }
997      } else {
998        return true;
999      }
1000    }
1001    return false;
1002  }
1003  private baseSort(data: Array<AnalysisObj>): void {
1004    if (data === this.functionData) {
1005      this.functionData.sort((a, b) => b.existSize - a.existSize);
1006      // @ts-ignore
1007      this.functionStatisticsData = this.totalData(this.functionStatisticsData);
1008      this.currentLevel = 3;
1009      this.progressEL!.loading = false;
1010    }
1011    if (data === this.soData) {
1012      this.soData.sort((a, b) => b.existSize - a.existSize);
1013      this.libStatisticsData = this.totalData(this.libStatisticsData);
1014      this.currentLevel = 2;
1015      this.progressEL!.loading = false;
1016    }
1017  }
1018
1019  private getPieChartData(res: unknown[]): unknown[] {
1020    if (res.length > PIE_CHART_LIMIT) {
1021      let pieChartArr: string[] = [];
1022      let other: unknown = {
1023        tableName: 'other',
1024        tName: 'other',
1025        libName: 'other',
1026        symbolName: 'other',
1027        existSizePercent: 0,
1028        existSize: 0,
1029        existSizeFormat: '',
1030        existCount: 0,
1031        existCountPercent: 0,
1032        applySizeFormat: '',
1033        applySize: 0,
1034        applySizePercent: 0,
1035        applyCount: 0,
1036        applyCountPercent: 0,
1037        releaseSizeFormat: '',
1038        releaseSize: 0,
1039        releaseSizePercent: 0,
1040        releaseCount: 0,
1041        releaseCountPercent: 0,
1042      };
1043      for (let i = 0; i < res.length; i++) {
1044        if (i < PIE_CHART_LIMIT - 1) {
1045          // @ts-ignore
1046          pieChartArr.push(res[i]);
1047        } else {
1048          // @ts-ignore
1049          other.existCount += res[i].existCount; // @ts-ignore
1050          other.existSize += res[i].existSize; // @ts-ignore
1051          other.applySize += res[i].applySize; // @ts-ignore
1052          other.applyCount += res[i].applyCount; // @ts-ignore
1053          other.releaseSize += res[i].releaseSize; // @ts-ignore
1054          other.releaseCount += res[i].releaseCount; // @ts-ignore
1055          other.existSizeFormat = Utils.getBinaryByteWithUnit(other.existSize); // @ts-ignore
1056          other.applySizeFormat = Utils.getBinaryByteWithUnit(other.applySize); // @ts-ignore
1057          other.releaseSizeFormat = Utils.getBinaryByteWithUnit(other.releaseSize); // @ts-ignore
1058          other.existSizePercent = this.currentLevelExistSize === 0 ? 0 : ((other.existSize / this.currentLevelExistSize) * 100).toFixed(2); // @ts-ignore
1059          other.existCountPercent = this.currentLevelExistCount === 0 ? 0 : ((other.existCount / this.currentLevelExistCount) * 100).toFixed(2); // @ts-ignore
1060          other.applySizePercent = this.currentLevelApplySize === 0 ? 0 : ((other.applySize / this.currentLevelApplySize) * 100).toFixed(2); // @ts-ignore
1061          other.applyCountPercent = this.currentLevelApplyCount === 0 ? 0 : ((other.applyCount / this.currentLevelApplyCount) * 100).toFixed(2);
1062          // @ts-ignore
1063          other.releaseSizePercent = this.currentLevelReleaseSize === 0 ? 0 :
1064            // @ts-ignore
1065            ((other.releaseSize / this.currentLevelReleaseSize) * 100).toFixed(2); // @ts-ignore
1066          other.releaseCountPercent = this.currentLevelReleaseCount === 0 ? 0 : ((other.releaseCount / this.currentLevelReleaseCount) * 100).toFixed(2);
1067        }
1068      } // @ts-ignore
1069      pieChartArr.push(other);
1070      return pieChartArr;
1071    }
1072    return res;
1073  }
1074
1075  private setTypeMap(typeMap: Map<number, unknown>, tyeId: number, typeName: string): AnalysisObj | null {
1076    let applySize = 0;
1077    let releaseSize = 0;
1078    let applyCount = 0;
1079    let releaseCount = 0;
1080    let currentType = typeMap.get(tyeId);
1081    if (!currentType) {
1082      return null;
1083    }
1084
1085    // @ts-ignore
1086    for (let applySample of typeMap.get(tyeId)!) {
1087      if (
1088        tyeId === TYPE_ALLOC ||
1089        (applySample.subType && applySample.subType === typeName) ||
1090        (!applySample.subType && typeName === TYPE_MAP_STRING)
1091      ) {
1092        applySize += applySample.size;
1093        applyCount += applySample.count;
1094        if (this.isStatistic) {
1095          releaseSize += applySample.releaseSize;
1096          releaseCount += applySample.releaseCount;
1097        } else {
1098          if (applySample.isRelease) {
1099            releaseSize += applySample.size;
1100            releaseCount += applySample.count;
1101          }
1102        }
1103      }
1104    }
1105    let typeItem = new AnalysisObj(applySize, applyCount, releaseSize, releaseCount);
1106    typeItem.typeId = tyeId;
1107    typeItem.typeName = typeName;
1108    typeItem.tableName = typeName === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : typeName;
1109    return typeItem;
1110  }
1111
1112  private calPercent(item: AnalysisObj): void {
1113    item.applySizePercent = this.currentLevelApplySize === 0 ? '0' : ((item.applySize / this.currentLevelApplySize) * 100).toFixed(2);
1114    item.applyCountPercent = this.currentLevelApplyCount === 0 ? '0' : ((item.applyCount / this.currentLevelApplyCount) * 100).toFixed(2);
1115    item.releaseSizePercent = this.currentLevelReleaseSize === 0 ? '0' : ((item.releaseSize / this.currentLevelReleaseSize) * 100).toFixed(2);
1116    item.releaseCountPercent = this.currentLevelReleaseCount === 0 ? '0' : ((item.releaseCount / this.currentLevelReleaseCount) * 100).toFixed(2);
1117    item.existSizePercent = this.currentLevelExistSize === 0 ? '0' : ((item.existSize / this.currentLevelExistSize) * 100).toFixed(2);
1118    item.existCountPercent = this.currentLevelExistCount === 0 ? '0' : ((item.existCount / this.currentLevelExistCount) * 100).toFixed(2);
1119  }
1120
1121  private resetCurrentLevelData(parent?: unknown): void {
1122    if (parent) {
1123      // @ts-ignore
1124      this.currentLevelApplySize = parent.applySize; // @ts-ignore
1125      this.currentLevelApplyCount = parent.applyCount; // @ts-ignore
1126      this.currentLevelExistSize = parent.existSize; // @ts-ignore
1127      this.currentLevelExistCount = parent.existCount; // @ts-ignore
1128      this.currentLevelReleaseSize = parent.releaseSize; // @ts-ignore
1129      this.currentLevelReleaseCount = parent.releaseCount;
1130    } else {
1131      this.currentLevelApplySize = 0;
1132      this.currentLevelApplyCount = 0;
1133      this.currentLevelExistSize = 0;
1134      this.currentLevelExistCount = 0;
1135      this.currentLevelReleaseSize = 0;
1136      this.currentLevelReleaseCount = 0;
1137    }
1138  }
1139
1140  private typeSizeGroup(dbArray: Array<number | string>): Map<number, Array<number | string>> {
1141    let typeMap = new Map<number, Array<number | string>>();
1142    if (!dbArray || dbArray.length === 0) {
1143      return typeMap;
1144    }
1145
1146    const setSize = (item: unknown): void => {
1147      // @ts-ignore
1148      this.currentLevelApplySize += item.size; // @ts-ignore
1149      this.currentLevelApplyCount += item.count;
1150      if (this.isStatistic) {
1151        // @ts-ignore
1152        this.currentLevelReleaseSize += item.releaseSize; // @ts-ignore
1153        this.currentLevelReleaseCount += item.releaseCount;
1154      } else {
1155        // @ts-ignore
1156        if (item.isRelease) {
1157          // @ts-ignore
1158          this.currentLevelReleaseSize += item.size; // @ts-ignore
1159          this.currentLevelReleaseCount += item.count;
1160        }
1161      }
1162    };
1163
1164    for (let itemData of dbArray) {
1165      // @ts-ignore
1166      switch (itemData.type) {
1167        case TYPE_ALLOC:
1168          setSize(itemData);
1169          if (typeMap.has(TYPE_ALLOC)) {
1170            typeMap.get(TYPE_ALLOC)?.push(itemData);
1171          } else {
1172            let itemArray: Array<number | string> = [];
1173            itemArray.push(itemData);
1174            typeMap.set(TYPE_ALLOC, itemArray);
1175          }
1176          break;
1177        case TYPE_MAP:
1178          setSize(itemData);
1179          if (typeMap.has(TYPE_MAP)) {
1180            typeMap.get(TYPE_MAP)?.push(itemData);
1181          } else {
1182            let itemArray: Array<number | string> = [];
1183            itemArray.push(itemData);
1184            typeMap.set(TYPE_MAP, itemArray);
1185          }
1186          break;
1187      }
1188    }
1189    return typeMap;
1190  }
1191
1192  private calSizeObj(dbData: Array<unknown>): SizeObj {
1193    let sizeObj = new SizeObj();
1194    for (let item of dbData) {
1195      if (this.isStatistic) {
1196        // @ts-ignore
1197        sizeObj.applyCount += item.count; // @ts-ignore
1198        sizeObj.applySize += item.size; // @ts-ignore
1199        sizeObj.releaseCount += item.releaseCount; // @ts-ignore
1200        sizeObj.releaseSize += item.releaseSize;
1201      } else {
1202        // @ts-ignore
1203        sizeObj.applyCount += item.count; // @ts-ignore
1204        sizeObj.applySize += item.size; // @ts-ignore
1205        if (item.isRelease) {
1206          // @ts-ignore
1207          sizeObj.releaseCount += item.count; // @ts-ignore
1208          sizeObj.releaseSize += item.size;
1209        }
1210      }
1211    }
1212    return sizeObj;
1213  }
1214
1215  private getTypes(parent: AnalysisObj): Array<number | string> {
1216    let types: Array<number | string> = [];
1217    types.push(parent.typeId!);
1218    types.push(parent.typeName!);
1219    if (!this.isStatistic) {
1220      let releaseType;
1221      if (parent.typeId === TYPE_ALLOC) {
1222        releaseType = TYPE_FREE;
1223      } else {
1224        releaseType = TYPE_UN_MAP;
1225      }
1226      types.push(releaseType);
1227    }
1228    return types;
1229  }
1230
1231  private totalData(total: {}): {} {
1232    total = {
1233      existSizeFormat: Utils.getBinaryByteWithUnit(this.currentLevelExistSize),
1234      existSizePercent: this.currentLevelExistSize === 0 ? 0 : ((this.currentLevelExistSize / this.currentLevelExistSize) * 100).toFixed(2),
1235      existCount: this.currentLevelExistCount,
1236      existCountPercent: this.currentLevelExistCount === 0 ? 0 : ((this.currentLevelExistCount / this.currentLevelExistCount) * 100).toFixed(2),
1237      releaseSizeFormat: Utils.getBinaryByteWithUnit(this.currentLevelReleaseSize),
1238      releaseSizePercent: this.currentLevelReleaseSize === 0 ? 0 : ((this.currentLevelReleaseSize / this.currentLevelReleaseSize) * 100).toFixed(2),
1239      releaseCount: this.currentLevelReleaseCount,
1240      releaseCountPercent: this.currentLevelReleaseCount === 0 ? 0 : ((this.currentLevelReleaseCount / this.currentLevelReleaseCount) * 100).toFixed(2),
1241      applySizeFormat: Utils.getBinaryByteWithUnit(this.currentLevelApplySize),
1242      applySizePercent: this.currentLevelApplySize === 0 ? 0 : ((this.currentLevelApplySize / this.currentLevelApplySize) * 100).toFixed(2),
1243      applyCount: this.currentLevelApplyCount,
1244      applyCountPercent: this.currentLevelApplyCount === 0 ? 0 : ((this.currentLevelApplyCount / this.currentLevelApplyCount) * 100).toFixed(2),
1245      existSize: 0,
1246      tableName: '',
1247      tName: '',
1248      libName: '',
1249      symbolName: '',
1250    };
1251    return total;
1252  }
1253
1254  private getNmCurrentTable(): LitTable | null | undefined {
1255    let nmCurrentTable: LitTable | null | undefined;
1256    switch (this.currentLevel) {
1257      case 0:
1258        nmCurrentTable = this.typeUsageTbl;
1259        break;
1260      case 1:
1261        nmCurrentTable = this.threadUsageTbl;
1262        break;
1263      case 2:
1264        nmCurrentTable = this.soUsageTbl;
1265        break;
1266      case 3:
1267        nmCurrentTable = this.functionUsageTbl;
1268        break;
1269    }
1270    return nmCurrentTable;
1271  }
1272
1273  private getSortedColumnZeroArr(data: unknown[]): unknown[] {
1274    let sortColumnZeroArr = [...data];
1275    switch (this.currentLevel) {
1276      case 0:
1277        sortColumnZeroArr.unshift(this.typeStatisticsData);
1278        break;
1279      case 1:
1280        sortColumnZeroArr.unshift(this.threadStatisticsData);
1281        break;
1282      case 2:
1283        sortColumnZeroArr.unshift(this.libStatisticsData);
1284        break;
1285      case 3:
1286        sortColumnZeroArr.unshift(this.functionStatisticsData);
1287        break;
1288    }
1289    return sortColumnZeroArr;
1290  }
1291
1292  private updateSortColumnArr(sortColumnArr: unknown[]): unknown[] {
1293    switch (this.currentLevel) {
1294      case 0:
1295        sortColumnArr.unshift(this.typeStatisticsData);
1296        break;
1297      case 1:
1298        sortColumnArr.unshift(this.threadStatisticsData);
1299        break;
1300      case 2:
1301        sortColumnArr.unshift(this.libStatisticsData);
1302        break;
1303      case 3:
1304        sortColumnArr.unshift(this.functionStatisticsData);
1305        break;
1306    }
1307    return sortColumnArr;
1308  }
1309
1310  private caseTableName(
1311    statisticAnalysisLeftData: { tableName: number },
1312    statisticAnalysisRightData: { tableName: number }
1313  ): number {
1314    if (this.nmSortType === 1) {
1315      if (statisticAnalysisLeftData.tableName > statisticAnalysisRightData.tableName) {
1316        return 1;
1317      } else if (statisticAnalysisLeftData.tableName === statisticAnalysisRightData.tableName) {
1318        return 0;
1319      } else {
1320        return -1;
1321      }
1322    } else {
1323      if (statisticAnalysisRightData.tableName > statisticAnalysisLeftData.tableName) {
1324        return 1;
1325      } else if (statisticAnalysisLeftData.tableName === statisticAnalysisRightData.tableName) {
1326        return 0;
1327      } else {
1328        return -1;
1329      }
1330    }
1331  }
1332
1333  private sortDataByExistSize(sortType: number, sortColumnArr: Array<unknown>): unknown[] {
1334    return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => {
1335      return sortType === 1 // @ts-ignore
1336        ? statisticAnalysisLeftData.existSize - statisticAnalysisRightData.existSize // @ts-ignore
1337        : statisticAnalysisRightData.existSize - statisticAnalysisLeftData.existSize;
1338    });
1339  }
1340
1341  private sortDataByExistCount(sortType: number, sortColumnArr: Array<unknown>): unknown[] {
1342    return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => {
1343      return sortType === 1 // @ts-ignore
1344        ? statisticAnalysisLeftData.existCount - statisticAnalysisRightData.existCount // @ts-ignore
1345        : statisticAnalysisRightData.existCount - statisticAnalysisLeftData.existCount;
1346    });
1347  }
1348
1349  private sortDataByReleaseSize(sortType: number, sortColumnArr: Array<unknown>): unknown[] {
1350    return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => {
1351      return sortType === 1 // @ts-ignore
1352        ? statisticAnalysisLeftData.releaseSize - statisticAnalysisRightData.releaseSize // @ts-ignore
1353        : statisticAnalysisRightData.releaseSize - statisticAnalysisLeftData.releaseSize;
1354    });
1355  }
1356
1357  private sortDataByReleaseCount(sortType: number, sortColumnArr: Array<unknown>): unknown[] {
1358    return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => {
1359      return sortType === 1 // @ts-ignore
1360        ? statisticAnalysisLeftData.releaseCount - statisticAnalysisRightData.releaseCount // @ts-ignore
1361        : statisticAnalysisRightData.releaseCount - statisticAnalysisLeftData.releaseCount;
1362    });
1363  }
1364
1365  private sortDataByApplySize(sortType: number, sortColumnArr: Array<unknown>): unknown[] {
1366    return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => {
1367      return sortType === 1 // @ts-ignore
1368        ? statisticAnalysisLeftData.applySize - statisticAnalysisRightData.applySize // @ts-ignore
1369        : statisticAnalysisRightData.applySize - statisticAnalysisLeftData.applySize;
1370    });
1371  }
1372
1373  private sortDataByApplyCount(sortType: number, sortColumnArr: Array<unknown>): unknown[] {
1374    return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => {
1375      return sortType === 1 // @ts-ignore
1376        ? statisticAnalysisLeftData.applyCount - statisticAnalysisRightData.applyCount // @ts-ignore
1377        : statisticAnalysisRightData.applyCount - statisticAnalysisLeftData.applyCount;
1378    });
1379  }
1380
1381  private sortByColumn(): void {
1382    let nmCurrentTable = this.getNmCurrentTable();
1383    if (!nmCurrentTable) {
1384      return;
1385    }
1386    if (this.nmSortType === 0) {
1387      nmCurrentTable!.recycleDataSource = this.getSortedColumnZeroArr(this.currentLevelData);
1388    } else {
1389      let sortColumnArr = [...this.currentLevelData];
1390      switch (this.nmSortColumn) {
1391        case 'tableName':
1392          // @ts-ignore
1393          nmCurrentTable!.recycleDataSource = sortColumnArr.sort(this.caseTableName);
1394          break;
1395        case 'existSizeFormat':
1396        case 'existSizePercent':
1397          nmCurrentTable!.recycleDataSource = this.sortDataByExistSize(this.nmSortType, sortColumnArr);
1398          break;
1399        case 'existCount':
1400        case 'existCountPercent':
1401          nmCurrentTable!.recycleDataSource = this.sortDataByExistCount(this.nmSortType, sortColumnArr);
1402          break;
1403        case 'releaseSizeFormat':
1404        case 'releaseSizePercent':
1405          nmCurrentTable!.recycleDataSource = this.sortDataByReleaseSize(this.nmSortType, sortColumnArr);
1406          break;
1407        case 'releaseCount':
1408        case 'releaseCountPercent':
1409          nmCurrentTable!.recycleDataSource = this.sortDataByReleaseCount(this.nmSortType, sortColumnArr);
1410          break;
1411        case 'applySizeFormat':
1412        case 'applySizePercent':
1413          nmCurrentTable!.recycleDataSource = this.sortDataByApplySize(this.nmSortType, sortColumnArr);
1414          break;
1415        case 'applyCount':
1416        case 'applyCountPercent':
1417          nmCurrentTable!.recycleDataSource = this.sortDataByApplyCount(this.nmSortType, sortColumnArr);
1418          break;
1419      }
1420      sortColumnArr = this.updateSortColumnArr(sortColumnArr);
1421      nmCurrentTable!.recycleDataSource = sortColumnArr;
1422    }
1423  }
1424
1425  resizeTable(): void {
1426    this.resize(this.typeUsageTbl);
1427    this.resize(this.threadUsageTbl);
1428    this.resize(this.soUsageTbl);
1429    this.resize(this.functionUsageTbl);
1430  }
1431
1432  resize(table?: LitTable | null): void {
1433    if (table) {
1434      // @ts-ignore
1435      table.shadowRoot.querySelector('.table').style.height = `${this.parentElement.clientHeight - 65}px`;
1436      table.reMeauseHeight();
1437    }
1438  }
1439
1440  public connectedCallback(): void {
1441    new ResizeObserver(() => {
1442      this.resizeTable();
1443      // @ts-ignore
1444      if (this.parentElement?.clientHeight !== 0) {
1445        if ((this.parentElement!.clientHeight >= 0 && this.parentElement!.clientHeight <= 31) || this.isStatistic) {
1446          this.filterEl!.style.display = 'none';
1447          this.nmPieChart!.style.marginBottom = '0px';
1448          this.nmTableBox!.style.marginBottom = '0px';
1449        } else {
1450          this.filterEl!.style.display = 'flex';
1451        }
1452      }
1453    }).observe(this.parentElement!);
1454  }
1455
1456  initHtml(): string {
1457    return TabPaneNMStatisticAnalysisHtml;
1458  }
1459}
1460