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'; 16import { RedrawTreeForm, type LitTable } from '../../../../../base-ui/table/lit-table'; 17import { resizeObserver } from '../SheetUtils'; 18import { VmTrackerChart } from '../../../chart/SpVmTrackerChart'; 19import { log } from '../../../../../log/Log'; 20import { SpSystemTrace } from '../../../SpSystemTrace'; 21import { Utils } from '../../base/Utils'; 22import {queryGpuDataByTs} from "../../../../database/sql/Gpu.sql"; 23interface GpuTreeItem { 24 name: string; 25 id: number; 26 size: number; 27 sizeStr: string; 28 children?: GpuTreeItem[] | undefined; 29} 30@element('tabpane-gpu-click-select') 31export class TabPaneGpuClickSelect extends BaseElement { 32 private gpuTbl: LitTable | null | undefined; 33 private gpuSource: Array<GpuTreeItem> = []; 34 gpuClickData(gpu: { type: string; startTs: number }) { 35 let td = this.gpuTbl!.shadowRoot!.querySelector('.thead')?.firstChild?.firstChild as HTMLDivElement; 36 let title = gpu.type === 'total' ? 'Module / Category' : 'Window / Module / Category'; 37 let titleArr = title.split('/'); 38 if (td) { 39 let labelEls = td.querySelectorAll('label'); 40 if (labelEls) { 41 for (let el of labelEls) { 42 td.removeChild(el); 43 } 44 } 45 for (let i = 0; i < titleArr.length; i++) { 46 let label = document.createElement('label'); 47 label.style.cursor = 'pointer'; 48 i == 0 ? (label.innerHTML = titleArr[i]) : (label.innerHTML = '/' + titleArr[i]); 49 td.appendChild(label); 50 } 51 } 52 //@ts-ignore 53 this.gpuTbl?.shadowRoot?.querySelector('.table')?.style?.height = this.parentElement!.clientHeight - 45 + 'px'; 54 this.gpuTbl!.loading = true; 55 let window = gpu.type === 'total' ? 0 : VmTrackerChart.gpuWindow; 56 let module = gpu.type === 'total' ? VmTrackerChart.gpuTotalModule : VmTrackerChart.gpuWindowModule; 57 queryGpuDataByTs(gpu.startTs, window || 0, module).then((result) => { 58 this.gpuTbl!.loading = false; 59 if (result != null && result.length > 0) { 60 log('queryGpuDataByTs result size : ' + result.length); 61 let items = this.createTreeData(result); 62 this.gpuSource = (gpu.type === 'total' ? items[0].children : items) || []; 63 this.gpuTbl!.recycleDataSource = this.gpuSource; 64 this.theadClick(this.gpuTbl!, this.gpuSource); 65 } else { 66 this.gpuSource = []; 67 this.gpuTbl!.recycleDataSource = []; 68 } 69 }); 70 } 71 protected createTreeData(result: any): Array<any> { 72 let gpuDataObj = result.reduce((group: any, 73 item: { categoryId: number; size: number; windowNameId: number; moduleId: number; windowId: any } 74 ) => { 75 let categoryItem: GpuTreeItem = { 76 name: SpSystemTrace.DATA_DICT.get(item.categoryId) || 'null', 77 id: item.categoryId, 78 size: item.size, 79 sizeStr: Utils.getBinaryByteWithUnit(item.size), 80 }; 81 if (group[`${item.windowNameId}(${item.windowId})`]) { 82 let windowGroup = group[`${item.windowNameId}(${item.windowId})`] as GpuTreeItem; 83 windowGroup.size += item.size; 84 windowGroup.sizeStr = Utils.getBinaryByteWithUnit(windowGroup.size); 85 let moduleGroup = windowGroup.children!.find((it) => it.id === item.moduleId); 86 if (moduleGroup) { 87 moduleGroup.size += item.size; 88 moduleGroup.sizeStr = Utils.getBinaryByteWithUnit(moduleGroup.size); 89 moduleGroup.children?.push(categoryItem); 90 } else { 91 windowGroup.children?.push({ 92 name: SpSystemTrace.DATA_DICT.get(item.moduleId) || 'null', 93 id: item.moduleId, 94 size: item.size, 95 sizeStr: Utils.getBinaryByteWithUnit(item.size), 96 children: [categoryItem], 97 }); 98 } 99 } else { 100 group[`${item.windowNameId}(${item.windowId})`] = { 101 name: SpSystemTrace.DATA_DICT.get(item.windowNameId) + `(${item.windowId})`, 102 id: item.windowNameId, 103 size: item.size, 104 sizeStr: Utils.getBinaryByteWithUnit(item.size), 105 children: [{ 106 name: SpSystemTrace.DATA_DICT.get(item.moduleId), 107 id: item.moduleId, 108 size: item.size, 109 sizeStr: Utils.getBinaryByteWithUnit(item.size), 110 children: [categoryItem], 111 }], 112 }; 113 } 114 return group; 115 },{} 116 ); 117 return Object.values(gpuDataObj) as GpuTreeItem[]; 118 } 119 initElements(): void { 120 this.gpuTbl = this.shadowRoot?.querySelector<LitTable>('#tb-gpu'); 121 this.gpuTbl!.addEventListener('column-click', (evt: any) => { 122 this.sortByColumn(evt.detail); 123 }); 124 } 125 connectedCallback(): void { 126 super.connectedCallback(); 127 this.parentElement!.style.overflow = 'hidden'; 128 resizeObserver(this.parentElement!, this.gpuTbl!, 18); 129 } 130 public theadClick(table: LitTable, data: Array<any>) { 131 let labels = table?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); 132 if (labels) { 133 for (let i = 0; i < labels.length; i++) { 134 let label = labels[i].innerHTML; 135 labels[i].addEventListener('click', (e) => { 136 if ((label.includes('Window') && i === 0) || (label.includes('Module') && i === 0)) { 137 table!.setStatus(data, false); 138 table!.recycleDs = table!.meauseTreeRowElement(data, RedrawTreeForm.Retract); 139 } else if (label.includes('Module') && i === 1) { 140 for (let item of data) { 141 item.status = true; 142 if (item.children != undefined && item.children.length > 0) { 143 table!.setStatus(item.children, false); 144 } 145 } 146 table!.recycleDs = table!.meauseTreeRowElement(data, RedrawTreeForm.Retract); 147 } else if ((label.includes('Category') && i === 2) || (label.includes('Category') && i === 1)) { 148 table!.setStatus(data, true); 149 table!.recycleDs = table!.meauseTreeRowElement(data, RedrawTreeForm.Expand); 150 } 151 e.stopPropagation(); 152 }); 153 } 154 } 155 } 156 initHtml(): string { 157 return ` 158 <style> 159 :host{ 160 display: flex; 161 flex-direction: column; 162 padding: 10px 10px; 163 } 164 </style> 165 <lit-table id="tb-gpu" style="height: auto" tree> 166 <lit-table-column width="50%" title="" data-index="name" key="name" align="flex-start" order retract> 167 </lit-table-column> 168 <lit-table-column width="1fr" title="Size" data-index="sizeStr" key="sizeStr" align="flex-start" order> 169 </lit-table-column> 170 </lit-table> 171 `; 172 } 173 sortByColumn(gpuDetail: any): void { 174 let compare = (gpuA: GpuTreeItem, gpuB: GpuTreeItem): number => { 175 if (gpuDetail.sort === 0) { 176 return gpuA.size - gpuB.size; 177 } else if (gpuDetail.sort === 1) { 178 return gpuA.size - gpuB.size; 179 } else { 180 return gpuB.size - gpuA.size; 181 } 182 }; 183 let deepCompare = (arr: GpuTreeItem[]): void => { 184 arr.forEach((it) => { 185 if (it.children) { 186 deepCompare(it.children); 187 } 188 }); 189 arr.sort(compare); 190 }; 191 deepCompare(this.gpuSource); 192 this.gpuTbl!.recycleDataSource = this.gpuSource; 193 } 194} 195