• 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<any> {
56    let gpuData: Array<any> = [];
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    for (const item of baseGpuData) {
90      this.baseGpuData.push(
91        new GpuDumpComparison(item.windowNameId, item.windowId, item.moduleId, item.categoryId, item.size)
92      );
93    }
94    for (let item of dataList) {
95      if (item.startNs !== startTs) {
96        dataArray.push(item);
97      }
98    }
99    this.selectStamps(dataArray, type);
100    this.getComparisonData(dataArray[0].startNs, type);
101  }
102  selectStamps(gpuSelectComList: Array<SnapshotStruct>, type: string): void {
103    let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement;
104    this.selectEl!.innerHTML = '';
105    let option = new LitSelectOption();
106    option.innerHTML = 'File Name';
107    option.setAttribute('disabled', 'disabled');
108    this.selectEl?.appendChild(option);
109    if (gpuSelectComList[0].name) {
110      option.setAttribute('value', gpuSelectComList[0].name);
111    }
112    option.setAttribute('value', gpuSelectComList[0].name);
113    this.selectEl!.defaultValue = gpuSelectComList[0].name || '';
114    this.selectEl!.placeholder = gpuSelectComList[0].name || '';
115    this.selectEl!.dataSource = gpuSelectComList;
116    this.selectEl!.querySelectorAll('lit-select-option').forEach((option) => {
117      option.addEventListener('onSelected', async (e) => {
118        for (let f of gpuSelectComList) {
119          if (input.value === f.name) {
120            this.getComparisonData(f.startNs, type);
121          }
122        }
123        e.stopPropagation();
124      });
125    });
126  }
127  async getComparisonData(targetStartNs: number, type: string): Promise<void> {
128    let comparisonData: Array<GpuDumpComparison> = [];
129    let targetGpuData: Array<GpuDumpComparison> = [];
130    let data = await this.queryDataByDB(type, targetStartNs);
131    for (const item of data) {
132      targetGpuData.push(
133        new GpuDumpComparison(item.windowNameId, item.windowId, item.moduleId, item.categoryId, item.size)
134      );
135    }
136    comparisonData = compare(this.baseGpuData!, targetGpuData);
137    for (const item of comparisonData) {
138      item.size = item.value;
139    }
140    let items = this.createTreeData(comparisonData);
141    this.gpuComparisonSource = (type === 'total' ? items[0].children : items) || [];
142    this.comparisonSortData = this.gpuComparisonSource;
143    this.gpuComparisonTbl!.recycleDataSource = this.gpuComparisonSource;
144    let labels = this.gpuComparisonTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label');
145    this.theadClick(this.gpuComparisonTbl!, this.gpuComparisonSource);
146    this.gpuComparisonTbl!.loading = false;
147  }
148
149  sortGpuByColumn(column: string, sort: number): void {
150    switch (sort) {
151      case 0:
152        this.gpuComparisonTbl!.recycleDataSource = this.comparisonSortData;
153        break;
154      default:
155        let array = [...this.comparisonSortData];
156        switch (column) {
157          case 'name':
158            this.gpuComparisonTbl!.recycleDataSource = array.sort((gpuComparisonLeftData, gpuComparisonRightData) => {
159              return sort === 1
160                ? `${gpuComparisonLeftData.name}`.localeCompare(`${gpuComparisonRightData.name}`)
161                : `${gpuComparisonRightData.name}`.localeCompare(`${gpuComparisonLeftData.name}`);
162            });
163            break;
164          case 'sizeDelta':
165            this.gpuComparisonTbl!.recycleDataSource = array.sort((gpuComparisonLeftData, gpuComparisonRightData) => {
166              return sort === 1
167                ? gpuComparisonLeftData.size - gpuComparisonRightData.size
168                : gpuComparisonRightData.size - gpuComparisonLeftData.size;
169            });
170            break;
171        }
172        break;
173    }
174  }
175
176  initHtml(): string {
177    return `
178    <style>
179    :host{
180        display: flex;
181        flex-direction: column;
182        padding: 10px 10px;
183    }
184    </style>
185    <lit-table id="tb-gpu" style="height: auto" tree>
186            <lit-table-column width="50%" title="" data-index="name" key="name" align="flex-start" order retract>
187            </lit-table-column>
188            <lit-table-column width="1fr" title="SizeDelta" data-index="sizeStr" key="sizeDelta"  align="flex-start" order>
189            </lit-table-column>
190    </lit-table>
191    <tab-pane-js-memory-filter id="filter" first hideFilter ></tab-pane-js-memory-filter>
192        `;
193  }
194}
195export class GpuDumpComparison extends CompareStruct {
196  windowNameId: number = -1;
197  windowId: number = -1;
198  moduleId: number = -1;
199  categoryId: number = -1;
200  size: number = -1;
201  constructor(windowNameId: number, windowId: number, moduleId: number, categoryId: number, value: number) {
202    super(`${windowNameId}` + '' + `${windowId}` + '' + `${moduleId}` + '' + `${categoryId}`, value);
203    this.windowNameId = windowNameId;
204    this.moduleId = moduleId;
205    this.windowId = windowId;
206    this.categoryId = categoryId;
207  }
208  clone(isBase?: boolean): GpuDumpComparison {
209    const value = isBase ? this.value : -this.value;
210    return new GpuDumpComparison(this.windowNameId, this.windowId, this.moduleId, this.categoryId, value);
211  }
212}
213