• 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.js';
17import { LitTabs } from '../../../../base-ui/tabs/lit-tabs.js';
18import { LitTabpane } from '../../../../base-ui/tabs/lit-tabpane.js';
19import { BoxJumpParam, SelectionParam } from '../../../bean/BoxSelection.js';
20import { TabPaneCurrentSelection } from '../sheet/TabPaneCurrentSelection.js';
21import { TabPaneFlag } from '../timer-shaft/TabPaneFlag.js';
22import { Flag } from '../timer-shaft/Flag.js';
23import { WakeupBean } from '../../../bean/WakeupBean.js';
24import { LitIcon } from '../../../../base-ui/icon/LitIcon.js';
25import { tabConfig } from './TraceSheetConfig.js';
26import { TabPaneBoxChild } from '../sheet/cpu/TabPaneBoxChild.js';
27import { CpuStruct } from '../../../database/ui-worker/ProcedureWorkerCPU.js';
28import { CpuFreqStruct } from '../../../database/ui-worker/ProcedureWorkerFreq.js';
29import { CpuFreqLimitsStruct } from '../../../database/ui-worker/ProcedureWorkerCpuFreqLimits.js';
30import { ThreadStruct } from '../../../database/ui-worker/ProcedureWorkerThread.js';
31import { FuncStruct } from '../../../database/ui-worker/ProcedureWorkerFunc.js';
32import { ProcessMemStruct } from '../../../database/ui-worker/ProcedureWorkerMem.js';
33import { CpuStateStruct } from '../../../database/ui-worker/ProcedureWorkerCpuState.js';
34import { ClockStruct } from '../../../database/ui-worker/ProcedureWorkerClock.js';
35import { IrqStruct } from '../../../database/ui-worker/ProcedureWorkerIrq.js';
36import { JankStruct } from '../../../database/ui-worker/ProcedureWorkerJank.js';
37import { HeapStruct } from '../../../database/ui-worker/ProcedureWorkerHeap.js';
38import { LitTable } from '../../../../base-ui/table/lit-table.js';
39import { queryNativeHookResponseTypes, threadPool } from '../../../database/SqlLite.js';
40import { HeapSnapshotStruct } from '../../../database/ui-worker/ProcedureWorkerHeapSnapshot.js';
41import { TabPaneNMStatisticAnalysis } from '../sheet/native-memory/TabPaneNMStatisticAnalysis.js';
42import { TabPaneCurrent } from '../sheet/TabPaneCurrent.js';
43import { SlicesTime } from '../timer-shaft/SportRuler.js';
44import { AppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAppStartup.js';
45import { SoStruct } from '../../../database/ui-worker/ProcedureWorkerSoInit.js';
46import { FrameAnimationStruct } from '../../../database/ui-worker/ProcedureWorkerFrameAnimation.js';
47import { TraceRow } from './TraceRow.js';
48import { FrameDynamicStruct } from '../../../database/ui-worker/ProcedureWorkerFrameDynamic.js';
49import { TabPaneFrameDynamic } from '../sheet/frame/TabPaneFrameDynamic.js';
50import { FrameSpacingStruct } from '../../../database/ui-worker/ProcedureWorkerFrameSpacing.js';
51import { TabFrameSpacing } from '../sheet/frame/TabFrameSpacing.js';
52import { procedurePool } from '../../../database/Procedure.js';
53import { JsCpuProfilerChartFrame } from '../../../bean/JsStruct.js';
54import { TabPaneJsCpuTopDown } from '../sheet/ark-ts/TabPaneJsCpuCallTree.js';
55import { TabPaneComparison } from '../sheet/ark-ts/TabPaneComparison.js';
56import { TabPaneSummary } from '../sheet/ark-ts/TabPaneSummary.js';
57import { TabPaneGpuClickSelect } from '../sheet/gpu/TabPaneGpuClickSelect.js';
58import { TabPanePurgTotalSelection } from '../sheet/ability/TabPanePurgTotalSelection.js';
59import { TabPanePurgPinSelection } from '../sheet/ability/TabPanePurgPinSelection.js';
60import { TabPaneVmTrackerShmSelection } from '../sheet/vmtracker/TabPaneVmTrackerShmSelection.js';
61import { TabPaneSmapsStatistics } from '../sheet/smaps/TabPaneSmapsStatistics.js';
62import { TabPaneSmapsComparison } from '../sheet/smaps/TabPaneSmapsComparison.js';
63import { SnapshotStruct } from '../../../database/ui-worker/ProcedureWorkerSnapshot.js';
64import { TabPaneDmaSelectAbility } from '../sheet/ability/TabPaneDmaSelectAbility.js';
65import { TabPaneGpuMemorySelectAbility } from '../sheet/ability/TabPaneGpuMemorySelectAbility.js';
66import { TabPaneDmaSelectVmTracker } from '../sheet/vmtracker/TabPaneDmaSelectVmTracker.js';
67import { TabPanePurgTotalComparisonAbility } from '../sheet/ability/TabPanePurgTotalComparisonAbility.js';
68import { TabPanePurgPinComparisonAbility } from '../sheet/ability/TabPanePurgPinComparisonAbility.js';
69import { TabPanePurgTotalComparisonVM } from '../sheet/vmtracker/TabPanePurgTotalComparisonVM.js';
70import { TabPanePurgPinComparisonVM } from '../sheet/vmtracker/TabPanePurgPinComparisonVM.js';
71import { TabPaneDmaAbilityComparison } from '../sheet/ability/TabPaneDmaAbilityComparison.js';
72import { TabPaneGpuMemoryComparison } from '../sheet/ability/TabPaneGpuMemoryComparison.js';
73import { TabPaneDmaVmTrackerComparison } from '../sheet/vmtracker/TabPaneDmaVmTrackerComparison.js';
74import { TabPaneGpuMemorySelectVmTracker } from '../sheet/vmtracker/TabPaneGpuMemorySelectVmTracker.js';
75import { TabPaneGpuMemoryVmTrackerComparison } from '../sheet/vmtracker/TabPaneGpuMemoryVmTrackerComparison.js';
76import { TabPaneVmTrackerShmComparison } from '../sheet/vmtracker/TabPaneVmTrackerShmComparison.js';
77import { TabPaneJsCpuStatistics } from '../sheet/ark-ts/TabPaneJsCpuStatistics.js';
78import { TabPaneGpuClickSelectComparison } from '../sheet/gpu/TabPaneGpuClickSelectComparison.js';
79
80@element('trace-sheet')
81export class TraceSheet extends BaseElement {
82  private litTabs: LitTabs | undefined | null;
83  private importDiv: HTMLDivElement | undefined | null;
84  private nav: HTMLDivElement | undefined | null;
85  private selection: SelectionParam | undefined | null;
86  private currentPaneID: string = 'current-selection';
87  private fragment: DocumentFragment | undefined;
88
89  static get observedAttributes(): string[] {
90    return ['mode'];
91  }
92
93  buildTabs(litTabs: LitTabs | undefined | null): void {
94    this.fragment = document.createDocumentFragment();
95    Reflect.ownKeys(tabConfig).forEach((key, index) => {
96      let pane = new LitTabpane();
97      pane.id = key.toString();
98      pane.className = 'tabHeight';
99      pane.tab = tabConfig[key].title;
100      pane.hidden = true;
101      pane.key = `${tabConfig[key].key || index}`;
102      let cls = tabConfig[key].type;
103      let node = new cls();
104      pane.append(node);
105      this.fragment?.appendChild(pane);
106    });
107    litTabs!.appendChild(this.fragment);
108  }
109
110  displayTab<T>(...names: string[]): T {
111    this.setAttribute('mode', 'max');
112    this.showUploadSoBt(null);
113    this.shadowRoot
114      ?.querySelectorAll<LitTabpane>('#tabs lit-tabpane')
115      .forEach((it) => (it.hidden = !names.some((k) => k === it.id)));
116    let litTabpane = this.shadowRoot?.querySelector<LitTabpane>(`#tabs lit-tabpane[id='${names[0]}']`);
117    this.shadowRoot?.querySelector<LitTabs>('#tabs')?.activePane(litTabpane!.key);
118    return litTabpane!.children.item(0) as unknown as T;
119  }
120
121  getComponentByID<T>(id: string): T {
122    return this.getPaneByID(id)!.children.item(0) as unknown as T;
123  }
124
125  getPaneByID(id: string): LitTabpane {
126    return this.shadowRoot!.querySelector(`#${id}`)!;
127  }
128
129  initElements(): void {
130    this.litTabs = this.shadowRoot?.querySelector('#tabs');
131    this.importDiv = this.shadowRoot?.querySelector('#import_div');
132    this.buildTabs(this.litTabs);
133    let minBtn = this.shadowRoot?.querySelector('#min-btn');
134    minBtn?.addEventListener('click', () => {});
135    this.litTabs!.onTabClick = (e: any): void => this.loadTabPaneData(e.detail.key);
136    this.litTabs!.addEventListener('close-handler', () => {
137      Reflect.ownKeys(tabConfig)
138        .reverse()
139        .forEach((id) => {
140          let element = tabConfig[id];
141          let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`);
142          if (element.require) {
143            pane!.hidden = !element.require(this.selection);
144          } else {
145            pane!.hidden = true;
146          }
147        });
148      this.litTabs?.activeByKey(`${this.getPaneByID(this.currentPaneID).key}`);
149    });
150    this.getComponentByID<any>('box-spt')!.addEventListener('row-click', this.rowClickHandler.bind(this));
151    this.getComponentByID<any>('box-pts')!.addEventListener('row-click', this.rowClickHandler.bind(this));
152    this.getComponentByID<any>('box-native-statstics')!.addEventListener('row-click', (e: any) => {
153      this.selection!.statisticsSelectData = e.detail;
154      let pane = this.getPaneByID('box-native-memory');
155      this.litTabs?.activeByKey(pane.key);
156      (pane.children.item(0) as any)!.fromStastics(this.selection);
157    });
158    this.getComponentByID<any>('box-virtual-memory-statistics')!.addEventListener('row-click', (e: any) => {
159      this.selection!.fileSystemVMData = { path: e.detail.path };
160      let pane = this.getPaneByID('box-vm-events');
161      this.litTabs?.activeByKey(pane.key);
162      if (e.detail.path) {
163        (pane.children.item(0) as any)!.fromStastics(this.selection);
164      }
165    });
166    this.getComponentByID<any>('box-io-tier-statistics')!.addEventListener('row-click', (e: any) => {
167      this.selection!.fileSystemIoData = { path: e.detail.path };
168      let pane = this.getPaneByID('box-io-events');
169      this.litTabs?.activeByKey(pane.key);
170      if (e.detail.path) {
171        (pane.children.item(0) as any)!.fromStastics(this.selection);
172      }
173    });
174    this.getComponentByID<any>('box-file-system-statistics')!.addEventListener('row-click', (e: any) => {
175      this.selection!.fileSystemFsData = e.detail.data;
176      let pane = this.getPaneByID('box-file-system-event');
177      this.litTabs?.activeByKey(pane.key);
178      if (e.detail.data) {
179        (pane.children.item(0) as any)!.fromStastics(this.selection);
180      }
181    });
182  }
183  connectedCallback(): void {
184    this.nav = this.shadowRoot?.querySelector('#tabs')?.shadowRoot?.querySelector('.tab-nav-container');
185    let tabs: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#tabs');
186    let navRoot: HTMLDivElement | null | undefined = this.shadowRoot
187      ?.querySelector('#tabs')
188      ?.shadowRoot?.querySelector('.nav-root');
189    let search: HTMLDivElement | undefined | null = document
190      .querySelector('body > sp-application')
191      ?.shadowRoot?.querySelector('div > div.search-container');
192    let timerShaft: HTMLDivElement | undefined | null = this.parentElement?.querySelector('.timer-shaft');
193    let spacer: HTMLDivElement | undefined | null = this.parentElement?.querySelector('.spacer');
194    let rowsPaneEL: HTMLDivElement | undefined | null = this.parentElement?.querySelector('.rows-pane');
195
196    let borderTop: number = 1;
197    let initialHeight = { tabs: `calc(30vh + 39px)`, node: '30vh' };
198    this.nav!.onmousedown = (event): void => {
199      (window as any).isSheetMove = true;
200      let litTabpane: NodeListOf<HTMLDivElement> | undefined | null =
201        this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane');
202      let preY = event.pageY;
203      let preHeight = tabs!.offsetHeight;
204      document.onmousemove = function (event): void {
205        let moveY: number = preHeight - (event.pageY - preY);
206        litTabpane!.forEach((node: HTMLDivElement) => {
207          if (spacer!.offsetHeight > rowsPaneEL!.offsetHeight) {
208            tabs!.style.height = moveY + 'px';
209            node!.style.height = moveY - navRoot!.offsetHeight + 'px';
210            tabsPackUp!.name = 'down';
211          } else if (
212            navRoot!.offsetHeight <= moveY &&
213            search!.offsetHeight + timerShaft!.offsetHeight + borderTop + spacer!.offsetHeight <=
214              window.innerHeight - moveY
215          ) {
216            tabs!.style.height = moveY + 'px';
217            node!.style.height = moveY - navRoot!.offsetHeight + 'px';
218            tabsPackUp!.name = 'down';
219          } else if (navRoot!.offsetHeight >= moveY) {
220            tabs!.style.height = navRoot!.offsetHeight + 'px';
221            node!.style.height = '0px';
222            tabsPackUp!.name = 'up';
223          } else if (
224            search!.offsetHeight + timerShaft!.offsetHeight + borderTop + spacer!.offsetHeight >=
225            window.innerHeight - moveY
226          ) {
227            tabs!.style.height =
228              window.innerHeight -
229              search!.offsetHeight -
230              timerShaft!.offsetHeight -
231              borderTop -
232              spacer!.offsetHeight +
233              'px';
234            node!.style.height =
235              window.innerHeight -
236              search!.offsetHeight -
237              timerShaft!.offsetHeight -
238              navRoot!.offsetHeight -
239              borderTop -
240              spacer!.offsetHeight +
241              'px';
242            tabsPackUp!.name = 'down';
243          }
244        });
245      };
246      document.onmouseup = function (): void {
247        setTimeout(() => {
248          (window as any).isSheetMove = false;
249        }, 100);
250        litTabpane!.forEach((node: HTMLDivElement) => {
251          if (node!.style.height !== '0px' && tabs!.style.height != '') {
252            initialHeight.node = node!.style.height;
253            initialHeight.tabs = tabs!.style.height;
254          }
255        });
256        this.onmousemove = null;
257        this.onmouseup = null;
258      };
259    };
260    let tabsOpenUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#max-btn');
261    let tabsPackUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#min-btn');
262    let importFileBt: HTMLInputElement | undefined | null =
263      this.shadowRoot?.querySelector<HTMLInputElement>('#import-file');
264    let exportDataBt: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#export-btn');
265    tabsOpenUp!.onclick = (): void => {
266      tabs!.style.height = window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - borderTop + 'px';
267      let litTabpane: NodeListOf<HTMLDivElement> | undefined | null =
268        this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane');
269      litTabpane!.forEach((node: HTMLDivElement) => {
270        node!.style.height =
271          window.innerHeight -
272          search!.offsetHeight -
273          timerShaft!.offsetHeight -
274          navRoot!.offsetHeight -
275          borderTop +
276          'px';
277        initialHeight.node = node!.style.height;
278      });
279      initialHeight.tabs = tabs!.style.height;
280      tabsPackUp!.name = 'down';
281    };
282    tabsPackUp!.onclick = (): void => {
283      let litTabpane: NodeListOf<HTMLDivElement> | undefined | null =
284        this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane');
285      if (tabsPackUp!.name == 'down') {
286        tabs!.style.height = navRoot!.offsetHeight + 'px';
287        litTabpane!.forEach((node: HTMLDivElement) => (node!.style.height = '0px'));
288        tabsPackUp!.name = 'up';
289        (window as any).isPackUpTable = true;
290      } else {
291        tabsPackUp!.name = 'down';
292        tabs!.style.height = initialHeight.tabs;
293        litTabpane!.forEach((node: HTMLDivElement) => (node!.style.height = initialHeight.node));
294      }
295    };
296    importFileBt!.addEventListener('change', (event) => {
297      let files = importFileBt?.files;
298      if (files) {
299        let fileList: Array<File> = [];
300        for (let file of files) {
301          if (file.name.endsWith('.so')) {
302            fileList.push(file);
303          }
304        }
305        if (fileList.length > 0) {
306          importFileBt!.disabled = true;
307          window.publish(window.SmartEvent.UI.Loading, true);
308          threadPool.submit(
309            'upload-so',
310            '',
311            fileList,
312            (res: string) => {
313              importFileBt!.disabled = false;
314              if (res === 'ok') {
315                window.publish(window.SmartEvent.UI.UploadSOFile, {});
316              } else {
317                window.publish(window.SmartEvent.UI.Error, 'parse so file failed!');
318              }
319            },
320            'upload-so'
321          );
322        }
323        fileList.length = 0;
324      }
325      importFileBt!.files = null;
326      importFileBt!.value = '';
327    });
328    exportDataBt!.onclick = (): void => {
329      let currentTab = this.getTabpaneByKey(this.litTabs?.activekey!);
330      if (currentTab) {
331        let tables = Array.from(
332          (currentTab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitTable>('lit-table') || []
333        );
334        for (let table of tables) {
335          if (!table.hasAttribute('hideDownload')) {
336            table.exportData();
337          }
338        }
339      }
340    };
341  }
342
343  getTabpaneByKey(key: string): LitTabpane | undefined {
344    let tabs = Array.from(this.shadowRoot?.querySelectorAll<LitTabpane>('#tabs lit-tabpane').values() || []);
345    return tabs.find((it) => it.key === key);
346  }
347
348  initHtml(): string {
349    return `
350            <style>
351                :host([mode='hidden']){
352                    display: none;
353                }
354                :host{
355                    display: block;
356                    background-color: rebeccapurple;
357                }
358                .tabHeight{
359                    height: 30vh;
360                    background-color: var(--dark-background,#FFFFFF);
361                }
362            </style>
363            <div id="container" style="border-top: 1px solid var(--dark-border1,#D5D5D5);">
364                <lit-tabs id="tabs" position="top-left" activekey="1" mode="card" >
365                    <div slot="right" style="margin: 0 10px; color: var(--dark-icon,#606060);display: flex;align-items: center;">
366                        <div title="SO导入" id="import_div" style="width: 20px;height: 20px;display: flex;flex-direction: row;margin-right: 10px">
367                            <input id="import-file" style="display: none;pointer-events: none" type="file" webkitdirectory>
368                            <label style="width: 20px;height: 20px;cursor: pointer;" for="import-file">
369                                <lit-icon id="import-btn" name="copy-csv" style="pointer-events: none" size="20">
370                                </lit-icon>
371                            </label>
372                        </div>
373                        <lit-icon title="下载数据" id="export-btn" name="import-so" style="font-weight: bold;cursor: pointer;margin-right: 10px" size="20">
374                        </lit-icon>
375                        <lit-icon title="最大化" id="max-btn" name="vertical-align-top" style="font-weight: bold;cursor: pointer;margin-right: 10px" size="20">
376                        </lit-icon>
377                        <lit-icon title="最小化" id="min-btn" name="down" style="font-weight: bold;cursor: pointer;" size="20">
378                        </lit-icon>
379                    </div>
380                </lit-tabs>
381            </div>`;
382  }
383  displayCurrent = (data: SlicesTime): void =>
384    this.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(data);
385  displayThreadData = (
386    data: ThreadStruct,
387    scrollCallback: ((e: ThreadStruct) => void) | undefined,
388    scrollWakeUp: (d: any) => void | undefined,
389    scrollPreviousData: (d: ThreadStruct) => void,
390    scrollNextData: (d: ThreadStruct) => void
391  ) =>
392    this.displayTab<TabPaneCurrentSelection>('current-selection').setThreadData(
393      data,
394      scrollCallback,
395      scrollWakeUp,
396      scrollPreviousData,
397      scrollNextData
398    );
399  displayMemData = (data: ProcessMemStruct): void =>
400    this.displayTab<TabPaneCurrentSelection>('current-selection').setMemData(data);
401  displayClockData = (data: ClockStruct): void =>
402    this.displayTab<TabPaneCurrentSelection>('current-selection').setClockData(data);
403  displayIrqData = (data: IrqStruct): void =>
404    this.displayTab<TabPaneCurrentSelection>('current-selection').setIrqData(data);
405  displayStartupData = (data: AppStartupStruct, scrollCallback: Function): void =>
406    this.displayTab<TabPaneCurrentSelection>('current-selection').setStartupData(data, scrollCallback);
407  displayStaticInitData = (data: SoStruct, scrollCallback: Function): void =>
408    this.displayTab<TabPaneCurrentSelection>('current-selection').setStaticInitData(data, scrollCallback);
409
410  displayNativeHookData = (data: HeapStruct, rowType: string): void => {
411    let val = new SelectionParam();
412    val.nativeMemoryStatistic.push(rowType);
413    val.nativeMemory = [];
414    val.leftNs = data.startTime!;
415    val.rightNs = data.startTime! + data.dur! - 1;
416    this.selection = val;
417    this.displayTab<TabPaneNMStatisticAnalysis>('box-native-statistic-analysis', 'box-native-calltree').data = val;
418    this.showUploadSoBt(val);
419  };
420
421  displayGpuSelectedData = (type: string, startTs: number, dataList: Array<SnapshotStruct>) => {
422    this.displayTab<TabPaneGpuClickSelectComparison>('gpu-click-select-comparison').getGpuClickDataByDB(
423      type,
424      startTs,
425      dataList
426    );
427    let dataObject = { type: type, startTs: startTs };
428    this.displayTab<TabPaneGpuClickSelect>('gpu-click-select', 'gpu-click-select-comparison').gpuClickData(dataObject);
429  };
430
431  displayFuncData = (names: string[], data: FuncStruct, scrollCallback: Function): void =>
432    this.displayTab<TabPaneCurrentSelection>(...names).setFunctionData(data, scrollCallback);
433  displayCpuData = (
434    data: CpuStruct,
435    callback: ((data: WakeupBean | null) => void) | undefined = undefined,
436    scrollCallback?: (data: CpuStruct) => void
437  ): void => this.displayTab<TabPaneCurrentSelection>('current-selection').setCpuData(data, callback, scrollCallback);
438  displayJankData = (
439    data: JankStruct,
440    callback: ((data: Array<any>) => void) | undefined = undefined,
441    scrollCallback: ((e: JankStruct) => void) | undefined
442  ) => this.displayTab<TabPaneCurrentSelection>('current-selection').setJankData(data, callback, scrollCallback);
443  displayShmData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>) => {
444    this.displayTab<TabPaneVmTrackerShmComparison>('box-vmtracker-shm-comparison').setShmData(data, dataList);
445    this.displayTab<TabPaneVmTrackerShmSelection>(
446      'box-vmtracker-shm-selection',
447      'box-vmtracker-shm-comparison'
448    ).setShmData(data, dataList);
449  };
450  displaySmapsData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>) => {
451    let val = new SelectionParam();
452    val.smapsType = [];
453    val.leftNs = data.startNs;
454    this.selection = val;
455    val.smapsType = [];
456    this.displayTab<TabPaneSmapsComparison>('box-smaps-comparison').setData(val, dataList);
457    this.displayTab<TabPaneSmapsStatistics>('box-smaps-statistics', 'box-smaps-record', 'box-smaps-comparison').data =
458      val;
459  };
460  displaySnapshotData = (
461    data: HeapSnapshotStruct,
462    dataList: Array<HeapSnapshotStruct>,
463    scrollCallback?: (data: HeapSnapshotStruct, dataList: Array<HeapSnapshotStruct>) => void
464  ): void => {
465    if (dataList.length > 1) {
466      this.displayTab<TabPaneSummary>('box-heap-summary', 'box-heap-comparison').setSnapshotData(
467        data,
468        dataList,
469        scrollCallback
470      );
471      let nav = this.shadowRoot!.querySelector('#tabs')!.shadowRoot!.querySelector(
472        '#nav > #nav-comparison'
473      ) as HTMLDivElement;
474      let tabPaneComparison = this.shadowRoot!.querySelector(
475        '#box-heap-comparison > tabpane-comparison'
476      ) as TabPaneComparison;
477      nav!.onclick = (): void => {
478        tabPaneComparison.initComparison(data, dataList);
479      };
480    } else {
481      this.displayTab<TabPaneSummary>('box-heap-summary').setSnapshotData(data, dataList, scrollCallback);
482    }
483  };
484  displayFlagData = (flagObj: Flag): void => this.displayTab<TabPaneFlag>('box-flag').setFlagObj(flagObj);
485  displayFreqData = (): CpuFreqStruct | undefined =>
486    (this.displayTab<TabPaneCurrentSelection>('box-freq').data = CpuFreqStruct.selectCpuFreqStruct);
487  displayCpuStateData = (): CpuStateStruct | undefined =>
488    (this.displayTab<TabPaneCurrentSelection>('cpu-state-click').data = CpuStateStruct.selectStateStruct);
489  displayFreqLimitData = (): CpuFreqLimitsStruct | undefined =>
490    (this.displayTab<TabPaneCurrentSelection>('box-freq-limit').data = CpuFreqLimitsStruct.selectCpuFreqLimitsStruct);
491
492  displayFrameAnimationData = (data: FrameAnimationStruct): Promise<void> =>
493    this.displayTab<TabPaneCurrentSelection>('current-selection').setFrameAnimationData(data);
494  displayFrameDynamicData = (row: TraceRow<FrameDynamicStruct>, data: FrameDynamicStruct): void =>
495    this.displayTab<TabPaneFrameDynamic>('box-frame-dynamic').buildDynamicTable([data], true);
496  displayFrameSpacingData = (data: FrameSpacingStruct): void =>
497    this.displayTab<TabFrameSpacing>('box-frames-spacing').setFrameSpacingData(data);
498  displayJsProfilerData = (data: Array<JsCpuProfilerChartFrame>): void => {
499    let val = new SelectionParam();
500    val.jsCpuProfilerData = data;
501    this.selection = val;
502    this.displayTab<TabPaneJsCpuStatistics>(
503      'box-js-Profiler-statistics',
504      'box-js-Profiler-bottom-up',
505      'box-js-Profiler-top-down'
506    ).data = data;
507  };
508  displayPurgTotalAbilityData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>) => {
509    data.type = 'ability';
510    this.displayTab<TabPanePurgTotalComparisonAbility>('box-purgeable-total-comparison-ability').totalData(
511      data,
512      dataList
513    );
514    this.displayTab<TabPanePurgTotalSelection>(
515      'box-purgeable-total-selection',
516      'box-purgeable-total-comparison-ability'
517    ).data = data;
518  };
519  displayPurgPinAbilityData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>) => {
520    data.type = 'ability';
521    this.displayTab<TabPanePurgPinComparisonAbility>('box-purgeable-pin-comparison-ability').totalData(data, dataList);
522    this.displayTab<TabPanePurgPinSelection>(
523      'box-purgeable-pin-selection',
524      'box-purgeable-pin-comparison-ability'
525    ).data = data;
526  };
527  displayPurgTotalVMData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>) => {
528    data.type = 'VM';
529    this.displayTab<TabPanePurgTotalComparisonVM>('box-purgeable-total-comparison-vm').totalData(data, dataList);
530    this.displayTab<TabPanePurgTotalSelection>(
531      'box-purgeable-total-selection',
532      'box-purgeable-total-comparison-vm'
533    ).data = data;
534  };
535  displayPurgPinVMData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>) => {
536    data.type = 'VM';
537    this.displayTab<TabPanePurgPinComparisonVM>('box-purgeable-pin-comparison-vm').totalData(data, dataList);
538    this.displayTab<TabPanePurgPinSelection>('box-purgeable-pin-selection', 'box-purgeable-pin-comparison-vm').data =
539      data;
540  };
541  displayDmaAbility = (data: number, dataList: Array<SnapshotStruct>) => {
542    if (dataList.length > 0) {
543      this.displayTab<TabPaneDmaAbilityComparison>('box-dma-ability-comparison').comparisonDataByDB(data, dataList);
544      this.displayTab<TabPaneDmaSelectAbility>(
545        'box-dma-selection-ability',
546        'box-dma-ability-comparison'
547      ).queryDmaClickDataByDB(data);
548    } else {
549      this.displayTab<TabPaneDmaSelectAbility>('box-dma-selection-ability').queryDmaClickDataByDB(data);
550    }
551  };
552  displayDmaVmTracker = (data: number, dataList: Array<SnapshotStruct>) => {
553    if (dataList.length > 0) {
554      this.displayTab<TabPaneDmaVmTrackerComparison>('box-vmTracker-comparison').comparisonDataByDB(data, dataList);
555      this.displayTab<TabPaneDmaSelectVmTracker>(
556        'box-dma-selection-vmTracker',
557        'box-vmTracker-comparison'
558      ).queryDmaVmTrackerClickDataByDB(data);
559    } else {
560      this.displayTab<TabPaneDmaSelectVmTracker>('box-dma-selection-vmTracker').queryDmaVmTrackerClickDataByDB(data);
561    }
562  };
563  displayGpuMemoryAbility = (data: number, dataList: Array<SnapshotStruct>) => {
564    if (dataList.length > 0) {
565      this.displayTab<TabPaneGpuMemoryComparison>('box-gpu-memory-comparison').comparisonDataByDB(data, dataList);
566      this.displayTab<TabPaneGpuMemorySelectAbility>(
567        'box-gpu-memory-selection-ability',
568        'box-gpu-memory-comparison'
569      ).queryGpuMemoryClickDataByDB(data);
570    } else {
571      this.displayTab<TabPaneGpuMemorySelectAbility>('box-gpu-memory-selection-ability').data = data;
572    }
573  };
574  displayGpuMemoryVmTracker = (data: number, dataList: Array<SnapshotStruct>) => {
575    if (dataList.length > 0) {
576      this.displayTab<TabPaneGpuMemoryVmTrackerComparison>('box-gpu-memory-vmTracker-comparison').comparisonDataByDB(
577        data,
578        dataList
579      );
580      this.displayTab<TabPaneGpuMemorySelectVmTracker>(
581        'box-gpu-memory-selection-vmTracker',
582        'box-gpu-memory-vmTracker-comparison'
583      ).queryGpuMemoryVmTrackerClickDataByDB(data);
584    } else {
585      this.displayTab<TabPaneGpuMemorySelectVmTracker>(
586        'box-gpu-memory-selection-vmTracker'
587      ).queryGpuMemoryVmTrackerClickDataByDB(data);
588    }
589  };
590
591  rangeSelect(selection: SelectionParam, restore = false): boolean {
592    this.selection = selection;
593    this.showUploadSoBt(selection);
594    Reflect.ownKeys(tabConfig)
595      .reverse()
596      .forEach((id) => {
597        let element = tabConfig[id];
598        let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`);
599        if (pane) {
600          pane.hidden = !(element.require && element.require(selection));
601        }
602      });
603    if (restore) {
604      if (this.litTabs?.activekey) {
605        this.loadTabPaneData(this.litTabs?.activekey);
606        this.setAttribute('mode', 'max');
607        return true;
608      } else {
609        this.setAttribute('mode', 'hidden');
610        return false;
611      }
612    } else {
613      let firstPane = this.shadowRoot!.querySelector<LitTabpane>(`lit-tabpane[hidden='false']`);
614      if (firstPane) {
615        this.litTabs?.activeByKey(firstPane.key);
616        this.loadTabPaneData(firstPane.key);
617        this.setAttribute('mode', 'max');
618        return true;
619      } else {
620        this.setAttribute('mode', 'hidden');
621        return false;
622      }
623    }
624  }
625
626  updateRangeSelect(): boolean {
627    if (
628      this.selection &&
629      (this.selection.nativeMemory.length > 0 ||
630        this.selection.nativeMemoryStatistic.length > 0 ||
631        this.selection.perfSampleIds.length > 0 ||
632        this.selection.fileSystemType.length > 0 ||
633        this.selection.fsCount > 0 ||
634        this.selection.fileSysVirtualMemory ||
635        this.selection.vmCount > 0 ||
636        this.selection.diskIOLatency ||
637        this.selection.diskIOipids.length > 0)
638    ) {
639      let param: SelectionParam = new SelectionParam();
640      Object.assign(param, this.selection);
641      if (param.nativeMemory.length > 0 || param.nativeMemoryStatistic.length > 0) {
642        this.initFilterLibList(param);
643      }
644      this.rangeSelect(param, true);
645      return true;
646    } else {
647      return false;
648    }
649  }
650
651  initFilterLibList(param: SelectionParam | any) {
652    let nmTypes: Array<string> = [];
653    if (param.nativeMemory.indexOf('All Heap & Anonymous VM') != -1) {
654      nmTypes.push("'AllocEvent'");
655      nmTypes.push("'MmapEvent'");
656    } else {
657      if (param.nativeMemory.indexOf('All Heap') != -1) {
658        nmTypes.push("'AllocEvent'");
659      }
660      if (param.nativeMemory.indexOf('All Anonymous VM') != -1) {
661        nmTypes.push("'MmapEvent'");
662      }
663    }
664    queryNativeHookResponseTypes(param.leftNs, param.rightNs, nmTypes).then((res) => {
665      procedurePool.submitWithName('logic1', 'native-memory-init-responseType', res, undefined, () => {});
666    });
667  }
668
669  showUploadSoBt(selection: SelectionParam | null | undefined): void {
670    if (
671      selection &&
672      (selection.nativeMemory.length > 0 ||
673        selection.nativeMemoryStatistic.length > 0 ||
674        selection.perfSampleIds.length > 0 ||
675        selection.fileSystemType.length > 0 ||
676        selection.fsCount > 0 ||
677        selection.fileSysVirtualMemory ||
678        selection.vmCount > 0 ||
679        selection.diskIOLatency ||
680        selection.diskIOipids.length > 0)
681    ) {
682      this.importDiv!.style.display = 'flex';
683    } else {
684      this.importDiv!.style.display = 'none';
685    }
686  }
687
688  loadTabPaneData(key: string): void {
689    let component: any = this.shadowRoot
690      ?.querySelector<LitTabpane>(`#tabs lit-tabpane[key='${key}']`)
691      ?.children.item(0);
692    if (component) {
693      component.data = this.selection;
694    }
695  }
696
697  rowClickHandler(e: any): void {
698    this.currentPaneID = e.target.parentElement.id;
699    this.shadowRoot!.querySelectorAll<LitTabpane>(`lit-tabpane`).forEach((it) =>
700      it.id != this.currentPaneID ? (it.hidden = true) : (it.hidden = false)
701    );
702    let pane = this.getPaneByID('box-cpu-child');
703    pane.closeable = true;
704    pane.hidden = false;
705    this.litTabs!.activeByKey(pane.key);
706    pane.tab = e.detail.title;
707    let param = new BoxJumpParam();
708    param.leftNs = this.selection!.leftNs;
709    param.rightNs = this.selection!.rightNs;
710    param.state = e.detail.state;
711    param.threadId = e.detail.threadId;
712    param.processId = e.detail.processId;
713    (pane.children.item(0) as TabPaneBoxChild).data = param;
714  }
715
716  clearMemory(): void {
717    let allTabs = Array.from(this.shadowRoot?.querySelectorAll<LitTabpane>('#tabs lit-tabpane').values() || []);
718    allTabs.forEach((tab) => {
719      if (tab) {
720        let tables = Array.from(
721          (tab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitTable>('lit-table') || []
722        );
723        for (let table of tables) {
724          table.recycleDataSource = [];
725        }
726      }
727    });
728  }
729}
730