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