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 { LitTable } from '../../../../../base-ui/table/lit-table'; 17import { SelectionParam } from '../../../../bean/BoxSelection'; 18import { LitChartPie } from '../../../../../base-ui/chart/pie/LitChartPie'; 19import '../../../../../base-ui/chart/pie/LitChartPie'; 20import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar'; 21import { Utils } from '../../base/Utils'; 22import { SpSystemTrace } from '../../../SpSystemTrace'; 23import { procedurePool } from '../../../../database/Procedure'; 24import { TabPaneFilter } from '../TabPaneFilter'; 25import { LitCheckBox } from '../../../../../base-ui/checkbox/LitCheckBox'; 26import { initSort } from '../SheetUtils'; 27import { TabpaneNMCalltree } from './TabPaneNMCallTree'; 28import { FilterByAnalysis } from '../../../../bean/NativeHook'; 29import { InitAnalysis } from '../../../../database/logic-worker/ProcedureLogicWorkerCommon'; 30import { TabPaneNMStatisticAnalysisHtml } from './TabPaneNMStatisticAnalysis.html'; 31 32const TYPE_ALLOC_STRING = 'AllocEvent'; 33const TYPE_MAP_STRING = 'MmapEvent'; 34const TYPE_OTHER_MMAP = 'Other MmapEvent'; 35 36const TYPE_ALLOC = 0; 37const TYPE_MAP = 1; 38const TYPE_FREE = 2; 39const TYPE_UN_MAP = 3; 40const PIE_CHART_LIMIT = 20; 41 42class AnalysisObj { 43 tName?: string; 44 tid?: number; 45 typeName?: string; 46 typeId?: number; 47 libName?: string; 48 libId?: number; 49 symbolName?: string; 50 symbolId?: number; 51 52 tableName = ''; 53 54 applySize: number; 55 applySizeFormat: string; 56 applyCount: number; 57 releaseSize: number; 58 releaseSizeFormat: string; 59 releaseCount: number; 60 existSize: number; 61 existSizeFormat: string; 62 existCount: number; 63 64 applySizePercent?: string; 65 applyCountPercent?: string; 66 releaseSizePercent?: string; 67 releaseCountPercent?: string; 68 existSizePercent?: string; 69 existCountPercent?: string; 70 71 constructor(applySize: number, applyCount: number, releaseSize: number, releaseCount: number) { 72 this.applySize = applySize; 73 this.applyCount = applyCount; 74 this.releaseSize = releaseSize; 75 this.releaseCount = releaseCount; 76 this.existSize = applySize - releaseSize; 77 this.existCount = applyCount - releaseCount; 78 this.applySizeFormat = Utils.getBinaryByteWithUnit(this.applySize); 79 this.releaseSizeFormat = Utils.getBinaryByteWithUnit(this.releaseSize); 80 this.existSizeFormat = Utils.getBinaryByteWithUnit(this.existSize); 81 } 82} 83 84class SizeObj { 85 applySize = 0; 86 applyCount = 0; 87 releaseSize = 0; 88 releaseCount = 0; 89} 90 91@element('tabpane-nm-statistic-analysis') 92export class TabPaneNMStatisticAnalysis extends BaseElement { 93 private currentSelection: SelectionParam | unknown; 94 private nmPieChart: LitChartPie | null | undefined; 95 private nmTableBox: HTMLDivElement | undefined | null; 96 private processData!: Array<unknown>; 97 private eventTypeData!: Array<AnalysisObj>; 98 private threadData!: Array<AnalysisObj>; 99 private soData!: Array<AnalysisObj>; 100 private functionData!: Array<AnalysisObj>; 101 private typeUsageTbl: LitTable | null | undefined; 102 private threadUsageTbl: LitTable | null | undefined; 103 private soUsageTbl: LitTable | null | undefined; 104 private functionUsageTbl: LitTable | null | undefined; 105 private range: HTMLLabelElement | null | undefined; 106 private nmBack: HTMLDivElement | null | undefined; 107 private threadName: string = ''; 108 private tabName: HTMLDivElement | null | undefined; 109 private progressEL: LitProgressBar | null | undefined; 110 private type: string = ''; 111 private isStatistic = false; 112 private typeMap!: Map<number, Array<unknown>>; 113 private currentLevel = -1; 114 private currentLevelApplySize = 0; 115 private currentLevelReleaseSize = 0; 116 private currentLevelExistSize = 0; 117 private currentLevelApplyCount = 0; 118 private currentLevelReleaseCount = 0; 119 private currentLevelExistCount = 0; 120 private currentLevelData!: Array<unknown>; 121 private typeStatisticsData!: {}; 122 private threadStatisticsData!: {}; 123 private libStatisticsData!: {}; 124 private functionStatisticsData!: {}; 125 private nmTableArray: NodeListOf<LitTable> | undefined | null; 126 private nmSortColumn: string = ''; 127 private nmSortType: number = 0; 128 private titleEl: HTMLDivElement | undefined | null; 129 private filterEl: TabPaneFilter | undefined | null; 130 private hideThreadCheckBox: LitCheckBox | undefined | null; 131 132 get titleTxt(): string | null { 133 return this.titleEl!.textContent; 134 } 135 136 set data(statisticAnalysisParam: SelectionParam) { 137 if (statisticAnalysisParam === this.currentSelection) { 138 if (this.eventTypeData) { 139 // @ts-ignore 140 this.eventTypeData.unshift(this.typeStatisticsData); 141 this.typeUsageTbl!.recycleDataSource = this.eventTypeData; 142 // @ts-ignore 143 this.eventTypeData.shift(this.typeStatisticsData); 144 } 145 return; 146 } 147 if (this.nmTableArray) { 148 for (let table of this.nmTableArray) { 149 initSort(table!, this.nmSortColumn, this.nmSortType); 150 } 151 } 152 this.hideThreadCheckBox!.checked = false; 153 if (statisticAnalysisParam.nativeMemoryStatistic.length > 0) { 154 Utils.getInstance().setCurrentSelectIPid(statisticAnalysisParam.nativeMemoryCurrentIPid); 155 Utils.getInstance().initResponseTypeList(statisticAnalysisParam); 156 } 157 this.resizeTable(); 158 this.reset(this.typeUsageTbl!, false); 159 this.currentSelection = statisticAnalysisParam; 160 this.titleEl!.textContent = ''; 161 this.tabName!.textContent = ''; 162 this.range!.textContent = `Selected range: ${parseFloat( 163 ((statisticAnalysisParam.rightNs - statisticAnalysisParam.leftNs) / 1000000.0).toFixed(5) 164 )} ms`; 165 this.isStatistic = statisticAnalysisParam.nativeMemory.length === 0; 166 if (this.isStatistic) { 167 this.threadName = ''; 168 } 169 this.getNMEventTypeSize(statisticAnalysisParam); 170 this.showAssignLevel(this.typeUsageTbl!, this.functionUsageTbl!, 0, this.eventTypeData); 171 } 172 173 initNmTableArray(): void { 174 this.nmTableArray = this.shadowRoot!.querySelectorAll('lit-table') as NodeListOf<LitTable>; 175 for (let nmTable of this.nmTableArray) { 176 nmTable!.addEventListener('contextmenu', function (event) { 177 event.preventDefault(); // 阻止默认的上下文菜单弹框 178 }); 179 nmTable!.addEventListener('column-click', (evt) => { 180 // @ts-ignore 181 this.nmSortColumn = evt.detail.key; 182 // @ts-ignore 183 this.nmSortType = evt.detail.sort; 184 this.sortByColumn(); 185 }); 186 nmTable!.addEventListener('row-hover', (evt) => { 187 // @ts-ignore 188 let detail = evt.detail; 189 if (detail.data) { 190 let data = detail.data; 191 data.isHover = true; 192 if (detail.callBack) { 193 detail.callBack(true); 194 } 195 } 196 this.nmPieChart?.showHover(); 197 this.nmPieChart?.hideTip(); 198 }); 199 } 200 this.threadUsageTbl!.addEventListener('row-click', (evt) => { 201 // @ts-ignore 202 let button = evt.detail.button; 203 // @ts-ignore 204 let data = evt.detail.data; 205 if (button === 0) { 206 if (data.tableName !== '' && data.existSize !== 0) { 207 this.nativeThreadLevelClickEvent(data); 208 } 209 } else if (button === 2) { 210 let title = `${this.titleEl!.textContent}/${data.tName}`; 211 this.clickRight(evt, title); 212 } 213 }); 214 } 215 216 initTable(): void { 217 this.typeUsageTbl!.addEventListener('row-click', (evt) => { 218 // @ts-ignore 219 let button = evt.detail.button; 220 // @ts-ignore 221 let data = evt.detail.data; 222 if (button === 0) { 223 if (data.tableName !== '' && data.existSize !== 0) { 224 this.nativeProcessLevelClickEvent(data); 225 } 226 } else if (button === 2) { 227 const typeName = data.typeName === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : data.typeName; 228 this.clickRight(evt, typeName); 229 } 230 }); 231 this.soUsageTbl!.addEventListener('row-click', (evt) => { 232 // @ts-ignore 233 let button = evt.detail.button; 234 // @ts-ignore 235 let data = evt.detail.data; 236 if (button === 0) { 237 if (data.tableName !== '' && data.existSize !== 0) { 238 this.nativeSoLevelClickEvent(data); 239 } 240 } else if (button === 2) { 241 let title = `${this.titleEl!.textContent}/${data.libName}`; 242 this.clickRight(evt, title); 243 } 244 }); 245 } 246 247 initElements(): void { 248 this.range = this.shadowRoot?.querySelector('#time-range'); 249 this.nmPieChart = this.shadowRoot!.querySelector<LitChartPie>('#nm-chart-pie'); 250 this.nmTableBox = this.shadowRoot!.querySelector<HTMLDivElement>('.nm-table-box'); 251 this.typeUsageTbl = this.shadowRoot!.querySelector<LitTable>('#tb-eventtype-usage'); 252 this.threadUsageTbl = this.shadowRoot!.querySelector<LitTable>('#tb-thread-usage'); 253 this.soUsageTbl = this.shadowRoot!.querySelector<LitTable>('#tb-so-usage'); 254 this.functionUsageTbl = this.shadowRoot!.querySelector<LitTable>('#tb-function-usage'); 255 this.nmBack = this.shadowRoot!.querySelector<HTMLDivElement>('.nm-go-back'); 256 this.tabName = this.shadowRoot!.querySelector<HTMLDivElement>('.nm-subheading'); 257 this.progressEL = this.shadowRoot?.querySelector('.nm-progress') as LitProgressBar; 258 this.getBack(); 259 this.titleEl = this.shadowRoot!.querySelector<HTMLDivElement>('.title'); 260 this.filterEl = this.shadowRoot?.querySelector('#filter'); 261 this.filterEl!.setOptionsList(['Hide Thread']); 262 let popover = this.filterEl!.shadowRoot!.querySelector('#check-popover'); 263 this.hideThreadCheckBox = popover!!.querySelector<LitCheckBox>('div > #hideThread'); 264 this.hideThreadCheckBox?.addEventListener('change', () => { 265 this.reset(this.typeUsageTbl!, false); 266 this.showAssignLevel(this.typeUsageTbl!, this.functionUsageTbl!, 0, this.eventTypeData); // @ts-ignore 267 this.getNMTypeSize(this.currentSelection, this.processData); 268 }); 269 this.initNmTableArray(); 270 this.initTable(); 271 this.functionUsageTbl?.addEventListener('row-click', (evt) => { 272 // @ts-ignore 273 let title = `${this.titleEl!.textContent}/${evt.detail.data.symbolName}`; 274 this.clickRight(evt, title); 275 }); 276 let exportHandlerMap = new Map<string, (value: unknown) => string>(); 277 exportHandlerMap.set('existSizeFormat', (value) => { 278 // @ts-ignore 279 return `${value.existSize}`; 280 }); 281 exportHandlerMap.set('applySizeFormat', (value) => { 282 // @ts-ignore 283 return `${value.applySize}`; 284 }); 285 exportHandlerMap.set('releaseSizeFormat', (value) => { 286 // @ts-ignore 287 return `${value.releaseSize}`; 288 }); 289 this.typeUsageTbl!.exportTextHandleMap = exportHandlerMap; 290 this.threadUsageTbl!.exportTextHandleMap = exportHandlerMap; 291 this.soUsageTbl!.exportTextHandleMap = exportHandlerMap; 292 this.functionUsageTbl!.exportTextHandleMap = exportHandlerMap; 293 } 294 295 private clickRight(evt: unknown, title: string): void { 296 // @ts-ignore 297 if (evt.detail.button === 2 && evt.detail.tableName && evt.detail.tableName !== '') { 298 let treeTab = this.parentElement?.parentElement?.querySelector<TabpaneNMCalltree>( 299 '#box-native-calltree > tabpane-nm-calltree' 300 ); 301 treeTab!.analysisTabWidth = this.clientWidth; // @ts-ignore 302 const data = evt.detail.data as AnalysisObj; 303 treeTab!.filterData = new FilterByAnalysis( 304 data.typeId, 305 data.typeName, 306 data.tName, 307 data.tid, 308 data.libId, 309 data.libName, 310 data.symbolId, 311 data.symbolName 312 ); 313 // 首次打开初始化数据 非首次初始化UI 314 if (!InitAnalysis.getInstance().isInitAnalysis) { 315 treeTab?.initUI(); 316 treeTab?.filterByAnalysis(); 317 } else { 318 treeTab!.initFromAnalysis = true; // @ts-ignore 319 treeTab!.data = this.currentSelection; 320 InitAnalysis.getInstance().isInitAnalysis = false; 321 } 322 323 treeTab!.banTypeAndLidSelect(); 324 treeTab!.titleBoxShow = true; 325 treeTab!.titleTxt = title; 326 } 327 } 328 329 private getDataFromWorker(val: SelectionParam, typeFilter: Array<number | string>): void { 330 this.getDataByWorkerQuery( 331 { 332 leftNs: val.leftNs, 333 rightNs: val.rightNs, 334 types: typeFilter, 335 isStatistic: this.isStatistic, 336 }, 337 (results: unknown) => { 338 this.processData = JSON.parse(JSON.stringify(results)); 339 this.getNMTypeSize(val, this.processData); 340 } 341 ); 342 } 343 344 private getDataByWorkerQuery(args: unknown, handler: Function): void { 345 this.progressEL!.loading = true; 346 procedurePool.submitWithName('logic0', 'native-memory-queryAnalysis', args, undefined, (results: unknown) => { 347 handler(results); 348 this.progressEL!.loading = false; 349 }); 350 } 351 352 private reset(showTable: LitTable, isShowBack: boolean): void { 353 this.clearData(); 354 if (isShowBack) { 355 this.nmBack!.style.visibility = 'visible'; 356 } else { 357 this.nmBack!.style.visibility = 'hidden'; 358 } 359 if (this.nmTableArray) { 360 for (let table of this.nmTableArray) { 361 if (table === showTable) { 362 initSort(table, this.nmSortColumn, this.nmSortType); 363 table.style.display = 'grid'; 364 table!.removeAttribute('hideDownload'); 365 } else { 366 table!.style.display = 'none'; 367 table.setAttribute('hideDownload', ''); 368 } 369 } 370 } 371 } 372 373 private clearData(): void { 374 this.nmPieChart!.dataSource = []; 375 this.typeUsageTbl!.recycleDataSource = []; 376 this.threadUsageTbl!.recycleDataSource = []; 377 this.soUsageTbl!.recycleDataSource = []; 378 this.functionUsageTbl!.recycleDataSource = []; 379 } 380 381 private showAssignLevel( 382 showNMTable: LitTable, 383 hideNMTable: LitTable, 384 currentLevel: number, 385 currentLevelData: Array<unknown> 386 ): void { 387 showNMTable!.style.display = 'grid'; 388 hideNMTable!.style.display = 'none'; 389 hideNMTable.setAttribute('hideDownload', ''); 390 showNMTable?.removeAttribute('hideDownload'); 391 this.currentLevel = currentLevel; 392 this.currentLevelData = currentLevelData; 393 } 394 395 private getBack(): void { 396 this.nmBack!.addEventListener('click', () => { 397 if (this.tabName!.textContent === 'Statistic By Thread Existing') { 398 this.showAssignLevel(this.typeUsageTbl!, this.threadUsageTbl!, 0, this.eventTypeData); 399 this.nmBack!.style.visibility = 'hidden'; 400 this.typePieChart(); 401 } else if (this.tabName!.textContent === 'Statistic By Library Existing') { 402 if (this.hideThreadCheckBox?.checked || this.isStatistic) { 403 this.showAssignLevel(this.typeUsageTbl!, this.soUsageTbl!, 0, this.eventTypeData); 404 this.nmBack!.style.visibility = 'hidden'; 405 this.typePieChart(); 406 } else { 407 this.showAssignLevel(this.threadUsageTbl!, this.soUsageTbl!, 1, this.threadData); 408 this.threadPieChart(); 409 } 410 } else if (this.tabName!.textContent === 'Statistic By Function Existing') { 411 this.showAssignLevel(this.soUsageTbl!, this.functionUsageTbl!, 2, this.soData); 412 this.libraryPieChart(); 413 } 414 }); 415 } 416 417 private typePieChart(): void { 418 this.nmPieChart!.config = { 419 appendPadding: 0, 420 data: this.getPieChartData(this.eventTypeData), 421 angleField: 'existSize', 422 colorField: 'tableName', 423 radius: 1, 424 label: { 425 type: 'outer', 426 }, 427 tip: (typeTipValue): string => { 428 // @ts-ignore 429 const obj = typeTipValue.obj as AnalysisObj; 430 return `<div> 431 <div>Memory Type:${obj.tableName}</div> 432 <div>Existing:${obj.existSizeFormat} (${obj.existSizePercent}%)</div> 433 <div># Existing:${obj.existCount} (${obj.existCountPercent}%)</div> 434 <div>Total Bytes:${obj.applySizeFormat} (${obj.applySizePercent}%)</div> 435 <div># Total:${obj.applyCount} (${obj.applyCountPercent}%)</div> 436 <div>Transient:${obj.releaseSizeFormat} (${obj.releaseSizePercent}%)</div> 437 <div># Transient:${obj.releaseCount} (${obj.releaseCountPercent}%)</div> 438 </div>`; 439 }, 440 angleClick: (it): void => { 441 // @ts-ignore 442 if (it.tableName !== 'other') { 443 this.nativeProcessLevelClickEvent(it); 444 } 445 }, 446 hoverHandler: (nmData): void => { 447 if (nmData) { 448 this.typeUsageTbl!.setCurrentHover(nmData); 449 } else { 450 this.typeUsageTbl!.mouseOut(); 451 } 452 }, 453 interactions: [ 454 { 455 type: 'element-active', 456 }, 457 ], 458 }; 459 460 this.titleEl!.textContent = ''; 461 this.tabName!.textContent = 'Statistic By Event Type Existing'; 462 // @ts-ignore 463 this.eventTypeData.unshift(this.typeStatisticsData); 464 this.typeUsageTbl!.recycleDataSource = this.eventTypeData; 465 // @ts-ignore 466 this.eventTypeData.shift(this.typeStatisticsData); 467 this.typeUsageTbl?.reMeauseHeight(); 468 this.currentLevelData = this.eventTypeData; 469 } 470 471 private threadPieChart(): void { 472 this.nmPieChart!.config = { 473 appendPadding: 0, 474 data: this.getPieChartData(this.threadData), 475 angleField: 'existSize', 476 colorField: 'tableName', 477 radius: 1, 478 label: { 479 type: 'outer', 480 }, 481 tip: (threadTipValue): string => { 482 // @ts-ignore 483 const obj = threadTipValue.obj as AnalysisObj; 484 return `<div> 485 <div>Thread:${obj.tableName}</div> 486 <div>Existing:${obj.existSizeFormat} (${obj.existSizePercent}%)</div> 487 <div># Existing:${obj.existCount} (${obj.existCountPercent}%)</div> 488 <div>Total Bytes:${obj.applySizeFormat} (${obj.applySizePercent}%)</div> 489 <div># Total:${obj.applyCount} (${obj.applyCountPercent}%)</div> 490 <div>Transient:${obj.releaseSizeFormat} (${obj.releaseSizePercent}%)</div> 491 <div># Transient:${obj.releaseCount} (${obj.releaseCountPercent}%)</div> 492 </div>`; 493 }, 494 angleClick: (it: unknown): void => { 495 // @ts-ignore 496 if (it.tid !== 'other') { 497 // @ts-ignore 498 this.nativeThreadLevelClickEvent(it); 499 } 500 }, 501 hoverHandler: (data): void => { 502 if (data) { 503 this.threadUsageTbl!.setCurrentHover(data); 504 } else { 505 this.threadUsageTbl!.mouseOut(); 506 } 507 }, 508 interactions: [ 509 { 510 type: 'element-active', 511 }, 512 ], 513 }; 514 const typeName = this.type === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : this.type; 515 this.titleEl!.textContent = typeName + ''; 516 this.tabName!.textContent = 'Statistic By Thread Existing'; 517 // @ts-ignore 518 this.threadData.unshift(this.threadStatisticsData); 519 this.threadUsageTbl!.recycleDataSource = this.threadData; 520 // @ts-ignore 521 this.threadData.shift(this.threadStatisticsData); 522 this.currentLevelData = this.threadData; 523 this.threadUsageTbl?.reMeauseHeight(); 524 } 525 526 private getLibraryTipValue(libraryTipValue: unknown): string { 527 // @ts-ignore 528 const obj = libraryTipValue.obj as AnalysisObj; 529 return `<div> 530 <div>Library:${obj.libName}</div> 531 <div>Existing:${obj.existSizeFormat} 532 (${obj.existSizePercent}%)</div> 533 <div># Existing:${obj.existCount} 534 (${obj.existCountPercent}%)</div> 535 <div>Total Bytes:${obj.applySizeFormat} 536 (${obj.applySizePercent}%)</div> 537 <div># Total:${obj.applyCount} 538 (${obj.applyCountPercent}%)</div> 539 <div>Transient:${obj.releaseSizeFormat} 540 (${obj.releaseSizePercent}%)</div> 541 <div># Transient:${obj.releaseCount} 542 (${obj.releaseCountPercent}%)</div> 543 </div>`; 544 } 545 546 private libraryPieChart(item?: unknown): void { 547 this.nmPieChart!.config = { 548 appendPadding: 0, 549 data: this.getPieChartData(this.soData), 550 angleField: 'existSize', 551 colorField: 'tableName', 552 radius: 1, 553 label: { 554 type: 'outer', 555 }, 556 tip: (libraryTipValue): string => { 557 return this.getLibraryTipValue(libraryTipValue); 558 }, 559 angleClick: (it): void => { 560 // @ts-ignore 561 if (it.tableName !== 'other') { 562 this.nativeSoLevelClickEvent(it); 563 } 564 }, 565 hoverHandler: (data): void => { 566 if (data) { 567 this.soUsageTbl!.setCurrentHover(data); 568 } else { 569 this.soUsageTbl!.mouseOut(); 570 } 571 }, 572 interactions: [ 573 { 574 type: 'element-active', 575 }, 576 ], 577 }; 578 const typeName = this.type === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : this.type; 579 let title = typeName; 580 if (!this.hideThreadCheckBox?.checked && this.threadName.length > 0) { 581 title += ' / ' + this.threadName; 582 } 583 this.titleEl!.textContent = title; 584 this.tabName!.textContent = 'Statistic By Library Existing'; 585 // @ts-ignore 586 this.soData.unshift(this.libStatisticsData); 587 this.soUsageTbl!.recycleDataSource = this.soData; 588 // @ts-ignore 589 this.soData.shift(this.libStatisticsData); 590 this.currentLevelData = this.soData; 591 this.soUsageTbl?.reMeauseHeight(); 592 } 593 594 private functionPieChart(): void { 595 this.nmPieChart!.config = { 596 appendPadding: 0, 597 data: this.getPieChartData(this.functionData), 598 angleField: 'existSize', 599 colorField: 'tableName', 600 radius: 1, 601 label: { 602 type: 'outer', 603 }, 604 tip: (functionTipValue): string => { 605 // @ts-ignore 606 const obj = functionTipValue.obj as AnalysisObj; 607 return `<div> 608 <div>Function:${obj.symbolName}</div> 609 <div>Existing:${obj.existSizeFormat} 610 (${obj.existSizePercent}%)</div> 611 <div># Existing:${obj.existCount} 612 (${obj.existCountPercent}%)</div> 613 <div>Total Bytes:${obj.applySizeFormat} 614 (${obj.applySizePercent}%)</div> 615 <div># Total:${obj.applyCount} 616 (${obj.applyCountPercent}%)</div> 617 <div>Transient:${obj.releaseSizeFormat} 618 (${obj.releaseSizePercent}%)</div> 619 <div># Transient:${obj.releaseCount} 620 (${obj.releaseCountPercent}%)</div> 621 </div>`; 622 }, 623 hoverHandler: (data): void => { 624 if (data) { 625 this.functionUsageTbl!.setCurrentHover(data); 626 } else { 627 this.functionUsageTbl!.mouseOut(); 628 } 629 }, 630 interactions: [ 631 { 632 type: 'element-active', 633 }, 634 ], 635 }; 636 // @ts-ignore 637 this.functionData.unshift(this.functionStatisticsData); 638 this.functionUsageTbl!.recycleDataSource = this.functionData; 639 // @ts-ignore 640 this.functionData.shift(this.functionStatisticsData); 641 this.currentLevelData = this.functionData; 642 this.functionUsageTbl?.reMeauseHeight(); 643 } 644 645 private nativeProcessLevelClickEvent(it: unknown): void { 646 if (this.hideThreadCheckBox?.checked || this.isStatistic) { 647 this.reset(this.soUsageTbl!, true); 648 this.showAssignLevel(this.soUsageTbl!, this.typeUsageTbl!, 1, this.eventTypeData); 649 this.getNMLibSize(it); 650 } else { 651 this.reset(this.threadUsageTbl!, true); 652 this.showAssignLevel(this.threadUsageTbl!, this.typeUsageTbl!, 1, this.eventTypeData); 653 this.getNMThreadSize(it); 654 } // @ts-ignore 655 const typeName = it.typeName === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : it.typeName; 656 this.titleEl!.textContent = typeName; 657 // @ts-ignore 658 this.type = it.typeName; 659 this.nmPieChart?.hideTip(); 660 } 661 662 private nativeThreadLevelClickEvent(it: AnalysisObj): void { 663 this.reset(this.soUsageTbl!, true); 664 this.showAssignLevel(this.soUsageTbl!, this.threadUsageTbl!, 2, this.eventTypeData); 665 this.getNMLibSize(it); 666 const typeName = this.type === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : this.type; 667 668 // @ts-ignore 669 let title = typeName; 670 if (!this.hideThreadCheckBox?.checked) { 671 this.threadName = `${it.tableName}`; 672 title += ` / ${this.threadName}`; 673 } 674 this.titleEl!.textContent = title; 675 this.nmPieChart?.hideTip(); 676 } 677 678 private nativeSoLevelClickEvent(it: unknown): void { 679 this.reset(this.functionUsageTbl!, true); 680 this.showAssignLevel(this.functionUsageTbl!, this.soUsageTbl!, 3, this.eventTypeData); 681 this.getNMFunctionSize(it); 682 const typeName = this.type === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : this.type; 683 // @ts-ignore 684 let title = typeName || ''; 685 if (!this.hideThreadCheckBox?.checked && this.threadName.length > 0) { 686 title += ` / ${this.threadName}`; 687 } // @ts-ignore 688 if (it.libName.length > 0) { 689 // @ts-ignore 690 title += ` / ${it.libName}`; 691 } 692 this.titleEl!.textContent = title; 693 this.nmPieChart?.hideTip(); 694 } 695 696 private getNMEventTypeSize(val: SelectionParam): void { 697 this.progressEL!.loading = true; 698 let typeFilter = []; 699 if (this.isStatistic) { 700 for (let type of val.nativeMemoryStatistic) { 701 if (type === 'All Heap & Anonymous VM') { 702 typeFilter = [0, 1]; 703 break; 704 } else if (type === 'All Heap') { 705 typeFilter.push(0); 706 } else { 707 typeFilter.push(1); 708 } 709 } 710 this.getDataFromWorker(val, typeFilter); 711 } else { 712 for (let type of val.nativeMemory) { 713 if (type === 'All Heap & Anonymous VM') { 714 typeFilter = []; 715 typeFilter.push(...["'AllocEvent'", "'FreeEvent'", "'MmapEvent'", "'MunmapEvent'"]); 716 break; 717 } else if (type === 'All Heap') { 718 typeFilter.push(...["'AllocEvent'", "'FreeEvent'"]); 719 } else { 720 typeFilter.push(...["'MmapEvent'", "'MunmapEvent'"]); 721 } 722 } 723 this.getDataFromWorker(val, typeFilter); 724 } 725 } 726 727 private getNMTypeSize(val: SelectionParam, result: unknown): void { 728 this.resetCurrentLevelData(); // @ts-ignore 729 this.typeMap = this.typeSizeGroup(this.processData); 730 this.currentLevelExistSize = this.currentLevelApplySize - this.currentLevelReleaseSize; 731 this.currentLevelExistCount = this.currentLevelApplyCount - this.currentLevelReleaseCount; 732 this.eventTypeData = []; 733 if (this.typeMap.has(TYPE_ALLOC)) { 734 let allocType = this.setTypeMap(this.typeMap, TYPE_ALLOC, TYPE_ALLOC_STRING); 735 if (allocType) { 736 this.calPercent(allocType); 737 this.eventTypeData.push(allocType); 738 } 739 } 740 if (this.typeMap.has(TYPE_MAP)) { 741 let subTypeMap = new Map<string, Array<number | string>>(); 742 for (let item of this.typeMap.get(TYPE_MAP)!) { 743 // @ts-ignore 744 if (item.subType) { 745 // @ts-ignore 746 if (subTypeMap.has(item.subType)) { 747 // @ts-ignore 748 subTypeMap.get(item.subType)?.push(item); 749 } else { 750 let dataArray: Array<number | string> = []; // @ts-ignore 751 dataArray.push(item); // @ts-ignore 752 subTypeMap.set(item.subType, dataArray); 753 } 754 } else { 755 if (subTypeMap.has(TYPE_MAP_STRING)) { 756 // @ts-ignore 757 subTypeMap.get(TYPE_MAP_STRING)?.push(item); 758 } else { 759 let dataArray: Array<number | string> = []; // @ts-ignore 760 dataArray.push(item); 761 subTypeMap.set(TYPE_MAP_STRING, dataArray); 762 } 763 } 764 } 765 subTypeMap.forEach((arr: Array<number | string>, subType: string) => { 766 let mapType = this.setTypeMap(this.typeMap, TYPE_MAP, subType); 767 if (mapType) { 768 this.calPercent(mapType); 769 this.eventTypeData.push(mapType); 770 } 771 }); 772 } 773 this.eventTypeData.sort((a, b) => b.existSize - a.existSize); 774 this.typeStatisticsData = this.totalData(this.typeStatisticsData); 775 this.progressEL!.loading = false; 776 this.currentLevel = 0; 777 this.typePieChart(); 778 } 779 780 private getNMThreadSize(item: unknown): void { 781 this.progressEL!.loading = true; 782 let threadMap = new Map<number, Array<number | string>>(); // @ts-ignore 783 let types = this.getTypes(item); // @ts-ignore 784 let typeName = item.typeName; 785 this.resetCurrentLevelData(item); 786 for (let itemData of this.processData) { 787 // @ts-ignore 788 if (this.shouldSkipItem(typeName, types, itemData)) { 789 continue; 790 } // @ts-ignore 791 if (threadMap.has(itemData.tid)) { 792 // @ts-ignore 793 threadMap.get(itemData.tid)?.push(itemData); 794 } else { 795 let itemArray: Array<number | string> = []; // @ts-ignore 796 itemArray.push(itemData); // @ts-ignore 797 threadMap.set(itemData.tid, itemArray); 798 } 799 } 800 this.threadData = []; 801 threadMap.forEach((dbData: Array<unknown>, tid: number) => { 802 const sizeObj = this.calSizeObj(dbData); 803 let analysis = new AnalysisObj(sizeObj.applySize, sizeObj.applyCount, sizeObj.releaseSize, sizeObj.releaseCount); 804 this.calPercent(analysis); // @ts-ignore 805 analysis.typeId = item.typeId; // @ts-ignore 806 analysis.typeName = item.typeName; 807 analysis.tid = tid; // @ts-ignore 808 if (dbData[0].threadName && dbData[0].threadName.length > 0) { 809 // @ts-ignore 810 analysis.tName = `${dbData[0].threadName}(${tid})`; 811 } else { 812 analysis.tName = `Thread ${tid}`; 813 } 814 analysis.tableName = analysis.tName; 815 this.threadData.push(analysis); 816 }); 817 this.threadData.sort((a, b) => b.existSize - a.existSize); 818 this.threadStatisticsData = this.totalData(this.threadStatisticsData); 819 this.currentLevel = 1; 820 this.currentLevelData = this.threadData; 821 this.progressEL!.loading = false; 822 this.threadPieChart(); 823 } 824 825 private shouldSkipItem(typeName: string, types: Array<number | string>, itemData: unknown): boolean { 826 if (typeName === TYPE_ALLOC_STRING) { 827 // @ts-ignore 828 return !types.includes(itemData.type); 829 } else if (typeName === TYPE_MAP_STRING) { 830 if (this.isStatistic) { 831 // @ts-ignore 832 if (itemData.subType) { 833 // @ts-ignore 834 return !types.includes(itemData.subType) || !types.includes(itemData.type); 835 } else { 836 return true; 837 } 838 } else { 839 // @ts-ignore 840 if (!itemData.subType) { 841 // @ts-ignore 842 return !types.includes(itemData.type); 843 } else { 844 return true; 845 } 846 } 847 } else { 848 // @ts-ignore 849 if (itemData.subType) { 850 // @ts-ignore 851 return !types.includes(itemData.subType) || !types.includes(itemData.type); 852 } else { 853 return true; 854 } 855 } 856 } 857 858 private getNMLibSize(item: unknown): void { 859 this.progressEL!.loading = true; // @ts-ignore 860 let typeId = item.typeId; // @ts-ignore 861 let typeName = item.typeName; // @ts-ignore 862 let tid = item.tid; 863 let libMap = new Map<number, Array<number | string>>(); 864 this.resetCurrentLevelData(item); // @ts-ignore 865 let types = this.getTypes(item); 866 this.soData = []; 867 if (!this.processData) { 868 return; 869 } 870 for (let itemData of this.processData) { 871 if (this.shouldSkipItem(typeName, types, itemData)) { 872 continue; 873 } // @ts-ignore 874 if (tid !== undefined && tid !== itemData.tid) { 875 continue; 876 } // @ts-ignore 877 let libId = itemData.libId; 878 if (libMap.has(libId)) { 879 // @ts-ignore 880 libMap.get(libId)?.push(itemData); 881 } else { 882 let dataArray: Array<number | string> = []; // @ts-ignore 883 dataArray.push(itemData); 884 libMap.set(libId, dataArray); 885 } 886 } 887 this.soData = []; 888 libMap.forEach((libItems, libId) => { 889 let libPath = SpSystemTrace.DATA_DICT.get(libId)?.split('/'); 890 let libName = ''; 891 if (libPath) { 892 libName = libPath[libPath.length - 1]; 893 } 894 const sizeObj = this.calSizeObj(libItems); 895 let analysis = new AnalysisObj(sizeObj.applySize, sizeObj.applyCount, sizeObj.releaseSize, sizeObj.releaseCount); 896 this.calPercent(analysis); 897 analysis.typeId = typeId; 898 analysis.typeName = typeName; 899 analysis.tid = tid; 900 analysis.tName = 'Thread ' + tid; 901 analysis.libId = libId; 902 analysis.libName = libName; 903 analysis.tableName = analysis.libName; 904 this.soData.push(analysis); 905 }); 906 this.baseSort(this.soData); 907 this.libraryPieChart(item); 908 } 909 910 private getNMFunctionSize(item: unknown): void { 911 this.progressEL!.loading = true; 912 this.shadowRoot!.querySelector<HTMLDivElement>('.nm-subheading')!.textContent = 'Statistic By Function Existing'; 913 // @ts-ignore 914 let typeId = item.typeId; // @ts-ignore 915 let typeName = item.typeName; // @ts-ignore 916 let tid = item.tid; // @ts-ignore 917 let libId = item.libId; // @ts-ignore 918 let symbolMap = new Map<number, Array<number | string>>(); 919 this.resetCurrentLevelData(item); // @ts-ignore 920 let types = this.getTypes(item); 921 if (!this.processData) { 922 return; 923 } 924 for (let data of this.processData) { 925 if (this.skipItemByType(typeName, types, data, libId)) { 926 continue; 927 } // @ts-ignore 928 if (tid !== undefined && tid !== data.tid) { 929 continue; 930 } // @ts-ignore 931 if (symbolMap.has(data.symbolId)) { 932 // @ts-ignore 933 symbolMap.get(data.symbolId)?.push(data); 934 } else { 935 let dataArray: Array<number | string> = []; // @ts-ignore 936 dataArray.push(data); // @ts-ignore 937 symbolMap.set(data.symbolId, dataArray); 938 } 939 } 940 this.functionData = []; 941 symbolMap.forEach((symbolItems, symbolId) => { 942 let symbolPath = SpSystemTrace.DATA_DICT.get(symbolId)?.split('/'); 943 let symbolName = symbolPath ? symbolPath[symbolPath.length - 1] : 'null'; 944 const sizeObj = this.calSizeObj(symbolItems); 945 let analysis = new AnalysisObj(sizeObj.applySize, sizeObj.applyCount, sizeObj.releaseSize, sizeObj.releaseCount); 946 this.calPercent(analysis); 947 analysis.typeId = typeId; 948 analysis.typeName = typeName; 949 analysis.tid = tid; 950 analysis.tName = 'Thread ' + tid; 951 analysis.libId = libId; // @ts-ignore 952 analysis.libName = item.libName; 953 analysis.symbolId = symbolId; 954 analysis.symbolName = symbolName; 955 analysis.tableName = analysis.symbolName; 956 this.functionData.push(analysis); 957 }); 958 this.baseSort(this.functionData); 959 this.functionPieChart(); 960 } 961 962 private skipItemByType(typeName: string, types: Array<string | number>, data: unknown, libId: number): boolean { 963 if (typeName === TYPE_ALLOC_STRING) { 964 // @ts-ignore 965 if (!types.includes(data.type) || data.libId !== libId) { 966 return true; 967 } 968 } else if (typeName === TYPE_MAP_STRING) { 969 if (this.isStatistic) { 970 // @ts-ignore 971 if (data.subType) { 972 // @ts-ignore 973 if (!types.includes(data.subType) || !types.includes(data.type) || data.libId !== libId) { 974 return true; 975 } 976 } else { 977 return true; 978 } 979 } else { 980 // @ts-ignore 981 if (!data.subType) { 982 // @ts-ignore 983 if (!types.includes(data.type) || data.libId !== libId) { 984 return true; 985 } 986 } else { 987 return true; 988 } 989 } 990 } else { 991 // @ts-ignore 992 if (data.subType) { 993 // @ts-ignore 994 if (!types.includes(data.subType) || !types.includes(data.type) || data.libId !== libId) { 995 return true; 996 } 997 } else { 998 return true; 999 } 1000 } 1001 return false; 1002 } 1003 private baseSort(data: Array<AnalysisObj>): void { 1004 if (data === this.functionData) { 1005 this.functionData.sort((a, b) => b.existSize - a.existSize); 1006 // @ts-ignore 1007 this.functionStatisticsData = this.totalData(this.functionStatisticsData); 1008 this.currentLevel = 3; 1009 this.progressEL!.loading = false; 1010 } 1011 if (data === this.soData) { 1012 this.soData.sort((a, b) => b.existSize - a.existSize); 1013 this.libStatisticsData = this.totalData(this.libStatisticsData); 1014 this.currentLevel = 2; 1015 this.progressEL!.loading = false; 1016 } 1017 } 1018 1019 private getPieChartData(res: unknown[]): unknown[] { 1020 if (res.length > PIE_CHART_LIMIT) { 1021 let pieChartArr: string[] = []; 1022 let other: unknown = { 1023 tableName: 'other', 1024 tName: 'other', 1025 libName: 'other', 1026 symbolName: 'other', 1027 existSizePercent: 0, 1028 existSize: 0, 1029 existSizeFormat: '', 1030 existCount: 0, 1031 existCountPercent: 0, 1032 applySizeFormat: '', 1033 applySize: 0, 1034 applySizePercent: 0, 1035 applyCount: 0, 1036 applyCountPercent: 0, 1037 releaseSizeFormat: '', 1038 releaseSize: 0, 1039 releaseSizePercent: 0, 1040 releaseCount: 0, 1041 releaseCountPercent: 0, 1042 }; 1043 for (let i = 0; i < res.length; i++) { 1044 if (i < PIE_CHART_LIMIT - 1) { 1045 // @ts-ignore 1046 pieChartArr.push(res[i]); 1047 } else { 1048 // @ts-ignore 1049 other.existCount += res[i].existCount; // @ts-ignore 1050 other.existSize += res[i].existSize; // @ts-ignore 1051 other.applySize += res[i].applySize; // @ts-ignore 1052 other.applyCount += res[i].applyCount; // @ts-ignore 1053 other.releaseSize += res[i].releaseSize; // @ts-ignore 1054 other.releaseCount += res[i].releaseCount; // @ts-ignore 1055 other.existSizeFormat = Utils.getBinaryByteWithUnit(other.existSize); // @ts-ignore 1056 other.applySizeFormat = Utils.getBinaryByteWithUnit(other.applySize); // @ts-ignore 1057 other.releaseSizeFormat = Utils.getBinaryByteWithUnit(other.releaseSize); // @ts-ignore 1058 other.existSizePercent = this.currentLevelExistSize === 0 ? 0 : ((other.existSize / this.currentLevelExistSize) * 100).toFixed(2); // @ts-ignore 1059 other.existCountPercent = this.currentLevelExistCount === 0 ? 0 : ((other.existCount / this.currentLevelExistCount) * 100).toFixed(2); // @ts-ignore 1060 other.applySizePercent = this.currentLevelApplySize === 0 ? 0 : ((other.applySize / this.currentLevelApplySize) * 100).toFixed(2); // @ts-ignore 1061 other.applyCountPercent = this.currentLevelApplyCount === 0 ? 0 : ((other.applyCount / this.currentLevelApplyCount) * 100).toFixed(2); 1062 // @ts-ignore 1063 other.releaseSizePercent = this.currentLevelReleaseSize === 0 ? 0 : 1064 // @ts-ignore 1065 ((other.releaseSize / this.currentLevelReleaseSize) * 100).toFixed(2); // @ts-ignore 1066 other.releaseCountPercent = this.currentLevelReleaseCount === 0 ? 0 : ((other.releaseCount / this.currentLevelReleaseCount) * 100).toFixed(2); 1067 } 1068 } // @ts-ignore 1069 pieChartArr.push(other); 1070 return pieChartArr; 1071 } 1072 return res; 1073 } 1074 1075 private setTypeMap(typeMap: Map<number, unknown>, tyeId: number, typeName: string): AnalysisObj | null { 1076 let applySize = 0; 1077 let releaseSize = 0; 1078 let applyCount = 0; 1079 let releaseCount = 0; 1080 let currentType = typeMap.get(tyeId); 1081 if (!currentType) { 1082 return null; 1083 } 1084 1085 // @ts-ignore 1086 for (let applySample of typeMap.get(tyeId)!) { 1087 if ( 1088 tyeId === TYPE_ALLOC || 1089 (applySample.subType && applySample.subType === typeName) || 1090 (!applySample.subType && typeName === TYPE_MAP_STRING) 1091 ) { 1092 applySize += applySample.size; 1093 applyCount += applySample.count; 1094 if (this.isStatistic) { 1095 releaseSize += applySample.releaseSize; 1096 releaseCount += applySample.releaseCount; 1097 } else { 1098 if (applySample.isRelease) { 1099 releaseSize += applySample.size; 1100 releaseCount += applySample.count; 1101 } 1102 } 1103 } 1104 } 1105 let typeItem = new AnalysisObj(applySize, applyCount, releaseSize, releaseCount); 1106 typeItem.typeId = tyeId; 1107 typeItem.typeName = typeName; 1108 typeItem.tableName = typeName === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : typeName; 1109 return typeItem; 1110 } 1111 1112 private calPercent(item: AnalysisObj): void { 1113 item.applySizePercent = this.currentLevelApplySize === 0 ? '0' : ((item.applySize / this.currentLevelApplySize) * 100).toFixed(2); 1114 item.applyCountPercent = this.currentLevelApplyCount === 0 ? '0' : ((item.applyCount / this.currentLevelApplyCount) * 100).toFixed(2); 1115 item.releaseSizePercent = this.currentLevelReleaseSize === 0 ? '0' : ((item.releaseSize / this.currentLevelReleaseSize) * 100).toFixed(2); 1116 item.releaseCountPercent = this.currentLevelReleaseCount === 0 ? '0' : ((item.releaseCount / this.currentLevelReleaseCount) * 100).toFixed(2); 1117 item.existSizePercent = this.currentLevelExistSize === 0 ? '0' : ((item.existSize / this.currentLevelExistSize) * 100).toFixed(2); 1118 item.existCountPercent = this.currentLevelExistCount === 0 ? '0' : ((item.existCount / this.currentLevelExistCount) * 100).toFixed(2); 1119 } 1120 1121 private resetCurrentLevelData(parent?: unknown): void { 1122 if (parent) { 1123 // @ts-ignore 1124 this.currentLevelApplySize = parent.applySize; // @ts-ignore 1125 this.currentLevelApplyCount = parent.applyCount; // @ts-ignore 1126 this.currentLevelExistSize = parent.existSize; // @ts-ignore 1127 this.currentLevelExistCount = parent.existCount; // @ts-ignore 1128 this.currentLevelReleaseSize = parent.releaseSize; // @ts-ignore 1129 this.currentLevelReleaseCount = parent.releaseCount; 1130 } else { 1131 this.currentLevelApplySize = 0; 1132 this.currentLevelApplyCount = 0; 1133 this.currentLevelExistSize = 0; 1134 this.currentLevelExistCount = 0; 1135 this.currentLevelReleaseSize = 0; 1136 this.currentLevelReleaseCount = 0; 1137 } 1138 } 1139 1140 private typeSizeGroup(dbArray: Array<number | string>): Map<number, Array<number | string>> { 1141 let typeMap = new Map<number, Array<number | string>>(); 1142 if (!dbArray || dbArray.length === 0) { 1143 return typeMap; 1144 } 1145 1146 const setSize = (item: unknown): void => { 1147 // @ts-ignore 1148 this.currentLevelApplySize += item.size; // @ts-ignore 1149 this.currentLevelApplyCount += item.count; 1150 if (this.isStatistic) { 1151 // @ts-ignore 1152 this.currentLevelReleaseSize += item.releaseSize; // @ts-ignore 1153 this.currentLevelReleaseCount += item.releaseCount; 1154 } else { 1155 // @ts-ignore 1156 if (item.isRelease) { 1157 // @ts-ignore 1158 this.currentLevelReleaseSize += item.size; // @ts-ignore 1159 this.currentLevelReleaseCount += item.count; 1160 } 1161 } 1162 }; 1163 1164 for (let itemData of dbArray) { 1165 // @ts-ignore 1166 switch (itemData.type) { 1167 case TYPE_ALLOC: 1168 setSize(itemData); 1169 if (typeMap.has(TYPE_ALLOC)) { 1170 typeMap.get(TYPE_ALLOC)?.push(itemData); 1171 } else { 1172 let itemArray: Array<number | string> = []; 1173 itemArray.push(itemData); 1174 typeMap.set(TYPE_ALLOC, itemArray); 1175 } 1176 break; 1177 case TYPE_MAP: 1178 setSize(itemData); 1179 if (typeMap.has(TYPE_MAP)) { 1180 typeMap.get(TYPE_MAP)?.push(itemData); 1181 } else { 1182 let itemArray: Array<number | string> = []; 1183 itemArray.push(itemData); 1184 typeMap.set(TYPE_MAP, itemArray); 1185 } 1186 break; 1187 } 1188 } 1189 return typeMap; 1190 } 1191 1192 private calSizeObj(dbData: Array<unknown>): SizeObj { 1193 let sizeObj = new SizeObj(); 1194 for (let item of dbData) { 1195 if (this.isStatistic) { 1196 // @ts-ignore 1197 sizeObj.applyCount += item.count; // @ts-ignore 1198 sizeObj.applySize += item.size; // @ts-ignore 1199 sizeObj.releaseCount += item.releaseCount; // @ts-ignore 1200 sizeObj.releaseSize += item.releaseSize; 1201 } else { 1202 // @ts-ignore 1203 sizeObj.applyCount += item.count; // @ts-ignore 1204 sizeObj.applySize += item.size; // @ts-ignore 1205 if (item.isRelease) { 1206 // @ts-ignore 1207 sizeObj.releaseCount += item.count; // @ts-ignore 1208 sizeObj.releaseSize += item.size; 1209 } 1210 } 1211 } 1212 return sizeObj; 1213 } 1214 1215 private getTypes(parent: AnalysisObj): Array<number | string> { 1216 let types: Array<number | string> = []; 1217 types.push(parent.typeId!); 1218 types.push(parent.typeName!); 1219 if (!this.isStatistic) { 1220 let releaseType; 1221 if (parent.typeId === TYPE_ALLOC) { 1222 releaseType = TYPE_FREE; 1223 } else { 1224 releaseType = TYPE_UN_MAP; 1225 } 1226 types.push(releaseType); 1227 } 1228 return types; 1229 } 1230 1231 private totalData(total: {}): {} { 1232 total = { 1233 existSizeFormat: Utils.getBinaryByteWithUnit(this.currentLevelExistSize), 1234 existSizePercent: this.currentLevelExistSize === 0 ? 0 : ((this.currentLevelExistSize / this.currentLevelExistSize) * 100).toFixed(2), 1235 existCount: this.currentLevelExistCount, 1236 existCountPercent: this.currentLevelExistCount === 0 ? 0 : ((this.currentLevelExistCount / this.currentLevelExistCount) * 100).toFixed(2), 1237 releaseSizeFormat: Utils.getBinaryByteWithUnit(this.currentLevelReleaseSize), 1238 releaseSizePercent: this.currentLevelReleaseSize === 0 ? 0 : ((this.currentLevelReleaseSize / this.currentLevelReleaseSize) * 100).toFixed(2), 1239 releaseCount: this.currentLevelReleaseCount, 1240 releaseCountPercent: this.currentLevelReleaseCount === 0 ? 0 : ((this.currentLevelReleaseCount / this.currentLevelReleaseCount) * 100).toFixed(2), 1241 applySizeFormat: Utils.getBinaryByteWithUnit(this.currentLevelApplySize), 1242 applySizePercent: this.currentLevelApplySize === 0 ? 0 : ((this.currentLevelApplySize / this.currentLevelApplySize) * 100).toFixed(2), 1243 applyCount: this.currentLevelApplyCount, 1244 applyCountPercent: this.currentLevelApplyCount === 0 ? 0 : ((this.currentLevelApplyCount / this.currentLevelApplyCount) * 100).toFixed(2), 1245 existSize: 0, 1246 tableName: '', 1247 tName: '', 1248 libName: '', 1249 symbolName: '', 1250 }; 1251 return total; 1252 } 1253 1254 private getNmCurrentTable(): LitTable | null | undefined { 1255 let nmCurrentTable: LitTable | null | undefined; 1256 switch (this.currentLevel) { 1257 case 0: 1258 nmCurrentTable = this.typeUsageTbl; 1259 break; 1260 case 1: 1261 nmCurrentTable = this.threadUsageTbl; 1262 break; 1263 case 2: 1264 nmCurrentTable = this.soUsageTbl; 1265 break; 1266 case 3: 1267 nmCurrentTable = this.functionUsageTbl; 1268 break; 1269 } 1270 return nmCurrentTable; 1271 } 1272 1273 private getSortedColumnZeroArr(data: unknown[]): unknown[] { 1274 let sortColumnZeroArr = [...data]; 1275 switch (this.currentLevel) { 1276 case 0: 1277 sortColumnZeroArr.unshift(this.typeStatisticsData); 1278 break; 1279 case 1: 1280 sortColumnZeroArr.unshift(this.threadStatisticsData); 1281 break; 1282 case 2: 1283 sortColumnZeroArr.unshift(this.libStatisticsData); 1284 break; 1285 case 3: 1286 sortColumnZeroArr.unshift(this.functionStatisticsData); 1287 break; 1288 } 1289 return sortColumnZeroArr; 1290 } 1291 1292 private updateSortColumnArr(sortColumnArr: unknown[]): unknown[] { 1293 switch (this.currentLevel) { 1294 case 0: 1295 sortColumnArr.unshift(this.typeStatisticsData); 1296 break; 1297 case 1: 1298 sortColumnArr.unshift(this.threadStatisticsData); 1299 break; 1300 case 2: 1301 sortColumnArr.unshift(this.libStatisticsData); 1302 break; 1303 case 3: 1304 sortColumnArr.unshift(this.functionStatisticsData); 1305 break; 1306 } 1307 return sortColumnArr; 1308 } 1309 1310 private caseTableName( 1311 statisticAnalysisLeftData: { tableName: number }, 1312 statisticAnalysisRightData: { tableName: number } 1313 ): number { 1314 if (this.nmSortType === 1) { 1315 if (statisticAnalysisLeftData.tableName > statisticAnalysisRightData.tableName) { 1316 return 1; 1317 } else if (statisticAnalysisLeftData.tableName === statisticAnalysisRightData.tableName) { 1318 return 0; 1319 } else { 1320 return -1; 1321 } 1322 } else { 1323 if (statisticAnalysisRightData.tableName > statisticAnalysisLeftData.tableName) { 1324 return 1; 1325 } else if (statisticAnalysisLeftData.tableName === statisticAnalysisRightData.tableName) { 1326 return 0; 1327 } else { 1328 return -1; 1329 } 1330 } 1331 } 1332 1333 private sortDataByExistSize(sortType: number, sortColumnArr: Array<unknown>): unknown[] { 1334 return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => { 1335 return sortType === 1 // @ts-ignore 1336 ? statisticAnalysisLeftData.existSize - statisticAnalysisRightData.existSize // @ts-ignore 1337 : statisticAnalysisRightData.existSize - statisticAnalysisLeftData.existSize; 1338 }); 1339 } 1340 1341 private sortDataByExistCount(sortType: number, sortColumnArr: Array<unknown>): unknown[] { 1342 return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => { 1343 return sortType === 1 // @ts-ignore 1344 ? statisticAnalysisLeftData.existCount - statisticAnalysisRightData.existCount // @ts-ignore 1345 : statisticAnalysisRightData.existCount - statisticAnalysisLeftData.existCount; 1346 }); 1347 } 1348 1349 private sortDataByReleaseSize(sortType: number, sortColumnArr: Array<unknown>): unknown[] { 1350 return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => { 1351 return sortType === 1 // @ts-ignore 1352 ? statisticAnalysisLeftData.releaseSize - statisticAnalysisRightData.releaseSize // @ts-ignore 1353 : statisticAnalysisRightData.releaseSize - statisticAnalysisLeftData.releaseSize; 1354 }); 1355 } 1356 1357 private sortDataByReleaseCount(sortType: number, sortColumnArr: Array<unknown>): unknown[] { 1358 return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => { 1359 return sortType === 1 // @ts-ignore 1360 ? statisticAnalysisLeftData.releaseCount - statisticAnalysisRightData.releaseCount // @ts-ignore 1361 : statisticAnalysisRightData.releaseCount - statisticAnalysisLeftData.releaseCount; 1362 }); 1363 } 1364 1365 private sortDataByApplySize(sortType: number, sortColumnArr: Array<unknown>): unknown[] { 1366 return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => { 1367 return sortType === 1 // @ts-ignore 1368 ? statisticAnalysisLeftData.applySize - statisticAnalysisRightData.applySize // @ts-ignore 1369 : statisticAnalysisRightData.applySize - statisticAnalysisLeftData.applySize; 1370 }); 1371 } 1372 1373 private sortDataByApplyCount(sortType: number, sortColumnArr: Array<unknown>): unknown[] { 1374 return sortColumnArr.sort((statisticAnalysisLeftData, statisticAnalysisRightData) => { 1375 return sortType === 1 // @ts-ignore 1376 ? statisticAnalysisLeftData.applyCount - statisticAnalysisRightData.applyCount // @ts-ignore 1377 : statisticAnalysisRightData.applyCount - statisticAnalysisLeftData.applyCount; 1378 }); 1379 } 1380 1381 private sortByColumn(): void { 1382 let nmCurrentTable = this.getNmCurrentTable(); 1383 if (!nmCurrentTable) { 1384 return; 1385 } 1386 if (this.nmSortType === 0) { 1387 nmCurrentTable!.recycleDataSource = this.getSortedColumnZeroArr(this.currentLevelData); 1388 } else { 1389 let sortColumnArr = [...this.currentLevelData]; 1390 switch (this.nmSortColumn) { 1391 case 'tableName': 1392 // @ts-ignore 1393 nmCurrentTable!.recycleDataSource = sortColumnArr.sort(this.caseTableName); 1394 break; 1395 case 'existSizeFormat': 1396 case 'existSizePercent': 1397 nmCurrentTable!.recycleDataSource = this.sortDataByExistSize(this.nmSortType, sortColumnArr); 1398 break; 1399 case 'existCount': 1400 case 'existCountPercent': 1401 nmCurrentTable!.recycleDataSource = this.sortDataByExistCount(this.nmSortType, sortColumnArr); 1402 break; 1403 case 'releaseSizeFormat': 1404 case 'releaseSizePercent': 1405 nmCurrentTable!.recycleDataSource = this.sortDataByReleaseSize(this.nmSortType, sortColumnArr); 1406 break; 1407 case 'releaseCount': 1408 case 'releaseCountPercent': 1409 nmCurrentTable!.recycleDataSource = this.sortDataByReleaseCount(this.nmSortType, sortColumnArr); 1410 break; 1411 case 'applySizeFormat': 1412 case 'applySizePercent': 1413 nmCurrentTable!.recycleDataSource = this.sortDataByApplySize(this.nmSortType, sortColumnArr); 1414 break; 1415 case 'applyCount': 1416 case 'applyCountPercent': 1417 nmCurrentTable!.recycleDataSource = this.sortDataByApplyCount(this.nmSortType, sortColumnArr); 1418 break; 1419 } 1420 sortColumnArr = this.updateSortColumnArr(sortColumnArr); 1421 nmCurrentTable!.recycleDataSource = sortColumnArr; 1422 } 1423 } 1424 1425 resizeTable(): void { 1426 this.resize(this.typeUsageTbl); 1427 this.resize(this.threadUsageTbl); 1428 this.resize(this.soUsageTbl); 1429 this.resize(this.functionUsageTbl); 1430 } 1431 1432 resize(table?: LitTable | null): void { 1433 if (table) { 1434 // @ts-ignore 1435 table.shadowRoot.querySelector('.table').style.height = `${this.parentElement.clientHeight - 65}px`; 1436 table.reMeauseHeight(); 1437 } 1438 } 1439 1440 public connectedCallback(): void { 1441 new ResizeObserver(() => { 1442 this.resizeTable(); 1443 // @ts-ignore 1444 if (this.parentElement?.clientHeight !== 0) { 1445 if ((this.parentElement!.clientHeight >= 0 && this.parentElement!.clientHeight <= 31) || this.isStatistic) { 1446 this.filterEl!.style.display = 'none'; 1447 this.nmPieChart!.style.marginBottom = '0px'; 1448 this.nmTableBox!.style.marginBottom = '0px'; 1449 } else { 1450 this.filterEl!.style.display = 'flex'; 1451 } 1452 } 1453 }).observe(this.parentElement!); 1454 } 1455 1456 initHtml(): string { 1457 return TabPaneNMStatisticAnalysisHtml; 1458 } 1459} 1460