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 { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; 18import { SelectionParam } from '../../../../bean/BoxSelection'; 19import { Utils } from '../../base/Utils'; 20import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar'; 21import { TabPaneFilter } from '../TabPaneFilter'; 22import '../TabPaneFilter'; 23import { VM_TYPE_MAP } from '../../../../database/logic-worker/ProcedureLogicWorkerFileSystem'; 24import { getTabPaneVirtualMemoryStatisticsData } from '../../../../database/sql/Memory.sql'; 25 26@element('tabpane-virtual-memory-statistics') 27export class TabPaneVirtualMemoryStatistics extends BaseElement { 28 private vmStatisticsTbl: LitTable | null | undefined; 29 private vmStatisticsSelectionParam: SelectionParam | null | undefined; 30 private vmStatisticsProgressEL: LitProgressBar | null | undefined; 31 private vmStatisticsFilter: TabPaneFilter | null | undefined; 32 private loadingPage: unknown; 33 private loadingList: number[] = []; 34 private vmStatisticsSource: Array<unknown> = []; 35 private vmStatisticsSortKey: string = ''; 36 private vmStatisticsSortType: number = 0; 37 private vmStatisticsResultData: Array<unknown> = []; 38 39 set data(vmStatisticsSelection: SelectionParam | unknown) { 40 if (vmStatisticsSelection === this.vmStatisticsSelectionParam) { 41 return; 42 } 43 this.vmStatisticsProgressEL!.loading = true; 44 // @ts-ignore 45 this.loadingPage.style.visibility = 'visible'; 46 // @ts-ignore 47 this.vmStatisticsSelectionParam = vmStatisticsSelection; 48 // @ts-ignore 49 this.vmStatisticsTbl!.shadowRoot!.querySelector('.table').style.height = `${this.parentElement!.clientHeight - 20 50 }px`; 51 this.queryDataByDB(vmStatisticsSelection); 52 } 53 54 initElements(): void { 55 this.vmStatisticsProgressEL = this.shadowRoot!.querySelector<LitProgressBar>('.progress'); 56 this.loadingPage = this.shadowRoot!.querySelector('.loading'); 57 this.vmStatisticsTbl = this.shadowRoot!.querySelector<LitTable>('#tb-vm-statistics'); 58 this.vmStatisticsTbl!.addEventListener('column-click', (evt) => { 59 // @ts-ignore 60 this.vmStatisticsSortKey = evt.detail.key; 61 // @ts-ignore 62 this.vmStatisticsSortType = evt.detail.sort; 63 if (this.vmStatisticsSortType !== 0 && this.vmStatisticsSource.length > 0) { 64 this.sortVmStatisticsTable(this.vmStatisticsSource[0], this.vmStatisticsSortKey); 65 } 66 this.vmStatisticsTbl!.recycleDataSource = this.vmStatisticsSource; 67 }); 68 this.vmStatisticsFilter = this.shadowRoot!.querySelector<TabPaneFilter>('#filter'); 69 this.vmStatisticsFilter!.getStatisticsTypeData((type) => { 70 if (type === 'operation') { 71 this.sortStatus(this.vmStatisticsResultData, 'ipid', 'itid'); 72 } else { 73 this.sortStatus(this.vmStatisticsResultData, 'type', 'ipid'); 74 } 75 const labels = this.vmStatisticsTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label') as NodeListOf<HTMLLabelElement>; 76 labels.forEach((label, index) => { 77 if (type === 'operation') { 78 switch (index) { 79 case 0: 80 label.textContent = 'Process'; 81 break; 82 case 1: 83 label.textContent = '/Thread'; 84 break; 85 case 2: 86 label.textContent = '/Operation'; 87 break; 88 } 89 } else { 90 switch (index) { 91 case 0: 92 label.textContent = 'Operation'; 93 break; 94 case 1: 95 label.textContent = '/Process'; 96 break; 97 case 2: 98 label.textContent = '/Thread'; 99 break; 100 } 101 } 102 }); 103 }); 104 } 105 106 connectedCallback(): void { 107 super.connectedCallback(); 108 new ResizeObserver((): void => { 109 if (this.parentElement!.clientHeight !== 0) { 110 // @ts-ignore 111 this.vmStatisticsTbl!.shadowRoot!.querySelector('.table').style.height = `${this.parentElement!.clientHeight - 10 - 32 112 }px`; 113 this.vmStatisticsTbl!.reMeauseHeight(); 114 // @ts-ignore 115 this.loadingPage.style.height = `${this.parentElement!.clientHeight - 24}px`; 116 } 117 }).observe(this.parentElement!); 118 } 119 120 getInitData(initVmMemoryStatItem: unknown, nameTitle: unknown = 'pname', subtitle: unknown = null): unknown { 121 // @ts-ignore 122 let title = nameTitle === 'type' ? VM_TYPE_MAP[initVmMemoryStatItem[nameTitle]] : initVmMemoryStatItem[nameTitle]; 123 return { 124 // @ts-ignore 125 ...initVmMemoryStatItem, 126 // @ts-ignore 127 title: title + (subtitle ? `(${initVmMemoryStatItem[subtitle]})` : ''), 128 // @ts-ignore 129 allDuration: Utils.getProbablyTime(initVmMemoryStatItem.allDuration), 130 // @ts-ignore 131 minDuration: Utils.getProbablyTime(initVmMemoryStatItem.minDuration), 132 // @ts-ignore 133 maxDuration: Utils.getProbablyTime(initVmMemoryStatItem.maxDuration), 134 // @ts-ignore 135 avgDuration: Utils.getProbablyTime(initVmMemoryStatItem.avgDuration), 136 // @ts-ignore 137 node: { ...initVmMemoryStatItem, children: [] }, 138 }; 139 } 140 141 queryDataByDB(vmMemoryStatParam: SelectionParam | unknown): void { 142 this.loadingList.push(1); 143 this.vmStatisticsProgressEL!.loading = true; 144 // @ts-ignore 145 this.loadingPage.style.visibility = 'visible'; 146 getTabPaneVirtualMemoryStatisticsData( 147 // @ts-ignore 148 vmMemoryStatParam.leftNs + vmMemoryStatParam.recordStartNs, 149 // @ts-ignore 150 vmMemoryStatParam.rightNs + vmMemoryStatParam.recordStartNs 151 ).then((result) => { 152 this.loadingList.splice(0, 1); 153 if (this.loadingList.length === 0) { 154 this.vmStatisticsProgressEL!.loading = false; 155 // @ts-ignore 156 this.loadingPage.style.visibility = 'hidden'; 157 } 158 this.vmStatisticsResultData = JSON.parse(JSON.stringify(result)); 159 this.sortStatus(result, 'type', 'ipid'); 160 }); 161 } 162 163 sortStatus(result: Array<unknown>, firstLevel: string, secondLevel: string): void { 164 let vmMemoryStatFatherMap = new Map<unknown, unknown>(); 165 let vmMemoryStatChildMap = new Map<unknown, unknown>(); 166 let vmMemoryStatAllNode: unknown = { 167 title: 'All', 168 count: 0, 169 allDuration: 0, 170 minDuration: 0, 171 maxDuration: 0, 172 avgDuration: '', 173 children: [], 174 }; 175 result.forEach((item, idx) => { 176 this.processChildMap(vmMemoryStatChildMap, item, firstLevel, secondLevel); 177 this.processFatherMap(vmMemoryStatFatherMap, item, firstLevel); 178 if (idx === 0) { 179 // @ts-ignore 180 vmMemoryStatAllNode.minDuration = item.minDuration; 181 } else { 182 // @ts-ignore 183 vmMemoryStatAllNode.minDuration = 184 // @ts-ignore 185 vmMemoryStatAllNode.minDuration <= item.minDuration ? vmMemoryStatAllNode.minDuration : item.minDuration; 186 } 187 // @ts-ignore 188 vmMemoryStatAllNode.count += item.count; 189 // @ts-ignore 190 vmMemoryStatAllNode.allDuration += item.allDuration; 191 // @ts-ignore 192 vmMemoryStatAllNode.maxDuration = 193 // @ts-ignore 194 vmMemoryStatAllNode.maxDuration >= item.maxDuration ? vmMemoryStatAllNode.maxDuration : item.maxDuration; 195 }); 196 this.handleFatherMap(vmMemoryStatFatherMap, firstLevel, vmMemoryStatChildMap, vmMemoryStatAllNode); 197 198 // @ts-ignore 199 vmMemoryStatAllNode.avgDuration = vmMemoryStatAllNode.allDuration / vmMemoryStatAllNode.count; 200 vmMemoryStatAllNode = this.getInitData(vmMemoryStatAllNode); 201 // @ts-ignore 202 vmMemoryStatAllNode.title = 'All'; 203 // @ts-ignore 204 vmMemoryStatAllNode.path = { type: null, tid: null, pid: null, value: 'All' }; 205 this.vmStatisticsSource = result.length > 0 ? [vmMemoryStatAllNode] : []; 206 if (this.vmStatisticsSortType !== 0 && result.length > 0) { 207 this.sortVmStatisticsTable(this.vmStatisticsSource[0], this.vmStatisticsSortKey); 208 } 209 this.theadClick(this.vmStatisticsSource); 210 this.vmStatisticsTbl!.recycleDataSource = this.vmStatisticsSource; 211 } 212 private theadClick(res: Array<unknown>): void { 213 let labels = this.vmStatisticsTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); 214 if (labels) { 215 for (let i = 0; i < labels.length; i++) { 216 let label = labels[i].innerHTML; 217 labels[i].addEventListener('click', (): void => { 218 if (i === 0) { 219 this.vmStatisticsTbl!.setStatus(res, false, 0, 1); 220 this.vmStatisticsTbl!.recycleDs = this.vmStatisticsTbl!.meauseTreeRowElement(res, RedrawTreeForm.Retract); 221 } else if (i === 1) { 222 this.vmStatisticsTbl!.setStatus(res, false, 0, 2); 223 this.vmStatisticsTbl!.recycleDs = this.vmStatisticsTbl!.meauseTreeRowElement(res, RedrawTreeForm.Retract); 224 } else if (i === 2) { 225 this.vmStatisticsTbl!.setStatus(res, true); 226 this.vmStatisticsTbl!.recycleDs = this.vmStatisticsTbl!.meauseTreeRowElement(res, RedrawTreeForm.Expand); 227 } 228 }); 229 } 230 } 231 } 232 private handleFatherMap( 233 vmMemoryStatFatherMap: Map<unknown, unknown>, 234 firstLevel: string, 235 vmMemoryStatChildMap: Map<unknown, unknown>, 236 vmMemoryStatAllNode: unknown 237 ): void { 238 for (let ks of vmMemoryStatFatherMap.keys()) { 239 let sp = vmMemoryStatFatherMap.get(ks); 240 // @ts-ignore 241 sp!.children = []; 242 // @ts-ignore 243 sp.avgDuration = sp.allDuration / sp.count; 244 let vmMemoryStatNode = this.getInitData( 245 sp, 246 firstLevel === 'type' ? 'type' : 'pname', 247 firstLevel === 'type' ? null : 'pid' 248 ); 249 // @ts-ignore 250 vmMemoryStatNode.path = { type: null, tid: null, pid: null, value: vmMemoryStatNode.title }; 251 // @ts-ignore 252 vmMemoryStatNode.path[firstLevel === 'type' ? 'type' : 'pid'] = 253 // @ts-ignore 254 vmMemoryStatNode[firstLevel === 'type' ? 'type' : 'pid']; 255 this.handleChildMap(vmMemoryStatChildMap, ks, firstLevel, vmMemoryStatNode, sp); 256 // @ts-ignore 257 vmMemoryStatAllNode.children.push(vmMemoryStatNode); 258 } 259 } 260 261 private handleChildMap( 262 vmMemoryStatChildMap: Map<unknown, unknown>, 263 ks: unknown, 264 firstLevel: string, 265 vmMemoryStatNode: unknown, 266 sp: unknown 267 ): void { 268 for (let kst of vmMemoryStatChildMap.keys()) { 269 // @ts-ignore 270 if (kst.startsWith(`${ks}_`)) { 271 let spt = vmMemoryStatChildMap.get(kst); 272 let data = this.getInitData( 273 spt!, 274 firstLevel === 'type' ? 'pname' : 'tname', 275 firstLevel === 'type' ? 'pid' : 'tid' 276 ); 277 this.handleData(data, vmMemoryStatNode, firstLevel); 278 // @ts-ignore 279 sp!.children.push(data); 280 } 281 } 282 } 283 284 private handleData(data: unknown, vmMemoryStatNode: unknown, firstLevel: string): void { 285 // @ts-ignore 286 data.path = { 287 type: null, 288 tid: null, 289 pid: null, 290 // @ts-ignore 291 value: `All-${vmMemoryStatNode.title}-${data.title}`, 292 }; 293 // @ts-ignore 294 data.path[firstLevel === 'type' ? 'type' : 'pid'] = vmMemoryStatNode[firstLevel === 'type' ? 'type' : 'pid']; 295 // @ts-ignore 296 data.path[firstLevel === 'type' ? 'pid' : 'tid'] = data[firstLevel === 'type' ? 'pid' : 'tid']; 297 // @ts-ignore 298 data.children.forEach((e: unknown) => { 299 // @ts-ignore 300 e.path = { 301 type: null, 302 tid: null, 303 pid: null, 304 // @ts-ignore 305 value: `All-${vmMemoryStatNode.title}-${data.title}-${e.title}`, 306 }; 307 // @ts-ignore 308 e.path[firstLevel === 'type' ? 'type' : 'pid'] = vmMemoryStatNode[firstLevel === 'type' ? 'type' : 'pid']; 309 // @ts-ignore 310 e.path[firstLevel === 'type' ? 'pid' : 'tid'] = data[firstLevel === 'type' ? 'pid' : 'tid']; 311 // @ts-ignore 312 e.path[firstLevel === 'type' ? 'tid' : 'type'] = e[firstLevel === 'type' ? 'tid' : 'type']; 313 }); 314 } 315 316 private processFatherMap(vmMemoryStatFatherMap: Map<unknown, unknown>, item: unknown, firstLevel: string): void { 317 // @ts-ignore 318 if (vmMemoryStatFatherMap.has(item[firstLevel])) { 319 // @ts-ignore 320 let vmMemoryStatFatherObj = vmMemoryStatFatherMap.get(item[firstLevel]); 321 // @ts-ignore 322 vmMemoryStatFatherObj.count += item.count; 323 // @ts-ignore 324 vmMemoryStatFatherObj.allDuration += item.allDuration; 325 // @ts-ignore 326 vmMemoryStatFatherObj.minDuration = 327 // @ts-ignore 328 vmMemoryStatFatherObj.minDuration <= item.minDuration ? vmMemoryStatFatherObj.minDuration : item.minDuration; 329 // @ts-ignore 330 vmMemoryStatFatherObj.maxDuration = 331 // @ts-ignore 332 vmMemoryStatFatherObj.maxDuration >= item.maxDuration ? vmMemoryStatFatherObj.maxDuration : item.maxDuration; 333 // @ts-ignore 334 vmMemoryStatFatherObj.children.push(this.getInitData(item)); 335 } else { 336 // @ts-ignore 337 vmMemoryStatFatherMap.set(item[firstLevel], { 338 // @ts-ignore 339 ...item, 340 children: [this.getInitData(item)], 341 }); 342 } 343 } 344 345 private processChildMap( 346 vmMemoryStatChildMap: Map<unknown, unknown>, 347 item: unknown, 348 firstLevel: string, 349 secondLevel: string 350 ): void { 351 // @ts-ignore 352 if (vmMemoryStatChildMap.has(`${item[firstLevel]}_${item[secondLevel]}`)) { 353 // @ts-ignore 354 let vmMemoryStatChildObj = vmMemoryStatChildMap.get(`${item[firstLevel]}_${item[secondLevel]}`); 355 // @ts-ignore 356 vmMemoryStatChildObj.count += item.count; 357 // @ts-ignore 358 vmMemoryStatChildObj.allDuration += item.allDuration; 359 // @ts-ignore 360 vmMemoryStatChildObj.minDuration = 361 // @ts-ignore 362 vmMemoryStatChildObj.minDuration <= item.minDuration ? vmMemoryStatChildObj.minDuration : item.minDuration; 363 // @ts-ignore 364 vmMemoryStatChildObj.maxDuration = 365 // @ts-ignore 366 vmMemoryStatChildObj.maxDuration >= item.maxDuration ? vmMemoryStatChildObj.maxDuration : item.maxDuration; 367 // @ts-ignore 368 vmMemoryStatChildObj.children.push( 369 this.getInitData(item, firstLevel === 'type' ? 'tname' : 'type', firstLevel === 'type' ? 'tid' : null) 370 ); 371 } else { 372 // @ts-ignore 373 vmMemoryStatChildMap.set(`${item[firstLevel]}_${item[secondLevel]}`, { 374 // @ts-ignore 375 ...item, 376 children: [ 377 this.getInitData(item, firstLevel === 'type' ? 'tname' : 'type', firstLevel === 'type' ? 'tid' : null), 378 ], 379 }); 380 } 381 } 382 383 sortVmStatisticsTable(allNode: unknown, key: string): void { 384 // @ts-ignore 385 allNode.children.sort((vmStatNodeA: unknown, vmStatNodeB: unknown) => { 386 // @ts-ignore 387 return this.vmStatisticsSortType === 1 ? vmStatNodeA.node[key] - vmStatNodeB.node[key] : vmStatNodeB.node[key] - vmStatNodeA.node[key]; 388 }); 389 // @ts-ignore 390 allNode.children.forEach((item: unknown): void => { 391 // @ts-ignore 392 item.children.sort((vmStatNodeA: unknown, vmStatNodeB: unknown) => { 393 let backData; 394 if (this.vmStatisticsSortType === 1) { 395 // @ts-ignore 396 backData = vmStatNodeA.node[key] - vmStatNodeB.node[key]; 397 } else if (this.vmStatisticsSortType === 2) { 398 // @ts-ignore 399 backData = vmStatNodeB.node[key] - vmStatNodeA.node[key]; 400 } 401 return backData; 402 }); 403 // @ts-ignore 404 item.children.forEach((vmStatItem: unknown) => { 405 // @ts-ignore 406 vmStatItem.children.sort((vmStatItemA: unknown, vmStatItemB: unknown) => { 407 let backData; 408 if (this.vmStatisticsSortType === 1) { 409 // @ts-ignore 410 backData = vmStatItemA.node[key] - vmStatItemB.node[key]; 411 } else if (this.vmStatisticsSortType === 2) { 412 // @ts-ignore 413 backData = vmStatItemB.node[key] - vmStatItemA.node[key]; 414 } 415 return backData; 416 }); 417 }); 418 }); 419 } 420 421 initHtml(): string { 422 return ` 423 <style> 424 .vm-stat-progress{ 425 bottom: 5px; 426 position: absolute; 427 height: 1px; 428 left: 0; 429 right: 0; 430 } 431 :host{ 432 display: flex; 433 flex-direction: column; 434 padding: 10px 10px 0 10px; 435 } 436 .vm-stat-loading{ 437 bottom: 0; 438 position: absolute; 439 left: 0; 440 right: 0; 441 width:100%; 442 background:transparent; 443 z-index: 999999; 444 } 445 </style> 446 <lit-table id="tb-vm-statistics" style="height: auto" tree> 447 <lit-table-column class="vm-memory-stat-column" width="20%" title="Operation/Process/Thread" data-index="title" key="title" align="flex-start"retract> 448 </lit-table-column> 449 <lit-table-column class="vm-memory-stat-column" width="1fr" title="Count" data-index="count" key="count" align="flex-start" order> 450 </lit-table-column> 451 <lit-table-column class="vm-memory-stat-column" width="1fr" title="Duration" data-index="allDuration" key="allDuration" align="flex-start" order> 452 </lit-table-column> 453 <lit-table-column class="vm-memory-stat-column" width="1fr" title="Min Duration" data-index="minDuration" key="minDuration" align="flex-start" order> 454 </lit-table-column> 455 <lit-table-column class="vm-memory-stat-column" width="1fr" title="Avg Duration" data-index="avgDuration" key="avgDuration" align="flex-start" order> 456 </lit-table-column> 457 <lit-table-column class="vm-memory-stat-column" width="1fr" title="Max Duration" data-index="maxDuration" key="maxDuration" align="flex-start" order> 458 </lit-table-column> 459 </lit-table> 460 <lit-progress-bar class="progress vm-stat-progress"></lit-progress-bar> 461 <tab-pane-filter id="filter" sort></tab-pane-filter> 462 <div class="loading vm-stat-loading"></div> 463 `; 464 } 465} 466