• 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 { element } from '../../../../../base-ui/BaseElement';
16import { type LitSelect } from '../../../../../base-ui/select/LitSelect';
17import { LitSelectOption } from '../../../../../base-ui/select/LitSelectOption';
18import { type LitTable } from '../../../../../base-ui/table/lit-table';
19import { type SnapshotStruct } from '../../../../database/ui-worker/ProcedureWorkerSnapshot';
20import { VmTrackerChart } from '../../../chart/SpVmTrackerChart';
21import { compare, CompareStruct, resizeObserverFromMemory } from '../SheetUtils';
22import '../TabPaneJsMemoryFilter';
23import { type TabPaneJsMemoryFilter } from '../TabPaneJsMemoryFilter';
24import { TabPaneGpuClickSelect } from './TabPaneGpuClickSelect';
25import { queryGpuDataByTs } from '../../../../database/sql/Gpu.sql';
26interface GpuTreeItem {
27  name: string;
28  id: number;
29  size: number;
30  sizeStr: string;
31  children?: GpuTreeItem[] | undefined;
32}
33@element('tabpane-gpu-click-select-comparison')
34export class TabPaneGpuClickSelectComparison extends TabPaneGpuClickSelect {
35  private comparisonSelect: TabPaneJsMemoryFilter | null | undefined;
36  private selectEl: LitSelect | null | undefined;
37  private gpuComparisonTbl: LitTable | null | undefined;
38  private baseGpuData: Array<GpuDumpComparison> = [];
39  private gpuComparisonSource: Array<GpuTreeItem> = [];
40  private comparisonSortData: Array<GpuTreeItem> = [];
41
42  initElements(): void {
43    this.gpuComparisonTbl = this.shadowRoot?.querySelector<LitTable>('#tb-gpu');
44    this.comparisonSelect = this.shadowRoot?.querySelector('#filter') as TabPaneJsMemoryFilter;
45    this.selectEl = this.comparisonSelect?.shadowRoot?.querySelector<LitSelect>('lit-select');
46    this.gpuComparisonTbl!.addEventListener('column-click', (e) => {
47      // @ts-ignore
48      this.sortGpuByColumn(e.detail.key, e.detail.sort);
49    });
50  }
51  connectedCallback(): void {
52    super.connectedCallback();
53    resizeObserverFromMemory(this.parentElement!, this.gpuComparisonTbl!, this.comparisonSelect!);
54  }
55  async queryDataByDB(type: string, startTs: number): Promise<unknown> {
56    let gpuData: Array<unknown> = [];
57    let window = type === 'total' ? 0 : VmTrackerChart.gpuWindow;
58    let module = type === 'total' ? VmTrackerChart.gpuTotalModule : VmTrackerChart.gpuWindowModule;
59    await queryGpuDataByTs(startTs, window || 0, module).then((result) => {
60      gpuData = result;
61    });
62    return gpuData;
63  }
64  async getGpuClickDataByDB(type: string, startTs: number, dataList: Array<SnapshotStruct>): Promise<void> {
65    const dataArray = [];
66    let td = this.gpuComparisonTbl!.shadowRoot!.querySelector('.thead')?.firstChild?.firstChild as HTMLDivElement;
67    let title = type === 'total' ? 'Module / Category' : 'Window / Module / Category';
68    let titleArr = title.split('/');
69    if (td) {
70      let labelEls = td.querySelectorAll('label');
71      if (labelEls) {
72        for (let el of labelEls) {
73          td.removeChild(el);
74        }
75      }
76      for (let i = 0; i < titleArr.length; i++) {
77        let label = document.createElement('label');
78        label.style.cursor = 'pointer';
79        i == 0 ? (label.innerHTML = titleArr[i]) : (label.innerHTML = '/' + titleArr[i]);
80        td.appendChild(label);
81      }
82    }
83    //@ts-ignore
84    this.gpuComparisonTbl?.shadowRoot?.querySelector('.table')?.style?.height =
85      this.parentElement!.clientHeight - 45 + 'px';
86    this.gpuComparisonTbl!.loading = true;
87    this.baseGpuData = [];
88    let baseGpuData = await this.queryDataByDB(type, startTs);
89    // @ts-ignore
90    for (const item of baseGpuData) {
91      this.baseGpuData.push(
92        new GpuDumpComparison(item.windowNameId, item.windowId, item.moduleId, item.categoryId, item.size)
93      );
94    }
95    for (let item of dataList) {
96      if (item.startNs !== startTs) {
97        dataArray.push(item);
98      }
99    }
100    this.selectStamps(dataArray, type);
101    this.getComparisonData(dataArray[0].startNs, type);
102  }
103  selectStamps(gpuSelectComList: Array<SnapshotStruct>, type: string): void {
104    let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement;
105    this.selectEl!.innerHTML = '';
106    let option = new LitSelectOption();
107    option.innerHTML = 'File Name';
108    option.setAttribute('disabled', 'disabled');
109    this.selectEl?.appendChild(option);
110    if (gpuSelectComList[0].name) {
111      option.setAttribute('value', gpuSelectComList[0].name);
112    }
113    option.setAttribute('value', gpuSelectComList[0].name);
114    this.selectEl!.defaultValue = gpuSelectComList[0].name || '';
115    this.selectEl!.placeholder = gpuSelectComList[0].name || '';
116    this.selectEl!.dataSource = gpuSelectComList;
117    this.selectEl!.querySelectorAll('lit-select-option').forEach((option) => {
118      option.addEventListener('onSelected', async (e) => {
119        for (let f of gpuSelectComList) {
120          if (input.value === f.name) {
121            this.getComparisonData(f.startNs, type);
122          }
123        }
124        e.stopPropagation();
125      });
126    });
127  }
128  async getComparisonData(targetStartNs: number, type: string): Promise<void> {
129    let comparisonData: Array<GpuDumpComparison> = [];
130    let targetGpuData: Array<GpuDumpComparison> = [];
131    let data = await this.queryDataByDB(type, targetStartNs);
132    // @ts-ignore
133    for (const item of data) {
134      targetGpuData.push(
135        new GpuDumpComparison(item.windowNameId, item.windowId, item.moduleId, item.categoryId, item.size)
136      );
137    }
138    comparisonData = compare(this.baseGpuData!, targetGpuData);
139    for (const item of comparisonData) {
140      item.size = item.value;
141    }
142    let items = this.createTreeData(comparisonData);
143    // @ts-ignore
144    this.gpuComparisonSource = (type === 'total' ? items[0].children : items) || [];
145    this.comparisonSortData = this.gpuComparisonSource;
146    this.gpuComparisonTbl!.recycleDataSource = this.gpuComparisonSource;
147    let labels = this.gpuComparisonTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label');
148    this.theadClick(this.gpuComparisonTbl!, this.gpuComparisonSource);
149    this.gpuComparisonTbl!.loading = false;
150  }
151
152  sortGpuByColumn(column: string, sort: number): void {
153    switch (sort) {
154      case 0:
155        this.gpuComparisonTbl!.recycleDataSource = this.comparisonSortData;
156        break;
157      default:
158        let array = [...this.comparisonSortData];
159        switch (column) {
160          case 'name':
161            this.gpuComparisonTbl!.recycleDataSource = array.sort((gpuComparisonLeftData, gpuComparisonRightData) => {
162              return sort === 1
163                ? `${gpuComparisonLeftData.name}`.localeCompare(`${gpuComparisonRightData.name}`)
164                : `${gpuComparisonRightData.name}`.localeCompare(`${gpuComparisonLeftData.name}`);
165            });
166            break;
167          case 'sizeDelta':
168            this.gpuComparisonTbl!.recycleDataSource = array.sort((gpuComparisonLeftData, gpuComparisonRightData) => {
169              return sort === 1
170                ? gpuComparisonLeftData.size - gpuComparisonRightData.size
171                : gpuComparisonRightData.size - gpuComparisonLeftData.size;
172            });
173            break;
174        }
175        break;
176    }
177  }
178
179  initHtml(): string {
180    return `
181    <style>
182    :host{
183        display: flex;
184        flex-direction: column;
185        padding: 10px 10px;
186    }
187    </style>
188    <lit-table id="tb-gpu" style="height: auto" tree>
189            <lit-table-column width="50%" title="" data-index="name" key="name" align="flex-start" order retract>
190            </lit-table-column>
191            <lit-table-column width="1fr" title="SizeDelta" data-index="sizeStr" key="sizeDelta"  align="flex-start" order>
192            </lit-table-column>
193    </lit-table>
194    <tab-pane-js-memory-filter id="filter" first hideFilter ></tab-pane-js-memory-filter>
195        `;
196  }
197}
198export class GpuDumpComparison extends CompareStruct {
199  windowNameId: number = -1;
200  windowId: number = -1;
201  moduleId: number = -1;
202  categoryId: number = -1;
203  size: number = -1;
204  constructor(windowNameId: number, windowId: number, moduleId: number, categoryId: number, value: number) {
205    super(`${windowNameId}` + '' + `${windowId}` + '' + `${moduleId}` + '' + `${categoryId}`, value);
206    this.windowNameId = windowNameId;
207    this.moduleId = moduleId;
208    this.windowId = windowId;
209    this.categoryId = categoryId;
210  }
211  clone(isBase?: boolean): GpuDumpComparison {
212    const value = isBase ? this.value : -this.value;
213    return new GpuDumpComparison(this.windowNameId, this.windowId, this.moduleId, this.categoryId, value);
214  }
215}
216