1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { BaseElement, element } from '../../../../../base-ui/BaseElement'; 17import { LitTable } from '../../../../../base-ui/table/lit-table'; 18import '../TabPaneFilter'; 19import { FilterData, TabPaneFilter } from '../TabPaneFilter'; 20import { SelectionParam } from '../../../../bean/BoxSelection'; 21import { PerfCallChainMerageData, PerfLevelStruct } from '../../../../bean/PerfProfile'; 22import '../../../chart/FrameChart'; 23import { FrameChart } from '../../../chart/FrameChart'; 24import { ChartMode } from '../../../../bean/FrameChartStruct'; 25import '../../../../../base-ui/slicer/lit-slicer'; 26import '../../../../../base-ui/progress-bar/LitProgressBar'; 27import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar'; 28import { procedurePool } from '../../../../database/Procedure'; 29import { showButtonMenu } from '../SheetUtils'; 30import '../../../../../base-ui/headline/lit-headline'; 31import { LitHeadLine } from '../../../../../base-ui/headline/lit-headline'; 32import { TabPerfProfileHtml } from './TabPerfProfile.html'; 33 34const InvertOptionIndex: number = 0; 35const hideThreadOptionIndex: number = 3; 36const hideThreadStateOptionIndex: number = 4; 37const callTreeValueNoSample: number[] = [InvertOptionIndex, hideThreadOptionIndex, hideThreadStateOptionIndex]; 38 39@element('tabpane-perf-profile') 40export class TabpanePerfProfile extends BaseElement { 41 private perfProfilerTbl: LitTable | null | undefined; 42 private perfProfilerList: LitTable | null | undefined; 43 private perfProfileProgressEL: LitProgressBar | null | undefined; 44 private perfProfilerRightSource: Array<PerfCallChainMerageData> = []; 45 private perfProfilerFilter: TabPaneFilter | null | undefined; 46 private perfProfilerDataSource: any[] = []; 47 private perfProfileSortKey: string = 'weight'; 48 private perfProfileSortType: number = 0; 49 private perfSelectedData: any = undefined; 50 private perfProfileFrameChart: FrameChart | null | undefined; 51 private isChartShow: boolean = false; 52 private systemRuleName: string = '/system/'; 53 private perfProfileNumRuleName: string = '/max/min/'; 54 private needShowMenu: boolean = true; 55 private searchValue: string = ''; 56 private perfProfileLoadingPage: any; 57 private currentSelection: SelectionParam | undefined; 58 private currentRowClickData: any; 59 private initWidth: number = 0; 60 private _pieTitle: string = ''; 61 private _cWidth: number = 0; 62 private _currentLevel: number = 0; 63 private _rowClickData: any = undefined; 64 private perfLevel: PerfLevelStruct | undefined | null; 65 private headLine: LitHeadLine | null | undefined; 66 67 set pieTitle(value: string) { 68 this._pieTitle = value; 69 if (this._pieTitle.length > 0) { 70 this.headLine!.isShow = true; 71 this.headLine!.titleTxt = this._pieTitle; 72 this.headLine!.closeCallback = (): void => { 73 this.restore(); 74 }; 75 } 76 } 77 78 set cWidth(value: number) { 79 this._cWidth = value; 80 } 81 82 set currentLevel(value: number) { 83 this._currentLevel = value; 84 } 85 86 set rowClickData(value: any) { 87 this._rowClickData = value; 88 } 89 90 set data(perfProfilerSelection: SelectionParam | any) { 91 if (perfProfilerSelection !== this.currentSelection && this._rowClickData === this.currentRowClickData) { 92 this._rowClickData = undefined; 93 } 94 if (perfProfilerSelection === this.currentSelection && !this.currentSelection?.isRowClick) { 95 return; 96 } 97 this.searchValue = ''; 98 this.currentSelection = perfProfilerSelection; 99 this.currentRowClickData = this._rowClickData; 100 this.perfProfilerTbl!.style.visibility = 'visible'; 101 if (this.parentElement!.clientHeight > this.perfProfilerFilter!.clientHeight) { 102 this.perfProfilerFilter!.style.display = 'flex'; 103 } else { 104 this.perfProfilerFilter!.style.display = 'none'; 105 } 106 procedurePool.submitWithName('logic0', 'perf-reset', [], undefined, () => {}); 107 this.perfProfilerFilter!.disabledTransfer(true); 108 this.perfProfilerFilter!.initializeFilterTree(true, true, true); 109 this.perfProfilerFilter!.filterValue = ''; 110 this.perfProfileProgressEL!.loading = true; 111 this.perfProfileLoadingPage.style.visibility = 'visible'; 112 this.getDataByWorkAndUpDateCanvas(perfProfilerSelection); 113 } 114 115 getDataByWorkAndUpDateCanvas(perfProfilerSelection: SelectionParam): void { 116 if (this.clientWidth === 0) { 117 this.initWidth = this._cWidth; 118 } else { 119 this.initWidth = this.clientWidth; 120 } 121 if (this._rowClickData && this.currentRowClickData !== undefined && this.currentSelection?.isRowClick) { 122 // 点击表格的某一行跳转到火焰图 123 this.getDataByPieLevel(perfProfilerSelection.perfEventTypeId); 124 } else { 125 this.headLine!.isShow = false; 126 this.initGetData(perfProfilerSelection, this.initWidth, perfProfilerSelection.perfEventTypeId); 127 } 128 } 129 130 initGetData(perfProfilerSelection: SelectionParam | any, initWidth: number, eventTypeId: undefined | number): void { 131 let perfProfileArgs: any[] = []; 132 perfProfileArgs.push( 133 { 134 funcName: 'setSearchValue', 135 funcArgs: [''], 136 }, 137 { 138 funcName: 'getCurrentDataFromDb', 139 funcArgs: [perfProfilerSelection], 140 } 141 ); 142 143 this.getDataByWorker(perfProfileArgs, (results: any[]) => { 144 this.setPerfProfilerLeftTableData(results); 145 this.perfProfilerList!.recycleDataSource = []; 146 if (eventTypeId === undefined) { 147 this.perfProfileFrameChart!.mode = ChartMode.Count; 148 } else { 149 this.perfProfileFrameChart!.mode = ChartMode.EventCount; 150 } 151 this.perfProfileFrameChart?.updateCanvas(true, initWidth); 152 this.perfProfileFrameChart!.data = this.perfProfilerDataSource; 153 this.switchFlameChart(); 154 this.perfProfilerFilter!.icon = 'block'; 155 }); 156 } 157 158 private restore(): void { 159 this.searchValue = ''; 160 this.perfProfilerFilter!.filterValue = ''; 161 this.headLine!.isShow = false; 162 this._rowClickData = undefined; 163 this.initGetData(this.currentSelection, this.initWidth, this.currentSelection?.perfEventTypeId); 164 } 165 166 /** 167 * 根据饼图跳转过来的层级绘制对应的火焰图和表格 168 */ 169 private getDataByPieLevel(eventTypeId: number | undefined): void { 170 this.perfLevel = new PerfLevelStruct(); 171 this.perfLevel = { 172 processId: this._rowClickData.pid, 173 threadId: this._rowClickData.tid, 174 libId: this._rowClickData.libId, 175 }; 176 let args = []; 177 args.push({ 178 funcName: 'getCurrentDataFromDb', 179 funcArgs: [this.currentSelection, this.perfLevel], 180 }); 181 182 if (this._rowClickData && this._rowClickData.libId !== undefined && this._currentLevel === 2) { 183 this.perfLevel!.libName = this._rowClickData.tableName; 184 args.push({ 185 funcName: 'showLibLevelData', 186 funcArgs: [this.perfLevel!.libId, this.perfLevel!.libName], 187 }); 188 } else if (this._rowClickData && this._rowClickData.symbolId !== undefined && this._currentLevel === 3) { 189 this.perfLevel!.symbolId = this._rowClickData.symbolId; 190 this.perfLevel!.symbolName = this._rowClickData.tableName; 191 args.push({ 192 funcName: 'showFunLevelData', 193 funcArgs: [this.perfLevel!.symbolId, this.perfLevel!.symbolName], 194 }); 195 } 196 197 this.getDataByWorker(args, (results: any[]) => { 198 this.perfProfileProgressEL!.loading = false; 199 this.perfProfileLoadingPage.style.visibility = 'hidden'; 200 this.setPerfProfilerLeftTableData(results); 201 this.perfProfilerList!.recycleDataSource = []; 202 if (eventTypeId === undefined) { 203 this.perfProfileFrameChart!.mode = ChartMode.Count; 204 } else { 205 this.perfProfileFrameChart!.mode = ChartMode.EventCount; 206 } 207 this.perfProfileFrameChart?.updateCanvas(true, this.initWidth); 208 this.perfProfileFrameChart!.data = this.perfProfilerDataSource; 209 this.switchFlameChart(); 210 this.perfProfilerFilter!.icon = 'block'; 211 }); 212 } 213 214 getParentTree( 215 perfCallSrc: Array<PerfCallChainMerageData>, 216 target: PerfCallChainMerageData, 217 parentsData: Array<PerfCallChainMerageData> 218 ): boolean { 219 for (let perfCall of perfCallSrc) { 220 if (perfCall.id === target.id) { 221 parentsData.push(perfCall); 222 return true; 223 } else { 224 if (this.getParentTree(perfCall.children as Array<PerfCallChainMerageData>, target, parentsData)) { 225 parentsData.push(perfCall); 226 return true; 227 } 228 } 229 } 230 return false; 231 } 232 233 getChildTree( 234 perfCallSrc: Array<PerfCallChainMerageData>, 235 id: string, 236 children: Array<PerfCallChainMerageData> 237 ): boolean { 238 for (let perfCall of perfCallSrc) { 239 if (perfCall.id === id && perfCall.children.length === 0) { 240 children.push(perfCall); 241 return true; 242 } else { 243 if (this.getChildTree(perfCall.children as Array<PerfCallChainMerageData>, id, children)) { 244 children.push(perfCall); 245 return true; 246 } 247 } 248 } 249 return false; 250 } 251 252 setRightTableData(chainMerageData: PerfCallChainMerageData): void { 253 let parentsMerageData: Array<PerfCallChainMerageData> = []; 254 let childrenMerageData: Array<PerfCallChainMerageData> = []; 255 this.getParentTree(this.perfProfilerDataSource, chainMerageData, parentsMerageData); 256 let maxId = chainMerageData.id; 257 let maxDur = 0; 258 259 function findMaxStack(call: PerfCallChainMerageData): void { 260 if (call.children.length === 0) { 261 if (call.dur > maxDur) { 262 maxDur = call.dur; 263 maxId = call.id; 264 } 265 } else { 266 call.children.map((callChild): void => { 267 findMaxStack(<PerfCallChainMerageData>callChild); 268 }); 269 } 270 } 271 272 findMaxStack(chainMerageData); 273 this.getChildTree(chainMerageData.children as Array<PerfCallChainMerageData>, maxId, childrenMerageData); 274 let perfProfileParentsList = parentsMerageData.reverse().concat(childrenMerageData.reverse()); 275 for (let data of perfProfileParentsList) { 276 data.type = 277 data.libName.endsWith('.so.1') || data.libName.endsWith('.dll') || data.libName.endsWith('.so') ? 0 : 1; 278 } 279 let len = perfProfileParentsList.length; 280 this.perfProfilerRightSource = perfProfileParentsList; 281 let rightSource: Array<any> = []; 282 if (len !== 0) { 283 rightSource = this.perfProfilerRightSource.filter((item): boolean => { 284 return item.canCharge; 285 }); 286 } 287 this.perfProfilerList!.dataSource = rightSource; 288 } 289 290 initElements(): void { 291 this.headLine = this.shadowRoot?.querySelector<LitHeadLine>('.titleBox'); 292 this.perfProfilerTbl = this.shadowRoot?.querySelector<LitTable>('#tb-perf-profile'); 293 this.perfProfileProgressEL = this.shadowRoot?.querySelector('.perf-profile-progress') as LitProgressBar; 294 this.perfProfileFrameChart = this.shadowRoot?.querySelector<FrameChart>('#framechart'); 295 this.perfProfileLoadingPage = this.shadowRoot?.querySelector('.perf-profile-loading'); 296 this.addEventListener('contextmenu', (event) => { 297 event.preventDefault(); // 阻止默认的上下文菜单弹框 298 }); 299 this.perfProfileFrameChart!.addChartClickListener((needShowMenu: boolean): void => { 300 this.parentElement!.scrollTo(0, 0); 301 showButtonMenu(this.perfProfilerFilter, needShowMenu); 302 this.needShowMenu = needShowMenu; 303 }); 304 this.perfProfilerTbl!.rememberScrollTop = true; 305 this.perfProfilerFilter = this.shadowRoot?.querySelector<TabPaneFilter>('#filter'); 306 this.perfProfilerList = this.shadowRoot?.querySelector<LitTable>('#tb-perf-list'); 307 this.initPerfProfilerDataAndListener(); 308 } 309 310 private initPerfProfilerDataAndListener(): void { 311 this.perfProfilerTbl!.addEventListener('row-click', (evt: any): void => { 312 // @ts-ignore 313 let data = evt.detail.data as PerfCallChainMerageData; 314 document.dispatchEvent( 315 new CustomEvent('number_calibration', { 316 detail: { time: data.tsArray }, 317 }) 318 ); 319 this.setRightTableData(data); 320 data.isSelected = true; 321 this.perfSelectedData = data; 322 this.perfProfilerList?.clearAllSelection(data); 323 this.perfProfilerList?.setCurrentSelection(data); 324 // @ts-ignore 325 if ((evt.detail as any).callBack) { 326 // @ts-ignore 327 (evt.detail as any).callBack(true); 328 } 329 }); 330 this.perfProfilerList!.addEventListener('row-click', (evt: any): void => { 331 // @ts-ignore 332 let data = evt.detail.data as PerfCallChainMerageData; 333 this.perfProfilerTbl?.clearAllSelection(data); 334 (data as any).isSelected = true; 335 this.perfProfilerTbl!.scrollToData(data); 336 // @ts-ignore 337 if ((evt.detail as any).callBack) { 338 // @ts-ignore 339 (evt.detail as any).callBack(true); 340 } 341 }); 342 this.perfProfilerFilter!.getDataLibrary(this.filterFunc.bind(this)); 343 this.perfProfilerFilter!.getDataMining(this.filterFunc.bind(this)); 344 this.perfProfilerFilter!.getCallTreeData(this.perfProfilerFilterGetCallTree.bind(this)); 345 this.perfProfilerFilter!.getCallTreeConstraintsData(this.perfProfilerFilterGetCallTreeConstraints.bind(this)); 346 this.perfProfilerFilter!.getFilterData(this.perfProfilerFilterGetFilter.bind(this)); 347 this.perfProfilerTbl!.addEventListener('column-click', (evt): void => { 348 // @ts-ignore 349 this.perfProfileSortKey = evt.detail.key; 350 // @ts-ignore 351 this.perfProfileSortType = evt.detail.sort; 352 // @ts-ignore 353 this.setPerfProfilerLeftTableData(this.perfProfilerDataSource); 354 this.perfProfileFrameChart!.data = this.perfProfilerDataSource; 355 }); 356 } 357 358 private filterFuncByCheckType(data: any, perfProfileFuncArgs: any[]): void { 359 if (data.item.checked) { 360 perfProfileFuncArgs.push({ 361 funcName: 'splitTree', 362 funcArgs: [data.item.name, data.item.select === '0', data.item.type === 'symbol'], 363 }); 364 } else { 365 perfProfileFuncArgs.push({ 366 funcName: 'resotreAllNode', 367 funcArgs: [[data.item.name]], 368 }); 369 perfProfileFuncArgs.push({ 370 funcName: 'resetAllNode', 371 funcArgs: [], 372 }); 373 perfProfileFuncArgs.push({ 374 funcName: 'clearSplitMapData', 375 funcArgs: [data.item.name], 376 }); 377 } 378 } 379 380 private filterFuncBySelect(data: any, perfProfileFuncArgs: any[]): void { 381 perfProfileFuncArgs.push({ 382 funcName: 'resotreAllNode', 383 funcArgs: [[data.item.name]], 384 }); 385 perfProfileFuncArgs.push({ 386 funcName: 'clearSplitMapData', 387 funcArgs: [data.item.name], 388 }); 389 perfProfileFuncArgs.push({ 390 funcName: 'splitTree', 391 funcArgs: [data.item.name, data.item.select === '0', data.item.type === 'symbol'], 392 }); 393 } 394 395 private filterFuncByButton(data: any, perfProfileFuncArgs: any[]): void { 396 if (data.item === 'symbol') { 397 if (this.perfSelectedData && !this.perfSelectedData.canCharge) { 398 return; 399 } 400 if (this.perfSelectedData !== undefined) { 401 this.perfProfilerFilter!.addDataMining({ name: this.perfSelectedData.symbolName }, data.item); 402 perfProfileFuncArgs.push({ 403 funcName: 'splitTree', 404 funcArgs: [this.perfSelectedData.symbolName, false, true], 405 }); 406 } else { 407 return; 408 } 409 } else if (data.item === 'library') { 410 if (this.perfSelectedData && !this.perfSelectedData.canCharge) { 411 return; 412 } 413 if (this.perfSelectedData !== undefined && this.perfSelectedData.libName !== '') { 414 this.perfProfilerFilter!.addDataMining({ name: this.perfSelectedData.libName }, data.item); 415 perfProfileFuncArgs.push({ 416 funcName: 'splitTree', 417 funcArgs: [this.perfSelectedData.libName, false, false], 418 }); 419 } else { 420 return; 421 } 422 } else if (data.item === 'restore') { 423 if (data.remove !== undefined && data.remove.length > 0) { 424 let list = data.remove.map((item: any) => { 425 return item.name; 426 }); 427 perfProfileFuncArgs.push({ 428 funcName: 'resotreAllNode', 429 funcArgs: [list], 430 }); 431 perfProfileFuncArgs.push({ 432 funcName: 'resetAllNode', 433 funcArgs: [], 434 }); 435 list.forEach((symbolName: string): void => { 436 perfProfileFuncArgs.push({ 437 funcName: 'clearSplitMapData', 438 funcArgs: [symbolName], 439 }); 440 }); 441 } 442 } 443 } 444 445 private filterFunc(data: any): void { 446 let perfProfileFuncArgs: any[] = []; 447 if (data.type === 'check') { 448 this.filterFuncByCheckType(data, perfProfileFuncArgs); 449 } else if (data.type === 'select') { 450 this.filterFuncBySelect(data, perfProfileFuncArgs); 451 } else if (data.type === 'button') { 452 this.filterFuncByButton(data, perfProfileFuncArgs); 453 } 454 this.getDataByWorker(perfProfileFuncArgs, (result: any[]): void => { 455 this.setPerfProfilerLeftTableData(result); 456 this.perfProfileFrameChart!.data = this.perfProfilerDataSource; 457 if (this.isChartShow) { 458 this.perfProfileFrameChart?.calculateChartData(); 459 } 460 this.perfProfilerTbl!.move1px(); 461 if (this.perfSelectedData) { 462 this.perfSelectedData.isSelected = false; 463 this.perfProfilerTbl?.clearAllSelection(this.perfSelectedData); 464 this.perfProfilerList!.recycleDataSource = []; 465 this.perfSelectedData = undefined; 466 } 467 }); 468 } 469 470 private perfProfilerFilterGetFilter(data: FilterData): void { 471 if (this.searchValue !== this.perfProfilerFilter!.filterValue) { 472 this.searchValue = this.perfProfilerFilter!.filterValue; 473 let perfArgs = [ 474 { 475 funcName: 'setSearchValue', 476 funcArgs: [this.searchValue], 477 }, 478 { 479 funcName: 'resetAllNode', 480 funcArgs: [], 481 }, 482 ]; 483 this.getDataByWorker(perfArgs, (result: any[]): void => { 484 this.perfProfilerTbl!.isSearch = true; 485 this.perfProfilerTbl!.setStatus(result, true); 486 this.setPerfProfilerLeftTableData(result); 487 this.perfProfileFrameChart!.data = this.perfProfilerDataSource; 488 this.switchFlameChart(data); 489 }); 490 } else { 491 this.perfProfilerTbl!.setStatus(this.perfProfilerDataSource, true); 492 this.setPerfProfilerLeftTableData(this.perfProfilerDataSource); 493 this.switchFlameChart(data); 494 } 495 } 496 497 private perfProfilerFilterGetCallTreeConstraints(data: any): void { 498 let perfProfilerConstraintsArgs: any[] = [ 499 { 500 funcName: 'resotreAllNode', 501 funcArgs: [[this.perfProfileNumRuleName]], 502 }, 503 { 504 funcName: 'clearSplitMapData', 505 funcArgs: [this.perfProfileNumRuleName], 506 }, 507 ]; 508 if (data.checked) { 509 perfProfilerConstraintsArgs.push({ 510 funcName: 'hideNumMaxAndMin', 511 funcArgs: [parseInt(data.min), data.max], 512 }); 513 } 514 perfProfilerConstraintsArgs.push({ 515 funcName: 'resetAllNode', 516 funcArgs: [], 517 }); 518 this.getDataByWorker(perfProfilerConstraintsArgs, (result: any[]): void => { 519 this.setPerfProfilerLeftTableData(result); 520 this.perfProfileFrameChart!.data = this.perfProfilerDataSource; 521 if (this.isChartShow) { 522 this.perfProfileFrameChart?.calculateChartData(); 523 } 524 }); 525 } 526 527 private perfProfilerFilterGetCallTree(data: any): void { 528 if (callTreeValueNoSample.includes(data.value)) { 529 this.refreshAllNode({ 530 ...this.perfProfilerFilter!.getFilterTreeData(), 531 callTree: data.checks, 532 }); 533 } else { 534 let perfProfileArgs: any[] = []; 535 if (data.checks[1]) { 536 perfProfileArgs.push({ 537 funcName: 'hideSystemLibrary', 538 funcArgs: [], 539 }); 540 } else { 541 perfProfileArgs.push({ 542 funcName: 'resotreAllNode', 543 funcArgs: [[this.systemRuleName]], 544 }); 545 perfProfileArgs.push({ 546 funcName: 'clearSplitMapData', 547 funcArgs: [this.systemRuleName], 548 }); 549 } 550 perfProfileArgs.push({ 551 funcName: 'resetAllNode', 552 funcArgs: [], 553 }); 554 this.getDataByWorker(perfProfileArgs, (result: any[]): void => { 555 this.setPerfProfilerLeftTableData(result); 556 this.perfProfileFrameChart!.data = this.perfProfilerDataSource; 557 if (this.isChartShow) { 558 this.perfProfileFrameChart?.calculateChartData(); 559 } 560 }); 561 } 562 } 563 564 connectedCallback(): void { 565 super.connectedCallback(); 566 this.parentElement!.onscroll = (): void => { 567 this.perfProfileFrameChart!.tabPaneScrollTop = this.parentElement!.scrollTop; 568 }; 569 let filterHeight = 0; 570 new ResizeObserver((entries): void => { 571 let perfProfileTabFilter = this.shadowRoot!.querySelector('#filter') as HTMLElement; 572 if (perfProfileTabFilter.clientHeight > 0) { 573 filterHeight = perfProfileTabFilter.clientHeight; 574 } 575 if (this.parentElement!.clientHeight > filterHeight) { 576 perfProfileTabFilter.style.display = 'flex'; 577 } else { 578 perfProfileTabFilter.style.display = 'none'; 579 } 580 if (this.perfProfilerTbl!.style.visibility === 'hidden') { 581 perfProfileTabFilter.style.display = 'none'; 582 } 583 if (this.parentElement?.clientHeight !== 0) { 584 if (this.isChartShow) { 585 this.perfProfileFrameChart?.updateCanvas(false, entries[0].contentRect.width); 586 this.perfProfileFrameChart?.calculateChartData(); 587 } 588 // @ts-ignore 589 this.perfProfilerTbl?.shadowRoot.querySelector('.table').style.height = 590 // @ts-ignore 591 `${this.parentElement.clientHeight - 10 - 35}px`; 592 this.perfProfilerTbl?.reMeauseHeight(); 593 // @ts-ignore 594 this.perfProfilerList?.shadowRoot.querySelector('.table').style.height = 595 // @ts-ignore 596 `${this.parentElement.clientHeight - 45 - 21}px`; 597 this.perfProfilerList?.reMeauseHeight(); 598 this.perfProfileLoadingPage.style.height = `${this.parentElement!.clientHeight - 24}px`; 599 } 600 }).observe(this.parentElement!); 601 } 602 603 switchFlameChart(data?: any): void { 604 let perfProfilerPageTab = this.shadowRoot?.querySelector('#show_table'); 605 let perfProfilerPageChart = this.shadowRoot?.querySelector('#show_chart'); 606 if (!data || data.icon === 'block') { 607 perfProfilerPageChart?.setAttribute('class', 'show'); 608 perfProfilerPageTab?.setAttribute('class', ''); 609 this.isChartShow = true; 610 this.perfProfilerFilter!.disabledMining = true; 611 showButtonMenu(this.perfProfilerFilter, this.needShowMenu); 612 this.perfProfileFrameChart?.calculateChartData(); 613 } else if (data.icon === 'tree') { 614 perfProfilerPageChart?.setAttribute('class', ''); 615 perfProfilerPageTab?.setAttribute('class', 'show'); 616 showButtonMenu(this.perfProfilerFilter, true); 617 this.isChartShow = false; 618 this.perfProfilerFilter!.disabledMining = false; 619 this.perfProfileFrameChart!.clearCanvas(); 620 this.perfProfilerTbl!.reMeauseHeight(); 621 } 622 } 623 624 refreshAllNode(filterData: any): void { 625 let perfProfileArgs: any[] = []; 626 let isTopDown: boolean = !filterData.callTree[0]; 627 let isHideSystemLibrary: boolean = filterData.callTree[1]; 628 let isHideThread: boolean = filterData.callTree[3]; 629 let isHideThreadState: boolean = filterData.callTree[4]; 630 let list = filterData.dataMining.concat(filterData.dataLibrary); 631 perfProfileArgs.push({ 632 funcName: 'hideThread', 633 funcArgs: [isHideThread], 634 }); 635 636 perfProfileArgs.push({ 637 funcName: 'hideThreadState', 638 funcArgs: [isHideThreadState], 639 }); 640 perfProfileArgs.push({ 641 funcName: 'getCallChainsBySampleIds', 642 funcArgs: [isTopDown], 643 }); 644 this.perfProfilerList!.recycleDataSource = []; 645 if (isHideSystemLibrary) { 646 perfProfileArgs.push({ 647 funcName: 'hideSystemLibrary', 648 funcArgs: [], 649 }); 650 } 651 if (filterData.callTreeConstraints.checked) { 652 perfProfileArgs.push({ 653 funcName: 'hideNumMaxAndMin', 654 funcArgs: [parseInt(filterData.callTreeConstraints.inputs[0]), filterData.callTreeConstraints.inputs[1]], 655 }); 656 } 657 perfProfileArgs.push({ 658 funcName: 'splitAllProcess', 659 funcArgs: [list], 660 }); 661 perfProfileArgs.push({ 662 funcName: 'resetAllNode', 663 funcArgs: [], 664 }); 665 this.refreshAllNodeExtend(perfProfileArgs); 666 } 667 668 refreshAllNodeExtend(perfProfileArgs: any[]): void { 669 if (this._rowClickData && this._rowClickData.libId !== undefined && this._currentLevel === 2) { 670 perfProfileArgs.push({ 671 funcName: 'showLibLevelData', 672 funcArgs: [this.perfLevel!.libId, this.perfLevel!.libName], 673 }); 674 } else if (this._rowClickData && this._rowClickData.symbolId && this._currentLevel === 3) { 675 perfProfileArgs.push({ 676 funcName: 'showFunLevelData', 677 funcArgs: [this.perfLevel!.symbolId, this.perfLevel!.symbolName], 678 }); 679 } 680 this.getDataByWorker(perfProfileArgs, (result: any[]): void => { 681 this.setPerfProfilerLeftTableData(result); 682 this.perfProfileFrameChart!.data = this.perfProfilerDataSource; 683 if (this.isChartShow) { 684 this.perfProfileFrameChart?.calculateChartData(); 685 } 686 }); 687 } 688 689 setPerfProfilerLeftTableData(resultData: any[]): void { 690 this.perfProfilerDataSource = this.sortTree(resultData); 691 this.perfProfilerTbl!.recycleDataSource = this.perfProfilerDataSource; 692 } 693 694 sortTree(arr: Array<any>): Array<any> { 695 let perfProfileSortArr = arr.sort((perfProfileA, perfProfileB): number => { 696 if (this.perfProfileSortKey === 'selfDur') { 697 if (this.perfProfileSortType === 0) { 698 return perfProfileB.dur - perfProfileA.dur; 699 } else if (this.perfProfileSortType === 1) { 700 return perfProfileA.selfDur - perfProfileB.selfDur; 701 } else { 702 return perfProfileB.selfDur - perfProfileA.selfDur; 703 } 704 } else { 705 if (this.perfProfileSortType === 0) { 706 return perfProfileB.dur - perfProfileA.dur; 707 } else if (this.perfProfileSortType === 1) { 708 return perfProfileA.dur - perfProfileB.dur; 709 } else { 710 return perfProfileB.dur - perfProfileA.dur; 711 } 712 } 713 }); 714 perfProfileSortArr.map((call: any): void => { 715 call.children = this.sortTree(call.children); 716 }); 717 return perfProfileSortArr; 718 } 719 720 getDataByWorker(args: any[], handler: Function): void { 721 this.perfProfileProgressEL!.loading = true; 722 this.perfProfileLoadingPage.style.visibility = 'visible'; 723 procedurePool.submitWithName('logic0', 'perf-action', args, undefined, (results: any): void => { 724 handler(results); 725 this.perfProfileProgressEL!.loading = false; 726 this.perfProfileLoadingPage.style.visibility = 'hidden'; 727 }); 728 } 729 730 initHtml(): string { 731 return TabPerfProfileHtml; 732 } 733} 734