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