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'; 17import { LitSelect } from '../../../../../base-ui/select/LitSelect'; 18import { LitSelectOption } from '../../../../../base-ui/select/LitSelectOption'; 19import { type LitTable } from '../../../../../base-ui/table/lit-table'; 20import { GpuMemoryComparison } from '../../../../bean/AbilityMonitor'; 21import { type SnapshotStruct } from '../../../../database/ui-worker/ProcedureWorkerSnapshot'; 22import { SpSystemTrace } from '../../../SpSystemTrace'; 23import { Utils } from '../../base/Utils'; 24import { compare, resizeObserverFromMemory } from '../SheetUtils'; 25import '../TabPaneJsMemoryFilter'; 26import { type TabPaneJsMemoryFilter } from '../TabPaneJsMemoryFilter'; 27import { getTabGpuMemoryComparisonData } from '../../../../database/sql/Ability.sql'; 28 29@element('tabpane-gpu-memory-comparison') 30export class TabPaneGpuMemoryComparison extends BaseElement { 31 private gpuMemoryClickTable: LitTable | null | undefined; 32 private comparisonSelect: TabPaneJsMemoryFilter | null | undefined; 33 private selectEl: LitSelect | null | undefined; 34 private selfData: Array<GpuMemoryComparison> = []; 35 private comparisonSource: Array<GpuMemoryComparison> = []; 36 37 initElements(): void { 38 this.gpuMemoryClickTable = this.shadowRoot?.querySelector<LitTable>('#gpuMemoryClickTable'); 39 this.comparisonSelect = this.shadowRoot?.querySelector('#filter') as TabPaneJsMemoryFilter; 40 this.selectEl = this.comparisonSelect?.shadowRoot?.querySelector<LitSelect>('lit-select'); 41 this.gpuMemoryClickTable!.addEventListener('column-click', (e) => { 42 // @ts-ignore 43 this.sortGpuMemoryByColumn(e.detail.key, e.detail.sort); 44 }); 45 } 46 47 connectedCallback(): void { 48 super.connectedCallback(); 49 resizeObserverFromMemory(this.parentElement!, this.gpuMemoryClickTable!, this.comparisonSelect!); 50 } 51 52 async queryDataByDB(startNs: number): Promise<GpuMemoryComparison[]> { 53 let timeStampData: Array<GpuMemoryComparison> = []; 54 await getTabGpuMemoryComparisonData(startNs).then((data) => { 55 data.forEach((item) => { 56 if (item.processName !== null) { 57 item.process = `${item.processName}(${item.processId})`; 58 } else { 59 item.process = `Process(${item.processId})`; 60 } 61 item.gpuName = SpSystemTrace.DATA_DICT.get(item.gpuNameId as number) || '-'; 62 }); 63 timeStampData = data; 64 }); 65 return timeStampData; 66 } 67 68 async comparisonDataByDB(startNs: number, dataList: Array<SnapshotStruct>): Promise<void> { 69 this.selfData = []; 70 let selfData = await this.queryDataByDB(startNs); 71 const dataArray = []; 72 for (const item of selfData) { 73 this.selfData.push(new GpuMemoryComparison(item.process, '', item.gpuName, item.value)); 74 } 75 for (let item of dataList) { 76 if (item.startNs !== startNs) { 77 dataArray.push(item); 78 } 79 } 80 this.selectStamps(dataArray); 81 this.getComparisonData(dataArray[0].startNs); 82 } 83 84 selectStamps(gpuMemoryComList: Array<SnapshotStruct>): void { 85 let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement; 86 this.selectEl!.innerHTML = ''; 87 let option = new LitSelectOption(); 88 option.innerHTML = 'File Name'; 89 option.setAttribute('disabled', 'disabled'); 90 this.selectEl?.appendChild(option); 91 if (gpuMemoryComList[0].name) { 92 option.setAttribute('value', gpuMemoryComList[0].name); 93 } 94 option.setAttribute('value', gpuMemoryComList[0].name); 95 this.selectEl!.defaultValue = gpuMemoryComList[0].name || ''; 96 this.selectEl!.placeholder = gpuMemoryComList[0].name || ''; 97 this.selectEl!.dataSource = gpuMemoryComList; 98 this.selectEl!.querySelectorAll('lit-select-option').forEach((option) => { 99 option.addEventListener('onSelected', async (e) => { 100 for (let f of gpuMemoryComList) { 101 if (input.value === f.name) { 102 this.getComparisonData(f.startNs); 103 } 104 } 105 e.stopPropagation(); 106 }); 107 }); 108 } 109 110 async getComparisonData(targetStartNs: number): Promise<void> { 111 let comparisonData: GpuMemoryComparison[] = []; 112 let comparison: GpuMemoryComparison[] = []; 113 let data = await this.queryDataByDB(targetStartNs); 114 for (const item of data) { 115 comparison.push(new GpuMemoryComparison(item.process, '', item.gpuName, item.value)); 116 } 117 comparisonData = compare(this.selfData!, comparison); 118 for (const item of comparisonData) { 119 item.sizes = Utils.getBinaryByteWithUnit(item.value); 120 } 121 this.comparisonSource = comparisonData; 122 this.gpuMemoryClickTable!.recycleDataSource = comparisonData; 123 } 124 125 sortGpuMemoryByColumn(column: string, sort: number): void { 126 switch (sort) { 127 case 0: 128 this.gpuMemoryClickTable!.recycleDataSource = this.comparisonSource; 129 break; 130 default: 131 let array = [...this.comparisonSource]; 132 switch (column) { 133 case 'process': 134 this.gpuMemoryClickTable!.recycleDataSource = array.sort( 135 (gpuMComparisonLeftData, gpuMComparisonRightData) => { 136 return sort === 1 137 ? `${gpuMComparisonLeftData.process}`.localeCompare(`${gpuMComparisonRightData.process}`) 138 : `${gpuMComparisonRightData.process}`.localeCompare(`${gpuMComparisonLeftData.process}`); 139 } 140 ); 141 break; 142 case 'gpuName': 143 this.gpuMemoryClickTable!.recycleDataSource = array.sort( 144 (gpuMComparisonLeftData, gpuMComparisonRightData) => { 145 return sort === 1 146 ? `${gpuMComparisonLeftData.gpuName}`.localeCompare(`${gpuMComparisonRightData.gpuName}`) 147 : `${gpuMComparisonRightData.gpuName}`.localeCompare(`${gpuMComparisonLeftData.gpuName}`); 148 } 149 ); 150 break; 151 case 'sizeDelta': 152 this.gpuMemoryClickTable!.recycleDataSource = array.sort( 153 (gpuMComparisonLeftData, gpuMComparisonRightData) => { 154 return sort === 1 155 ? gpuMComparisonLeftData.value - gpuMComparisonRightData.value 156 : gpuMComparisonRightData.value - gpuMComparisonLeftData.value; 157 } 158 ); 159 break; 160 } 161 break; 162 } 163 } 164 165 initHtml(): string { 166 return ` 167<style> 168.gpuMemoryClickTable{ 169 height: auto; 170} 171:host{ 172 display: flex; 173 flex-direction: column; 174 padding: 10px 10px; 175} 176</style> 177<lit-table id="gpuMemoryClickTable" class="gpuMemoryClickTable"> 178 <lit-table-column order title="Process" data-index="process" key="process" align="flex-start" width="1fr" > 179 </lit-table-column> 180 <lit-table-column order title="GpuName" data-index="gpuName" key="gpuName" align="flex-start" width="1fr" > 181 </lit-table-column> 182 <lit-table-column order title="SizeDelta" data-index="sizes" key="sizeDelta" align="flex-start" width="1fr" > 183 </lit-table-column> 184</lit-table> 185<tab-pane-js-memory-filter id="filter" first hideFilter ></tab-pane-js-memory-filter> 186 `; 187 } 188} 189