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