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 './trace/TimerShaftElement'; 18import './trace/base/TraceRow'; 19import { threadPool } from '../database/SqlLite'; 20import { TraceRow } from './trace/base/TraceRow'; 21import { TimerShaftElement } from './trace/TimerShaftElement'; 22import './trace/base/TraceSheet'; 23import { TraceSheet } from './trace/base/TraceSheet'; 24import { RangeSelect } from './trace/base/RangeSelect'; 25import { SelectionParam } from '../bean/BoxSelection'; 26import { procedurePool } from '../database/Procedure'; 27import { SpApplication } from '../SpApplication'; 28import { Flag } from './trace/timer-shaft/Flag'; 29import { SlicesTime, SportRuler } from './trace/timer-shaft/SportRuler'; 30import { SpHiPerf } from './chart/SpHiPerf'; 31import { SearchSdkBean } from '../bean/SearchFuncBean'; 32import { info } from '../../log/Log'; 33import { 34 drawFlagLineSegment, 35 drawLines, 36 drawLinkLines, 37 drawLogsLineSegment, 38 drawWakeUp, 39 drawWakeUpList, 40 LineType, 41 ns2x, 42 ns2xByTimeShaft, 43 PairPoint, 44 Rect, 45} from '../database/ui-worker/ProcedureWorkerCommon'; 46import { SpChartManager } from './chart/SpChartManager'; 47import { CpuStruct, WakeupBean } from '../database/ui-worker/cpu/ProcedureWorkerCPU'; 48import { ProcessStruct } from '../database/ui-worker/ProcedureWorkerProcess'; 49import { CpuFreqStruct } from '../database/ui-worker/ProcedureWorkerFreq'; 50import { CpuFreqLimitsStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; 51import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread'; 52import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc'; 53import { CpuStateStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuState'; 54import { HiPerfCpuStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfCPU2'; 55import { HiPerfProcessStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfProcess2'; 56import { HiPerfThreadStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfThread2'; 57import { HiPerfEventStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfEvent'; 58import { HiPerfReportStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfReport'; 59import { FpsStruct } from '../database/ui-worker/ProcedureWorkerFPS'; 60import { CpuAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerCpuAbility'; 61import { DiskAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerDiskIoAbility'; 62import { MemoryAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerMemoryAbility'; 63import { NetworkAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerNetworkAbility'; 64import { ClockStruct } from '../database/ui-worker/ProcedureWorkerClock'; 65import { Utils } from './trace/base/Utils'; 66import { IrqStruct } from '../database/ui-worker/ProcedureWorkerIrq'; 67import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank'; 68import { TabPaneCurrent } from './trace/sheet/TabPaneCurrent'; 69import { HeapStruct } from '../database/ui-worker/ProcedureWorkerHeap'; 70import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil'; 71import { HeapSnapshotStruct } from '../database/ui-worker/ProcedureWorkerHeapSnapshot'; 72import { HeapDataInterface } from '../../js-heap/HeapDataInterface'; 73import { LitTabs } from '../../base-ui/tabs/lit-tabs'; 74import { TraceRowConfig } from './trace/base/TraceRowConfig'; 75import { TabPaneCurrentSelection } from './trace/sheet/TabPaneCurrentSelection'; 76import { SpChartList } from './trace/SpChartList'; 77import './trace/SpChartList'; 78import { AppStartupStruct } from '../database/ui-worker/ProcedureWorkerAppStartup'; 79import { AllAppStartupStruct } from '../database/ui-worker/ProcedureWorkerAllAppStartup'; 80import { SoStruct } from '../database/ui-worker/ProcedureWorkerSoInit'; 81import { FrameDynamicStruct } from '../database/ui-worker/ProcedureWorkerFrameDynamic'; 82import { FrameAnimationStruct } from '../database/ui-worker/ProcedureWorkerFrameAnimation'; 83import { FrameSpacingStruct } from '../database/ui-worker/ProcedureWorkerFrameSpacing'; 84import { JsCpuProfilerStruct } from '../database/ui-worker/ProcedureWorkerCpuProfiler'; 85import { FileInfo } from '../../js-heap/model/UiStruct'; 86import { SnapshotStruct } from '../database/ui-worker/ProcedureWorkerSnapshot'; 87import { LogStruct } from '../database/ui-worker/ProcedureWorkerLog'; 88import { TabPaneFrequencySample } from './trace/sheet/cpu/TabPaneFrequencySample'; 89import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample'; 90import { TabPaneFlag } from './trace/timer-shaft/TabPaneFlag'; 91import { LitTabpane } from '../../base-ui/tabs/lit-tabpane'; 92import { HiPerfCallChartStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfCallChart'; 93import { InitAnalysis } from '../database/logic-worker/ProcedureLogicWorkerCommon'; 94import { searchCpuDataSender } from '../database/data-trafic/CpuDataSender'; 95import { resetVSync } from './chart/VSync'; 96import { QueryEnum } from '../database/data-trafic/utils/QueryEnum'; 97import { SpSystemTraceHtml } from './SpSystemTrace.html'; 98import { querySceneSearchFunc, querySearchFunc } from '../database/sql/Func.sql'; 99import { queryCpuKeyPathData } from '../database/sql/Cpu.sql'; 100import { LtpoStruct } from '../database/ui-worker/ProcedureWorkerLTPO'; 101import { HitchTimeStruct } from '../database/ui-worker/ProcedureWorkerHitchTime'; 102import { 103 spSystemTraceInit, 104 spSystemTraceInitElement, 105 spSystemTraceInitPointToEvent, 106 spSystemTraceShowStruct, 107} from './SpSystemTrace.init'; 108import { 109 spSystemTraceDrawJankLine, 110 spSystemTraceDrawTaskPollLine, 111 spSystemTraceDrawThreadLine, 112} from './SpSystemTrace.line'; 113import spSystemTraceOnClickHandler, { 114 spSystemTraceDocumentOnClick, 115 spSystemTraceDocumentOnKeyDown, 116 SpSystemTraceDocumentOnKeyPress, 117 spSystemTraceDocumentOnKeyUp, 118 spSystemTraceDocumentOnMouseDown, 119 spSystemTraceDocumentOnMouseMove, 120 spSystemTraceDocumentOnMouseOut, 121 spSystemTraceDocumentOnMouseUp, 122} from './SpSystemTrace.event'; 123 124function dpr(): number { 125 return window.devicePixelRatio || 1; 126} 127 128export class CurrentSlicesTime { 129 startTime: number | undefined; 130 endTime: number | undefined; 131} 132 133type HTMLDivElementAlias = HTMLDivElement | undefined | null; 134type FlagAlias = Flag | undefined | null; 135type SlicesTimeAlias = SlicesTime | undefined | null; 136 137@element('sp-system-trace') 138export class SpSystemTrace extends BaseElement { 139 mouseCurrentPosition = 0; 140 offsetMouse = 0; 141 isMouseLeftDown = false; 142 static scrollViewWidth = 0; 143 static isCanvasOffScreen = true; 144 static DATA_DICT: Map<number, string> = new Map<number, string>(); 145 static DATA_TASK_POOL_CALLSTACK: Map<number, { id: number; ts: number; dur: number; name: string }> = new Map< 146 number, 147 { id: number; ts: number; dur: number; name: string } 148 >(); 149 static SDK_CONFIG_MAP: any; 150 static sliceRangeMark: any; 151 static wakeupList: Array<WakeupBean> = []; 152 static keyPathList: Array<CpuStruct> = []; 153 static jsProfilerMap: Map<number, any> = new Map<number, any>(); 154 times: Set<number> = new Set<number>(); 155 currentSlicesTime: CurrentSlicesTime = new CurrentSlicesTime(); 156 intersectionObserver: IntersectionObserver | undefined; 157 tipEL: HTMLDivElementAlias; 158 rowsEL: HTMLDivElementAlias; 159 rowsPaneEL: HTMLDivElementAlias; 160 stateRowsId: Array<object> = []; 161 spacerEL: HTMLDivElementAlias; 162 visibleRows: Array<TraceRow<any>> = []; 163 invisibleRows: Array<TraceRow<any>> = []; 164 collectRows: Array<TraceRow<any>> = []; 165 currentRow: TraceRow<any> | undefined | null; 166 keyboardEnable = true; 167 mouseEventEnable = true; 168 currentRowType = ''; /*保存当前鼠标所在行的类型*/ 169 observerScrollHeightEnable: boolean = false; 170 observerScrollHeightCallback: Function | undefined; 171 favoriteChartListEL: SpChartList | undefined | null; 172 // @ts-ignore 173 observer = new ResizeObserver((entries) => { 174 if (this.observerScrollHeightEnable && this.observerScrollHeightCallback) { 175 this.observerScrollHeightCallback(); 176 } 177 }); 178 static btnTimer: any = null; 179 isMousePointInSheet = false; 180 hoverFlag: FlagAlias; 181 selectFlag: FlagAlias; 182 slicestime: SlicesTimeAlias; 183 public timerShaftEL: TimerShaftElement | null | undefined; 184 public traceSheetEL: TraceSheet | undefined | null; 185 public rangeSelect!: RangeSelect; 186 chartManager: SpChartManager | undefined | null; 187 loadTraceCompleted: boolean = false; 188 rangeTraceRow: Array<TraceRow<any>> | undefined = []; 189 canvasFavoritePanelCtx: CanvasRenderingContext2D | null | undefined; 190 canvasPanel: HTMLCanvasElement | null | undefined; //绘制取消收藏后泳道图 191 canvasPanelCtx: CanvasRenderingContext2D | undefined | null; 192 linkNodes: PairPoint[][] = []; 193 public currentClickRow: HTMLDivElement | undefined | null; 194 private litTabs: LitTabs | undefined | null; 195 eventMap: any = {}; 196 isSelectClick: boolean = false; 197 selectionParam: SelectionParam | undefined; 198 snapshotFiles: FileInfo | null | undefined; 199 tabCpuFreq: TabPaneFrequencySample | undefined | null; 200 tabCpuState: TabPaneCounterSample | undefined | null; 201 collapseAll: boolean = false; 202 currentCollectGroup: string = '1'; 203 private _list: Array<SlicesTime> = []; 204 expandRowList: Array<TraceRow<any>> = []; 205 _slicesList: Array<SlicesTime> = []; 206 _flagList: Array<any> = []; 207 208 set snapshotFile(data: FileInfo) { 209 this.snapshotFiles = data; 210 } 211 212 set slicesList(list: Array<SlicesTime>) { 213 this._slicesList = list; 214 } 215 216 set flagList(list: Array<any>) { 217 this._flagList = list; 218 } 219 220 //节流处理 221 throttle(fn: Function, t: number, ev?: any): Function { 222 let timerId: any = null; 223 return () => { 224 if (!timerId) { 225 timerId = setTimeout(function () { 226 if (ev) { 227 fn(ev); 228 } else { 229 fn(); 230 } 231 timerId = null; 232 }, t); 233 this.times.add(timerId); 234 } 235 }; 236 } 237 238 // 防抖处理 239 debounce(fn: Function, ms: number, ev?: any): Function { 240 let timerId: undefined | number; 241 return () => { 242 if (timerId) { 243 window.clearTimeout(timerId); 244 } else { 245 timerId = window.setTimeout(() => { 246 if (ev) { 247 fn(ev); 248 } else { 249 fn(); 250 } 251 timerId = undefined; 252 }, ms); 253 this.times.add(timerId); 254 } 255 }; 256 } 257 258 addPointPair(startPoint: PairPoint, endPoint: PairPoint): void { 259 if (startPoint.rowEL.collect) { 260 startPoint.rowEL.translateY = startPoint.rowEL.getBoundingClientRect().top - 195; 261 } else { 262 startPoint.rowEL.translateY = startPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 263 } 264 if (endPoint.rowEL.collect) { 265 endPoint.rowEL.translateY = endPoint.rowEL.getBoundingClientRect().top - 195; 266 } else { 267 endPoint.rowEL.translateY = endPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 268 } 269 startPoint.y = startPoint.rowEL!.translateY! + startPoint.offsetY; 270 endPoint.y = endPoint.rowEL!.translateY! + endPoint.offsetY; 271 startPoint.backrowEL = startPoint.rowEL; 272 endPoint.backrowEL = endPoint.rowEL; 273 this.linkNodes.push([startPoint, endPoint]); 274 } 275 276 clearPointPair(): void { 277 this.linkNodes.length = 0; 278 } 279 280 removeLinkLinesByBusinessType(...businessTypes: string[]): void { 281 this.linkNodes = this.linkNodes.filter((pointPair) => { 282 return businessTypes.indexOf(pointPair[0].business) <= -1; 283 }); 284 } 285 286 hiddenLinkLinesByBusinessType(...businessTypes: string[]): void { 287 this.linkNodes.map((value) => { 288 if (businessTypes.indexOf(value[0].business) !== -1) { 289 value[0].hidden = true; 290 value[1].hidden = true; 291 } 292 }); 293 } 294 295 showLinkLinesByBusinessType(...businessTypes: string[]): void { 296 this.linkNodes.map((value) => { 297 if (businessTypes.indexOf(value[0].business) !== -1) { 298 value[0].hidden = false; 299 value[1].hidden = false; 300 } 301 }); 302 } 303 304 initElements(): void { 305 spSystemTraceInitElement(this); 306 } 307 308 // 清除上一次点击调用栈产生的三角旗子 309 clearTriangle(flagList: Array<Flag>): void { 310 this.timerShaftEL!.sportRuler!.times = []; 311 for (let i = 0; i < flagList.length; i++) { 312 if (flagList[i].type === 'triangle') { 313 flagList.splice(i, 1); 314 i--; 315 } 316 } 317 } 318 319 pushPidToSelection(selection: SelectionParam, id: string): void { 320 let pid = parseInt(id); 321 if (!selection.processIds.includes(pid)) { 322 selection.processIds.push(pid); 323 } 324 } 325 326 getCollectRows(condition: (row: TraceRow<any>) => boolean): Array<TraceRow<any>> { 327 return this.favoriteChartListEL!.getCollectRows(condition); 328 } 329 330 createPointEvent(it: TraceRow<any>) { 331 let event = this.eventMap[`${it.rowType}`]; 332 if (event) { 333 return event; 334 } else { 335 if (it.rowType === TraceRow.ROW_TYPE_HEAP) { 336 event = it.name; 337 } else if (it.rowType === TraceRow.ROW_TYPE_HIPERF_CPU) { 338 event = 'HiPerf Cpu'; 339 if (it.rowId === 'HiPerf-cpu-merge') { 340 event = 'HiPerf'; 341 } 342 } else if (it.rowType === TraceRow.ROW_TYPE_FILE_SYSTEM) { 343 event = this.handleFileSystemType(it, event); 344 } else if (it.rowType === TraceRow.ROW_TYPE_STATE_ENERGY) { 345 event = it.name; 346 } else if (it.rowType === TraceRow.ROW_TYPE_VM_TRACKER) { 347 if (it.rowParentId === '') { 348 event = 'VM Tracker'; 349 } else { 350 event = it.name; 351 } 352 } else if (it.rowType === TraceRow.ROW_TYPE_JANK) { 353 if (it.rowId === 'frameTime' || it.rowParentId === 'frameTime') { 354 event = 'FrameTimeLine'; 355 } else if (it.hasAttribute('frame_type')) { 356 event = it.getAttribute('frame_type') + ''; 357 } 358 } else if (it.rowType === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) { 359 event = 'DeliverInputEvent'; 360 if (it.rowParentId === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) { 361 event = 'DeliverInputEvent Func'; 362 } 363 } else { 364 event = it.name; 365 } 366 return event; 367 } 368 } 369 370 private handleFileSystemType(it: TraceRow<any>, event: any) { 371 if (it.rowId === 'FileSystemLogicalWrite') { 372 event = 'FileSystem Logical Write'; 373 } else if (it.rowId === 'FileSystemLogicalRead') { 374 event = 'FileSystem Logical Read'; 375 } else if (it.rowId === 'FileSystemVirtualMemory') { 376 event = 'Page Fault Trace'; 377 } else if (it.rowId!.startsWith('FileSystemDiskIOLatency')) { 378 event = 'Disk I/O Latency'; 379 if (it.rowId!.startsWith('FileSystemDiskIOLatency-')) { 380 event = 'Bio Process'; 381 } 382 } 383 return event; 384 } 385 386 refreshFavoriteCanvas(): void { 387 this.favoriteChartListEL!.refreshFavoriteCanvas(); 388 } 389 390 expansionAllParentRow(currentRow: TraceRow<any>): void { 391 let parentRow = this.rowsEL!.querySelector<TraceRow<any>>( 392 `trace-row[row-id='${currentRow.rowParentId}'][folder][scene]` 393 ); 394 if (parentRow) { 395 parentRow.expansion = true; 396 if (this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${parentRow.rowParentId}'][folder]`)) { 397 this.expansionAllParentRow(parentRow); 398 } 399 } 400 } 401 402 canvasPanelConfig(): void { 403 this.canvasPanel!.style.left = `${this.timerShaftEL!.canvas!.offsetLeft!}px`; 404 this.canvasPanel!.width = this.canvasPanel!.offsetWidth * dpr(); 405 this.canvasPanel!.height = this.canvasPanel!.offsetHeight * dpr(); 406 this.canvasPanelCtx!.scale(dpr(), dpr()); 407 } 408 409 getScrollWidth(): number { 410 let totalScrollDiv, 411 scrollDiv, 412 overflowDiv = document.createElement('div'); 413 overflowDiv.style.cssText = 'position:absolute; top:-2000px;width:200px; height:200px; overflow:hidden;'; 414 totalScrollDiv = document.body.appendChild(overflowDiv).clientWidth; 415 overflowDiv.style.overflowY = 'scroll'; 416 scrollDiv = overflowDiv.clientWidth; 417 document.body.removeChild(overflowDiv); 418 return totalScrollDiv - scrollDiv; 419 } 420 421 getShowTab(): Array<string> { 422 let tabpane = this.traceSheetEL!.shadowRoot!.querySelectorAll('lit-tabpane') as NodeListOf<LitTabpane>; 423 let showTab: Array<string> = []; 424 for (let pane of tabpane) { 425 if (pane.getAttribute('hidden') === 'false') { 426 showTab.push(pane.getAttribute('id') || ''); 427 } 428 } 429 return showTab; 430 } 431 432 timerShaftELFlagClickHandler = (flag: FlagAlias) => { 433 if (flag) { 434 setTimeout(() => { 435 if (TraceRow.rangeSelectObject) { 436 let showTab = this.getShowTab(); 437 this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag', ...showTab).setCurrentFlag(flag); 438 } else { 439 this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag').setCurrentFlag(flag); 440 } 441 }, 100); 442 } 443 }; 444 445 timerShaftELFlagChange = (hoverFlag: FlagAlias, selectFlag: FlagAlias) => { 446 this.hoverFlag = hoverFlag; 447 this.selectFlag = selectFlag; 448 this.refreshCanvas(true, 'flagChange'); 449 }; 450 451 timerShaftELRangeClick = (sliceTime: SlicesTimeAlias): void => { 452 if (sliceTime) { 453 setTimeout(() => { 454 if (TraceRow.rangeSelectObject) { 455 let showTab = this.getShowTab(); 456 this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current', ...showTab).setCurrentSlicesTime(sliceTime); 457 } else { 458 this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(sliceTime); 459 } 460 }, 0); 461 } 462 }; 463 464 timerShaftELRangeChange = (e: any): void => { 465 TraceRow.range = e; 466 if (TraceRow.rangeSelectObject) { 467 TraceRow.rangeSelectObject!.startX = Math.floor( 468 ns2x( 469 TraceRow.rangeSelectObject!.startNS!, 470 TraceRow.range?.startNS!, 471 TraceRow.range?.endNS!, 472 TraceRow.range?.totalNS!, 473 this.timerShaftEL!.sportRuler!.frame 474 ) 475 ); 476 TraceRow.rangeSelectObject!.endX = Math.floor( 477 ns2x( 478 TraceRow.rangeSelectObject!.endNS!, 479 TraceRow.range?.startNS!, 480 TraceRow.range?.endNS!, 481 TraceRow.range?.totalNS!, 482 this.timerShaftEL!.sportRuler!.frame 483 ) 484 ); 485 } 486 //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知 487 this.linkNodes.forEach((it) => { 488 it[0].x = ns2xByTimeShaft(it[0].ns, this.timerShaftEL!); 489 it[1].x = ns2xByTimeShaft(it[1].ns, this.timerShaftEL!); 490 }); 491 this.invisibleRows.forEach((it) => (it.needRefresh = true)); 492 this.visibleRows.forEach((it) => (it.needRefresh = true)); 493 this.refreshCanvas(false, 'rangeChange'); 494 }; 495 tim: number = -1; 496 top: number = 0; 497 handler: any = undefined; 498 rowsElOnScroll = (e: any): void => { 499 this.linkNodes.forEach((itln) => { 500 if (itln[0].rowEL.collect) { 501 itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; 502 } else { 503 itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 504 } 505 if (itln[1].rowEL.collect) { 506 itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; 507 } else { 508 itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 509 } 510 itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; 511 itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; 512 }); 513 this.hoverStructNull(); 514 if (this.scrollTimer) { 515 clearTimeout(this.scrollTimer); 516 } 517 this.scrollTimer = setTimeout(() => { 518 TraceRow.range!.refresh = true; 519 requestAnimationFrame(() => this.refreshCanvas(false)); 520 }, 200); 521 requestAnimationFrame(() => this.refreshCanvas(false)); 522 }; 523 524 private scrollTimer: any; 525 526 favoriteRowsElOnScroll = (e: any): void => { 527 this.rowsElOnScroll(e); 528 }; 529 530 offset = 147; 531 532 getRowsContentHeight(): number { 533 return [...this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row:not([sleeping])`)] 534 .map((it) => it.clientHeight) 535 .reduce((acr, cur) => acr + cur, 0); 536 } 537 538 // refresh main canvas and favorite canvas 539 refreshCanvas(cache: boolean, from?: string): void { 540 if (this.visibleRows.length === 0) { 541 return; 542 } 543 //clear main canvas 544 this.canvasPanelCtx!.clearRect(0, 0, this.canvasPanel!.offsetWidth, this.canvasPanel!.offsetHeight); 545 this.favoriteChartListEL!.clearRect(); 546 //draw lines for main canvas 547 let rowsContentHeight = this.getRowsContentHeight(); 548 let canvasHeight = 549 rowsContentHeight > this.canvasPanel!.clientHeight ? this.canvasPanel!.clientHeight : rowsContentHeight; 550 drawLines(this.canvasPanelCtx!, TraceRow.range?.xs || [], canvasHeight, this.timerShaftEL!.lineColor()); 551 //draw lines for favorite canvas 552 this.favoriteChartListEL?.drawLines(TraceRow.range?.xs, this.timerShaftEL!.lineColor()); // chart list 553 554 //canvas translate 555 this.canvasPanel!.style.transform = `translateY(${this.rowsPaneEL!.scrollTop}px)`; 556 //draw trace row 557 this.visibleRows.forEach((v, i) => { 558 if (v.collect) { 559 v.translateY = v.getBoundingClientRect().top - 195; 560 } else { 561 v.translateY = v.offsetTop - this.rowsPaneEL!.scrollTop; 562 } 563 v.draw(cache); 564 }); 565 this.drawAllLines(); 566 } 567 568 drawWakeUpLine(): void { 569 //draw wakeup for main canvas 570 drawWakeUp( 571 this.canvasPanelCtx, 572 CpuStruct.wakeupBean, 573 TraceRow.range!.startNS, 574 TraceRow.range!.endNS, 575 TraceRow.range!.totalNS, 576 { 577 x: 0, 578 y: 0, 579 width: TraceRow.FRAME_WIDTH, 580 height: this.canvasPanel!.clientHeight!, 581 } as Rect 582 ); 583 this.favoriteChartListEL?.drawWakeUp(); 584 // draw wakeuplist for main canvas 585 for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) { 586 if (i + 1 == SpSystemTrace.wakeupList.length) { 587 return; 588 } 589 drawWakeUpList( 590 this.canvasPanelCtx, 591 SpSystemTrace.wakeupList[i + 1], 592 TraceRow.range!.startNS, 593 TraceRow.range!.endNS, 594 TraceRow.range!.totalNS, 595 { 596 x: 0, 597 y: 0, 598 width: this.timerShaftEL!.canvas!.clientWidth, 599 height: this.canvasPanel!.clientHeight!, 600 } as Rect 601 ); 602 this.favoriteChartListEL?.drawWakeUpList(SpSystemTrace.wakeupList[i + 1]); 603 } 604 } 605 606 drawAllLines(): void { 607 // draw flag line segment for canvas 608 drawFlagLineSegment( 609 this.canvasPanelCtx, 610 this.hoverFlag, 611 this.selectFlag, 612 { 613 x: 0, 614 y: 0, 615 width: this.timerShaftEL?.canvas?.clientWidth, 616 height: this.canvasPanel?.clientHeight, 617 }, 618 this.timerShaftEL! 619 ); 620 this.favoriteChartListEL?.drawFlagLineSegment(this.hoverFlag, this.selectFlag, this.timerShaftEL!); 621 this.drawWakeUpLine(); 622 //draw system logs line segment for canvas 623 drawLogsLineSegment( 624 this.canvasPanelCtx, 625 this.traceSheetEL?.systemLogFlag, 626 { 627 x: 0, 628 y: 0, 629 width: this.timerShaftEL?.canvas?.clientWidth, 630 height: this.canvasPanel?.clientHeight, 631 }, 632 this.timerShaftEL! 633 ); 634 this.favoriteChartListEL?.drawLogsLineSegment(this.traceSheetEL!.systemLogFlag, this.timerShaftEL!); 635 636 // Draw the connection curve 637 if (this.linkNodes && this.linkNodes.length > 0) { 638 drawLinkLines( 639 this.canvasPanelCtx!, 640 this.linkNodes, 641 this.timerShaftEL!, 642 false, 643 this.favoriteChartListEL!.clientHeight 644 ); 645 this.favoriteChartListEL?.drawLinkLines( 646 this.linkNodes, 647 this.timerShaftEL!, 648 true, 649 this.favoriteChartListEL!.clientHeight 650 ); 651 } 652 } 653 654 drawAllLine(row: TraceRow<any>) { 655 let context: CanvasRenderingContext2D; 656 if (row.currentContext) { 657 context = row.currentContext; 658 } else { 659 context = row.collect ? this.canvasFavoritePanelCtx! : this.canvasPanelCtx!; 660 } 661 let startNS = TraceRow.range!.startNS; 662 let endNS = TraceRow.range!.endNS; 663 let totalNS = TraceRow.range!.totalNS; 664 drawFlagLineSegment(context, this.hoverFlag, this.selectFlag, row.frame, this.timerShaftEL!); 665 drawWakeUp(context, CpuStruct.wakeupBean, startNS, endNS, totalNS, row.frame); 666 for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) { 667 if (i + 1 == SpSystemTrace.wakeupList.length) { 668 return; 669 } 670 drawWakeUpList(context, SpSystemTrace.wakeupList[i + 1], startNS, endNS, totalNS, row.frame); 671 } 672 drawLogsLineSegment(context, this.traceSheetEL?.systemLogFlag, row.frame, this.timerShaftEL!); 673 } 674 675 documentOnMouseDown = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseDown(this, ev); 676 677 onContextMenuHandler = (e: Event): void => { 678 setTimeout(() => { 679 for (let key of this.keyPressMap.keys()) { 680 if (this.keyPressMap.get(key)) { 681 this.timerShaftEL?.stopWASD({ key: key }); 682 this.keyPressMap.set(key, false); 683 } 684 } 685 }, 100); 686 }; 687 688 documentOnMouseUp = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseUp(this, ev); 689 690 cancelDrag(): void { 691 this.rangeSelect.drag = false; 692 this.rangeSelect.isMouseDown = false; 693 TraceRow.rangeSelectObject = { 694 startX: 0, 695 endX: 0, 696 startNS: 0, 697 endNS: 0, 698 }; 699 } 700 701 documentOnMouseOut = (ev: MouseEvent) => spSystemTraceDocumentOnMouseOut(this, ev); 702 703 keyPressMap: Map<string, boolean> = new Map([ 704 ['w', false], 705 ['s', false], 706 ['a', false], 707 ['d', false], 708 ['f', false], 709 ]); 710 711 documentOnKeyDown = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyDown(this, ev); 712 713 documentOnKeyPress = (ev: KeyboardEvent): void => SpSystemTraceDocumentOnKeyPress(this, ev); 714 715 verticalScrollToRow(): void { 716 if (this.currentRow) { 717 //@ts-ignore 718 this.currentRow.scrollIntoViewIfNeeded(); 719 } 720 } 721 722 setCurrentSlicesTime(): void { 723 if (CpuStruct.selectCpuStruct) { 724 if (CpuStruct.selectCpuStruct.startTime && CpuStruct.selectCpuStruct.dur) { 725 this.currentSlicesTime.startTime = CpuStruct.selectCpuStruct.startTime; 726 this.currentSlicesTime.endTime = CpuStruct.selectCpuStruct.startTime + CpuStruct.selectCpuStruct.dur; 727 } 728 } else if (ThreadStruct.selectThreadStruct) { 729 if (ThreadStruct.selectThreadStruct.startTime && ThreadStruct.selectThreadStruct.dur) { 730 this.currentSlicesTime.startTime = ThreadStruct.selectThreadStruct.startTime; 731 this.currentSlicesTime.endTime = 732 ThreadStruct.selectThreadStruct.startTime + ThreadStruct.selectThreadStruct.dur; 733 } 734 } else if (FuncStruct.selectFuncStruct) { 735 if (FuncStruct.selectFuncStruct.startTs && FuncStruct.selectFuncStruct.dur) { 736 this.currentSlicesTime.startTime = FuncStruct.selectFuncStruct.startTs; 737 this.currentSlicesTime.endTime = FuncStruct.selectFuncStruct.startTs + FuncStruct.selectFuncStruct.dur; 738 } 739 } else if (IrqStruct.selectIrqStruct) { 740 if (IrqStruct.selectIrqStruct.startNS && IrqStruct.selectIrqStruct.dur) { 741 this.currentSlicesTime.startTime = IrqStruct.selectIrqStruct.startNS; 742 this.currentSlicesTime.endTime = IrqStruct.selectIrqStruct.startNS + IrqStruct.selectIrqStruct.dur; 743 } 744 } else if (TraceRow.rangeSelectObject) { 745 this.currentRow = undefined; 746 if (TraceRow.rangeSelectObject.startNS && TraceRow.rangeSelectObject.endNS) { 747 this.currentSlicesTime.startTime = TraceRow.rangeSelectObject.startNS; 748 this.currentSlicesTime.endTime = TraceRow.rangeSelectObject.endNS; 749 } 750 } else if (JankStruct.selectJankStruct) { 751 if (JankStruct.selectJankStruct.ts && JankStruct.selectJankStruct.dur) { 752 this.currentSlicesTime.startTime = JankStruct.selectJankStruct.ts; 753 this.currentSlicesTime.endTime = JankStruct.selectJankStruct.ts + JankStruct.selectJankStruct.dur; 754 } 755 } else { 756 this.currentSlicesTime.startTime = 0; 757 this.currentSlicesTime.endTime = 0; 758 } 759 } 760 761 public setSLiceMark = (shiftKey: boolean): SlicesTime | null | undefined => { 762 const selectedStruct: any = 763 CpuStruct.selectCpuStruct || 764 ThreadStruct.selectThreadStruct || 765 FuncStruct.selectFuncStruct || 766 IrqStruct.selectIrqStruct || 767 TraceRow.rangeSelectObject || 768 JankStruct.selectJankStruct || 769 AppStartupStruct.selectStartupStruct || 770 SoStruct.selectSoStruct || 771 AllAppStartupStruct.selectStartupStruct || 772 FrameAnimationStruct.selectFrameAnimationStruct || 773 JsCpuProfilerStruct.selectJsCpuProfilerStruct; 774 this.calculateSlicesTime(selectedStruct, shiftKey); 775 776 return this.slicestime; 777 }; 778 779 private calculateSlicesTime(selectedStruct: any, shiftKey: boolean): void { 780 if (selectedStruct) { 781 const startTs = selectedStruct.startTs || selectedStruct.startTime || selectedStruct.startNS || 0; 782 const dur = selectedStruct.dur || selectedStruct.totalTime || selectedStruct.endNS || 0; 783 this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, startTs + dur, shiftKey); 784 } else { 785 this.slicestime = this.timerShaftEL?.setSlicesMark(); 786 } 787 } 788 789 stopWASD = (): void => { 790 setTimeout((): void => { 791 for (let key of this.keyPressMap.keys()) { 792 if (this.keyPressMap.get(key)) { 793 this.timerShaftEL?.stopWASD({ key: key }); 794 this.keyPressMap.set(key, false); 795 } 796 } 797 }, 100); 798 }; 799 800 // 一直按着回车键的时候执行搜索功能 801 continueSearch = (ev: KeyboardEvent) => { 802 if (ev.key === 'Enter') { 803 if (ev.shiftKey) { 804 this.dispatchEvent( 805 new CustomEvent('trace-previous-data', { 806 detail: { down: true }, 807 composed: false, 808 }) 809 ); 810 } else { 811 this.dispatchEvent( 812 new CustomEvent('trace-next-data', { 813 detail: { down: true }, 814 composed: false, 815 }) 816 ); 817 } 818 } 819 }; 820 821 documentOnKeyUp = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyUp(this, ev); 822 823 /** 824 * 根据传入的参数实现卡尺和旗子的快捷跳转 825 * @param list 要跳转的数组 826 * @param type 标记类型(卡尺和旗子) 827 * @param direction 跳转方向(前一个/后一个) 828 */ 829 MarkJump(list: Array<any>, type: string, direction: string): void { 830 this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet'); 831 let find = list.find((it) => it.selected); 832 if (!find) { 833 // 如果当前没有选中的,就选中第一个 834 list.forEach((it) => (it.selected = false)); 835 list[0].selected = true; 836 } else { 837 for (let i = 0; i < list.length; i++) { 838 // 将当前数组中选中的那条数据改为未选中 839 if (list[i].selected) { 840 list[i].selected = false; 841 if (direction === 'previous') { 842 if (i === 0) { 843 // 如果当前选中的是第一个,就循环到最后一个上 844 list[list.length - 1].selected = true; 845 break; 846 } else { 847 // 选中当前的上一个 848 list[i - 1].selected = true; 849 break; 850 } 851 } else if (direction === 'next') { 852 if (i === list.length - 1) { 853 // 如果当前选中的是最后一个,就循环到第一个上 854 list[0].selected = true; 855 break; 856 } else { 857 // 选中当前的下一个 858 list[i + 1].selected = true; 859 break; 860 } 861 } 862 } 863 } 864 } 865 866 if (type === 'flag') { 867 let currentPane = this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag'); 868 list.forEach((flag, index) => { 869 this.timerShaftEL!.sportRuler!.drawTriangle(flag.time, flag.type); 870 if (flag.selected) { 871 // 修改当前选中的旗子对应的表格中某行的背景 872 currentPane!.setTableSelection(index + 1); 873 } 874 }); 875 } else if (type === 'slice') { 876 this.refreshCanvas(true); 877 let currentPane = this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current'); 878 list.forEach((slice, index) => { 879 if (slice.selected) { 880 // 修改当前选中的卡尺对应的表格中某行的背景 881 currentPane!.setTableSelection(index + 1); 882 } 883 }); 884 } 885 } 886 887 isMouseInSheet = (ev: MouseEvent) => { 888 this.isMousePointInSheet = 889 this.traceSheetEL?.getAttribute('mode') != 'hidden' && 890 ev.offsetX > this.traceSheetEL!.offsetLeft && 891 ev.offsetY > this.traceSheetEL!.offsetTop; 892 return this.isMousePointInSheet; 893 }; 894 895 favoriteChangeHandler = (row: TraceRow<any>): void => { 896 info('favoriteChangeHandler', row.frame, row.offsetTop, row.offsetHeight); 897 }; 898 899 verticalScrollHandler = (row: TraceRow<any>): void => { 900 row.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); 901 }; 902 903 /** 904 * 根据选择的traceRow 处理foler 905 * @param currentRow 当前点击checkbox的row 906 */ 907 setParentCheckStatus(currentRow: TraceRow<any>): void { 908 if (currentRow.parentRowEl?.folder && currentRow.parentRowEl?.childrenList) { 909 const parent = currentRow.parentRowEl; 910 const childrenList = parent.childrenList; 911 const selectList = []; 912 const unSelectList = []; 913 for (const child of childrenList) { 914 if (child.offsetParent === null) { 915 continue; 916 } 917 if (child.checkType === '2') { 918 selectList.push(child); 919 } else { 920 unSelectList.push(child); 921 } 922 } 923 if (unSelectList.length === 0) { 924 parent.setAttribute('check-type', '2'); 925 parent.rangeSelect = true; 926 parent.checkBoxEL!.checked = true; 927 parent.checkBoxEL!.indeterminate = false; 928 } else if (selectList.length === 0) { 929 parent.setAttribute('check-type', '0'); 930 parent.rangeSelect = false; 931 parent.checkBoxEL!.checked = false; 932 parent.checkBoxEL!.indeterminate = false; 933 } else { 934 parent.setAttribute('check-type', '1'); 935 parent.rangeSelect = false; 936 parent.checkBoxEL!.checked = false; 937 parent.checkBoxEL!.indeterminate = true; 938 } 939 } 940 } 941 942 /** 943 * 处理点击checkbox的逻辑 944 * @param row 当前点击checkbox的row 945 */ 946 selectChangeHandler = (row: TraceRow<any>): void => { 947 this.setParentCheckStatus(row); 948 const rows = [ 949 ...this.shadowRoot!.querySelectorAll<TraceRow<any>>("trace-row[check-type='2']"), 950 ...this.favoriteChartListEL!.getAllSelectCollectRows(), 951 ]; 952 this.isSelectClick = true; 953 this.rangeSelect.rangeTraceRow = rows; 954 let changeTraceRows: Array<TraceRow<any>> = []; 955 if (this.rangeTraceRow!.length < rows.length) { 956 rows!.forEach((currentTraceRow: TraceRow<any>) => { 957 let changeFilter = this.rangeTraceRow!.filter( 958 (prevTraceRow: TraceRow<any>) => prevTraceRow === currentTraceRow 959 ); 960 if (changeFilter.length < 1) { 961 changeTraceRows.push(currentTraceRow); 962 } 963 }); 964 if (changeTraceRows.length > 0) { 965 changeTraceRows!.forEach((changeTraceRow: TraceRow<any>) => { 966 let pointEvent = this.createPointEvent(changeTraceRow); 967 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 968 action: 'trace_row', 969 event: pointEvent, 970 }); 971 }); 972 } 973 } 974 this.rangeTraceRow = rows; 975 this.rangeSelect.selectHandler?.(this.rangeSelect.rangeTraceRow, false); 976 }; 977 inFavoriteArea: boolean | undefined; 978 documentOnMouseMove = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseMove(this, ev); 979 980 hoverStructNull() { 981 CpuStruct.hoverCpuStruct = undefined; 982 CpuFreqStruct.hoverCpuFreqStruct = undefined; 983 ThreadStruct.hoverThreadStruct = undefined; 984 FuncStruct.hoverFuncStruct = undefined; 985 HiPerfCpuStruct.hoverStruct = undefined; 986 HiPerfProcessStruct.hoverStruct = undefined; 987 HiPerfThreadStruct.hoverStruct = undefined; 988 HiPerfEventStruct.hoverStruct = undefined; 989 HiPerfReportStruct.hoverStruct = undefined; 990 CpuStateStruct.hoverStateStruct = undefined; 991 CpuAbilityMonitorStruct.hoverCpuAbilityStruct = undefined; 992 DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined; 993 MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = undefined; 994 NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = undefined; 995 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined; 996 FpsStruct.hoverFpsStruct = undefined; 997 ClockStruct.hoverClockStruct = undefined; 998 IrqStruct.hoverIrqStruct = undefined; 999 HeapStruct.hoverHeapStruct = undefined; 1000 JankStruct.hoverJankStruct = undefined; 1001 AppStartupStruct.hoverStartupStruct = undefined; 1002 SoStruct.hoverSoStruct = undefined; 1003 HeapSnapshotStruct.hoverSnapshotStruct = undefined; 1004 FrameAnimationStruct.hoverFrameAnimationStruct = undefined; 1005 FrameDynamicStruct.hoverFrameDynamicStruct = undefined; 1006 FrameSpacingStruct.hoverFrameSpacingStruct = undefined; 1007 JsCpuProfilerStruct.hoverJsCpuProfilerStruct = undefined; 1008 SnapshotStruct.hoverSnapshotStruct = undefined; 1009 HiPerfCallChartStruct.hoverPerfCallCutStruct = undefined; 1010 this.tipEL!.style.display = 'none'; 1011 return this; 1012 } 1013 1014 selectStructNull() { 1015 CpuStruct.selectCpuStruct = undefined; 1016 CpuStruct.wakeupBean = null; 1017 CpuFreqStruct.selectCpuFreqStruct = undefined; 1018 ThreadStruct.selectThreadStruct = undefined; 1019 FuncStruct.selectFuncStruct = undefined; 1020 SpHiPerf.selectCpuStruct = undefined; 1021 CpuStateStruct.selectStateStruct = undefined; 1022 CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = undefined; 1023 ClockStruct.selectClockStruct = undefined; 1024 IrqStruct.selectIrqStruct = undefined; 1025 JankStruct.selectJankStruct = undefined; 1026 HeapStruct.selectHeapStruct = undefined; 1027 AppStartupStruct.selectStartupStruct = undefined; 1028 SoStruct.selectSoStruct = undefined; 1029 HeapSnapshotStruct.selectSnapshotStruct = undefined; 1030 FrameSpacingStruct.selectFrameSpacingStruct = undefined; 1031 FrameAnimationStruct.selectFrameAnimationStruct = undefined; 1032 FrameDynamicStruct.selectFrameDynamicStruct = undefined; 1033 JsCpuProfilerStruct.selectJsCpuProfilerStruct = undefined; 1034 SnapshotStruct.selectSnapshotStruct = undefined; 1035 HiPerfCallChartStruct.selectStruct = undefined; 1036 AllAppStartupStruct.selectStartupStruct = undefined; 1037 LtpoStruct.selectLtpoStruct = undefined; 1038 HitchTimeStruct.selectHitchTimeStruct = undefined; 1039 return this; 1040 } 1041 1042 isWASDKeyPress() { 1043 return ( 1044 this.keyPressMap.get('w') || this.keyPressMap.get('a') || this.keyPressMap.get('d') || this.keyPressMap.get('s') 1045 ); 1046 } 1047 1048 documentOnClick = (ev: MouseEvent) => spSystemTraceDocumentOnClick(this, ev); 1049 1050 clickEmptyArea() { 1051 this.queryAllTraceRow().forEach((it) => { 1052 it.checkType = '-1'; 1053 it.rangeSelect = false; 1054 }); 1055 this.rangeSelect.rangeTraceRow = []; 1056 TraceRow.rangeSelectObject = undefined; 1057 this.selectStructNull(); 1058 this.wakeupListNull(); 1059 this.observerScrollHeightEnable = false; 1060 this.selectFlag = null; 1061 this.timerShaftEL?.removeTriangle('inverted'); 1062 // 如果鼠标在SportRuler区域不隐藏tab页 1063 if (!SportRuler.isMouseInSportRuler) { 1064 this.traceSheetEL?.setAttribute('mode', 'hidden'); 1065 } 1066 this.removeLinkLinesByBusinessType('task', 'thread'); 1067 this.refreshCanvas(true); 1068 JankStruct.delJankLineFlag = true; 1069 } 1070 1071 //泳道图点击判定条件 1072 traceRowClickJudgmentConditions: Map<string, () => boolean> = new Map<string, () => boolean>([ 1073 [TraceRow.ROW_TYPE_CPU, (): boolean => CpuStruct.hoverCpuStruct !== null && CpuStruct.hoverCpuStruct !== undefined], 1074 [ 1075 TraceRow.ROW_TYPE_THREAD, 1076 (): boolean => ThreadStruct.hoverThreadStruct !== null && ThreadStruct.hoverThreadStruct !== undefined, 1077 ], 1078 [ 1079 TraceRow.ROW_TYPE_FUNC, 1080 (): boolean => FuncStruct.hoverFuncStruct !== null && FuncStruct.hoverFuncStruct !== undefined, 1081 ], 1082 [ 1083 TraceRow.ROW_TYPE_CPU_FREQ, 1084 (): boolean => CpuFreqStruct.hoverCpuFreqStruct !== null && CpuFreqStruct.hoverCpuFreqStruct !== undefined, 1085 ], 1086 [ 1087 TraceRow.ROW_TYPE_CPU_STATE, 1088 (): boolean => CpuStateStruct.hoverStateStruct !== null && CpuStateStruct.hoverStateStruct !== undefined, 1089 ], 1090 [ 1091 TraceRow.ROW_TYPE_CPU_FREQ_LIMIT, 1092 (): boolean => 1093 CpuFreqLimitsStruct.selectCpuFreqLimitsStruct !== null && 1094 CpuFreqLimitsStruct.selectCpuFreqLimitsStruct !== undefined, 1095 ], 1096 [ 1097 TraceRow.ROW_TYPE_CLOCK, 1098 (): boolean => ClockStruct.hoverClockStruct !== null && ClockStruct.hoverClockStruct !== undefined, 1099 ], 1100 [TraceRow.ROW_TYPE_IRQ, (): boolean => IrqStruct.hoverIrqStruct !== null && IrqStruct.hoverIrqStruct !== undefined], 1101 [ 1102 TraceRow.ROW_TYPE_APP_STARTUP, 1103 (): boolean => AppStartupStruct.hoverStartupStruct !== null && AppStartupStruct.hoverStartupStruct !== undefined, 1104 ], 1105 [ 1106 TraceRow.ROW_TYPE_ALL_APPSTARTUPS, 1107 (): boolean => 1108 AllAppStartupStruct.hoverStartupStruct !== null && AllAppStartupStruct.hoverStartupStruct !== undefined, 1109 ], 1110 [TraceRow.ROW_TYPE_STATIC_INIT, () => SoStruct.hoverSoStruct !== null && SoStruct.hoverSoStruct !== undefined], 1111 [TraceRow.ROW_TYPE_JANK, () => JankStruct.hoverJankStruct !== null && JankStruct.hoverJankStruct !== undefined], 1112 [TraceRow.ROW_TYPE_HEAP, () => HeapStruct.hoverHeapStruct !== null && HeapStruct.hoverHeapStruct !== undefined], 1113 [ 1114 TraceRow.ROW_TYPE_SYS_MEMORY_GPU_TOTAL, 1115 (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1116 ], 1117 [ 1118 TraceRow.ROW_TYPE_SYS_MEMORY_GPU_WINDOW, 1119 (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1120 ], 1121 [ 1122 TraceRow.ROW_TYPE_HEAP_SNAPSHOT, 1123 (): boolean => 1124 HeapSnapshotStruct.hoverSnapshotStruct !== null && HeapSnapshotStruct.hoverSnapshotStruct !== undefined, 1125 ], 1126 [ 1127 TraceRow.ROW_TYPE_FRAME_ANIMATION, 1128 (): boolean => 1129 FrameAnimationStruct.hoverFrameAnimationStruct !== null && 1130 FrameAnimationStruct.hoverFrameAnimationStruct !== undefined, 1131 ], 1132 [ 1133 TraceRow.ROW_TYPE_FRAME_DYNAMIC, 1134 (): boolean => 1135 FrameDynamicStruct.hoverFrameDynamicStruct !== null && FrameDynamicStruct.hoverFrameDynamicStruct !== undefined, 1136 ], 1137 [ 1138 TraceRow.ROW_TYPE_FRAME_SPACING, 1139 (): boolean => 1140 FrameSpacingStruct.hoverFrameSpacingStruct !== null && FrameSpacingStruct.hoverFrameSpacingStruct !== undefined, 1141 ], 1142 [ 1143 TraceRow.ROW_TYPE_JS_CPU_PROFILER, 1144 (): boolean => 1145 JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== null && 1146 JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== undefined, 1147 ], 1148 [ 1149 TraceRow.ROW_TYPE_PURGEABLE_TOTAL_ABILITY, 1150 (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1151 ], 1152 [ 1153 TraceRow.ROW_TYPE_PURGEABLE_PIN_ABILITY, 1154 (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1155 ], 1156 [ 1157 TraceRow.ROW_TYPE_PURGEABLE_TOTAL_VM, 1158 (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1159 ], 1160 [ 1161 TraceRow.ROW_TYPE_PURGEABLE_PIN_VM, 1162 (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1163 ], 1164 [ 1165 TraceRow.ROW_TYPE_DMA_ABILITY, 1166 (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1167 ], 1168 [ 1169 TraceRow.ROW_TYPE_DMA_VMTRACKER, 1170 (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1171 ], 1172 [ 1173 TraceRow.ROW_TYPE_GPU_MEMORY_ABILITY, 1174 (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1175 ], 1176 [ 1177 TraceRow.ROW_TYPE_GPU_MEMORY_VMTRACKER, 1178 (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1179 ], 1180 [ 1181 TraceRow.ROW_TYPE_GPU_RESOURCE_VMTRACKER, 1182 () => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1183 ], 1184 [ 1185 TraceRow.ROW_TYPE_VMTRACKER_SHM, 1186 () => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1187 ], 1188 [ 1189 TraceRow.ROW_TYPE_VM_TRACKER_SMAPS, 1190 () => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, 1191 ], 1192 [TraceRow.ROW_TYPE_LOGS, () => LogStruct.hoverLogStruct !== null && LogStruct.hoverLogStruct !== undefined], 1193 ]); 1194 1195 onClickHandler(clickRowType: string, row?: TraceRow<any>) { 1196 spSystemTraceOnClickHandler(this, clickRowType, row); 1197 } 1198 1199 makePoint( 1200 ts: number, 1201 dur: number, 1202 translateY: number, 1203 rowStruct: any, 1204 offsetY: number, 1205 business: string, 1206 lineType: LineType, 1207 isRight: boolean 1208 ): PairPoint { 1209 return { 1210 x: ns2xByTimeShaft(ts + dur, this.timerShaftEL!), 1211 y: translateY!, 1212 offsetY: offsetY, 1213 ns: ts + dur, 1214 rowEL: rowStruct!, 1215 isRight: isRight, 1216 business: business, 1217 lineType: lineType, 1218 }; 1219 } 1220 1221 drawTaskPollLine(row?: TraceRow<any>) { 1222 spSystemTraceDrawTaskPollLine(this, row); 1223 } 1224 drawJankLine(endParentRow: any, selectJankStruct: JankStruct, data: any) { 1225 spSystemTraceDrawJankLine(this, endParentRow, selectJankStruct, data); 1226 } 1227 1228 drawThreadLine(endParentRow: any, selectThreadStruct: ThreadStruct | undefined, data: any) { 1229 spSystemTraceDrawThreadLine(this, endParentRow, selectThreadStruct, data); 1230 } 1231 1232 getStartRow(selectRowId: number | undefined, collectList: any[]): any { 1233 let startRow = this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>( 1234 `trace-row[row-id='${selectRowId}'][row-type='thread']` 1235 ); 1236 if (!startRow) { 1237 for (let collectChart of collectList) { 1238 if (collectChart.rowId === selectRowId?.toString() && collectChart.rowType === 'thread') { 1239 startRow = collectChart; 1240 break; 1241 } 1242 } 1243 } 1244 return startRow; 1245 } 1246 1247 calculateStartY(startRow: any, selectThreadStruct: ThreadStruct): [number, any, number] { 1248 let startY = startRow!.translateY!; 1249 let startRowEl = startRow; 1250 let startOffSetY = 20 * 0.5; 1251 const startParentRow = this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>( 1252 `trace-row[row-id='${startRow.rowParentId}'][folder]` 1253 ); 1254 const expansionFlag = this.collectionHasThread(startRow); 1255 if (startParentRow && !startParentRow.expansion && expansionFlag) { 1256 startY = startParentRow.translateY!; 1257 startRowEl = startParentRow; 1258 startOffSetY = 10 * 0.5; 1259 } 1260 return [startY, startRowEl, startOffSetY]; 1261 } 1262 1263 calculateEndY(endParentRow: any, endRowStruct: any): [number, any, number] { 1264 let endY = endRowStruct.translateY!; 1265 let endRowEl = endRowStruct; 1266 let endOffSetY = 20 * 0.5; 1267 const expansionFlag = this.collectionHasThread(endRowStruct); 1268 if (!endParentRow.expansion && expansionFlag) { 1269 endY = endParentRow.translateY!; 1270 endRowEl = endParentRow; 1271 endOffSetY = 10 * 0.5; 1272 } 1273 return [endY, endRowEl, endOffSetY]; 1274 } 1275 1276 collectionHasThread(threadRow: any): boolean { 1277 const collectList = this.favoriteChartListEL!.getCollectRows(); 1278 for (let item of collectList!) { 1279 if (item.rowId === threadRow.rowId && item.rowType === threadRow.rowType) { 1280 return false; 1281 } 1282 } 1283 return true; 1284 } 1285 1286 translateByMouseMove(ev: MouseEvent): void { 1287 ev.preventDefault(); 1288 let offset = 0; 1289 if (this.offsetMouse === 0) { 1290 this.offsetMouse = ev.clientX; 1291 offset = ev.clientX - this.mouseCurrentPosition; 1292 } else { 1293 offset = ev.clientX - this.offsetMouse; 1294 } 1295 this.offsetMouse = ev.clientX; 1296 const rangeRuler = this.timerShaftEL?.getRangeRuler()!; 1297 1298 rangeRuler.translate(offset); 1299 } 1300 1301 private eventListener(): void { 1302 /** 1303 * 监听时间轴区间变化 1304 */ 1305 this.timerShaftEL!.rangeChangeHandler = this.timerShaftELRangeChange; 1306 this.timerShaftEL!.rangeClickHandler = this.timerShaftELRangeClick; 1307 this.timerShaftEL!.flagChangeHandler = this.timerShaftELFlagChange; 1308 this.timerShaftEL!.flagClickHandler = this.timerShaftELFlagClickHandler; 1309 /** 1310 * 监听rowsEL的滚动时间,刷新可见区域的trace-row组件的时间区间(将触发trace-row组件重绘) 1311 */ 1312 this.rowsPaneEL?.addEventListener('scroll', this.rowsElOnScroll, { 1313 passive: true, 1314 }); 1315 this.favoriteChartListEL?.addEventListener('scroll', this.favoriteRowsElOnScroll, { 1316 passive: true, 1317 }); 1318 /** 1319 * 监听document的mousemove事件 坐标通过换算后找到当前鼠标所在的trace-row组件,将坐标传入 1320 */ 1321 this.addEventListener('mousemove', this.documentOnMouseMove); 1322 this.addEventListener('click', this.documentOnClick); 1323 this.addEventListener('mousedown', this.documentOnMouseDown); 1324 this.addEventListener('mouseup', this.documentOnMouseUp); 1325 this.addEventListener('mouseout', this.documentOnMouseOut); 1326 1327 document.addEventListener('keydown', this.documentOnKeyDown); 1328 document.addEventListener('keypress', this.documentOnKeyPress); 1329 document.addEventListener('keyup', this.documentOnKeyUp); 1330 document.addEventListener('contextmenu', this.onContextMenuHandler); 1331 this.wheelListener(); 1332 } 1333 1334 private wheelListener() { 1335 document.addEventListener( 1336 'wheel', 1337 (e) => { 1338 if (e.ctrlKey) { 1339 if (e.deltaY > 0) { 1340 e.preventDefault(); 1341 e.stopPropagation(); 1342 let eventS = new KeyboardEvent('keypress', { 1343 key: 's', 1344 code: '83', 1345 keyCode: 83, 1346 }); 1347 this.timerShaftEL!.documentOnKeyPress(eventS); 1348 setTimeout(() => { 1349 this.timerShaftEL!.documentOnKeyUp(eventS); 1350 }, 200); 1351 } 1352 if (e.deltaY < 0) { 1353 e.preventDefault(); 1354 e.stopPropagation(); 1355 let eventW = new KeyboardEvent('keypress', { 1356 key: 'w', 1357 code: '87', 1358 keyCode: 87, 1359 }); 1360 this.timerShaftEL!.documentOnKeyPress(eventW); 1361 setTimeout(() => { 1362 this.timerShaftEL!.documentOnKeyUp(eventW); 1363 }, 200); 1364 } 1365 } 1366 }, 1367 { passive: false } 1368 ); 1369 } 1370 1371 connectedCallback(): void { 1372 this.initPointToEvent(); 1373 this.eventListener(); 1374 /** 1375 * 泳道图中添加ctrl+鼠标滚轮事件,对泳道图进行放大缩小。 1376 * 鼠标滚轮事件转化为键盘事件,keyPress和keyUp两个事件需要配合使用, 1377 * 否则泳道图会一直放大或一直缩小。 1378 * setTimeout()函数中的时间参数可以控制鼠标滚轮的频率。 1379 */ 1380 SpApplication.skinChange2 = (val: boolean) => { 1381 this.timerShaftEL?.render(); 1382 }; 1383 window.subscribe(window.SmartEvent.UI.UploadSOFile, (data) => { 1384 this.chartManager?.importSoFileUpdate().then(() => { 1385 window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Import So File' }); 1386 let updateCanvas = this.traceSheetEL?.updateRangeSelect(); 1387 if (updateCanvas) { 1388 this.refreshCanvas(true); 1389 } 1390 }); 1391 }); 1392 1393 window.subscribe(window.SmartEvent.UI.KeyPath, (data) => { 1394 this.invisibleRows.forEach((it) => (it.needRefresh = true)); 1395 this.visibleRows.forEach((it) => (it.needRefresh = true)); 1396 if (data.length === 0) { 1397 // clear 1398 SpSystemTrace.keyPathList = []; 1399 this.refreshCanvas(false); 1400 } else { 1401 // draw 1402 queryCpuKeyPathData(data).then((res) => { 1403 SpSystemTrace.keyPathList = res; 1404 this.refreshCanvas(false); 1405 }); 1406 } 1407 }); 1408 1409 window.subscribe(window.SmartEvent.UI.CheckALL, (data) => { 1410 this.getCollectRows((row) => row.rowParentId === data.rowId).forEach((it) => { 1411 it.checkType = data.isCheck ? '2' : '0'; 1412 }); 1413 }); 1414 window.subscribe(window.SmartEvent.UI.HoverNull, () => this.hoverStructNull()); 1415 } 1416 1417 favoriteAreaSearchHandler(row: TraceRow<any>): void { 1418 if (this.timerShaftEL!.collecBtn!.hasAttribute('close')) { 1419 this.timerShaftEL!.collecBtn!.removeAttribute('close'); 1420 this.favoriteChartListEL!.showCollectArea(); 1421 } 1422 this.favoriteChartListEL?.expandSearchRowGroup(row); 1423 } 1424 1425 scrollToProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) { 1426 let traceRow = 1427 this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`) || 1428 this.favoriteChartListEL!.getCollectRow((row) => row.rowId === rowId && row.rowType === rowType); 1429 if (traceRow?.collect) { 1430 this.favoriteChartListEL!.scroll({ 1431 top: 1432 (traceRow?.offsetTop || 0) - 1433 this.favoriteChartListEL!.getCanvas()!.offsetHeight + 1434 (traceRow?.offsetHeight || 0), 1435 left: 0, 1436 behavior: smooth ? 'smooth' : undefined, 1437 }); 1438 } else { 1439 let row = this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`); 1440 if (row && !row.expansion) { 1441 row.expansion = true; 1442 } 1443 if (traceRow && traceRow.offsetTop >= 0 && traceRow.offsetHeight >= 0) { 1444 this.rowsPaneEL!.scroll({ 1445 top: (traceRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + (traceRow?.offsetHeight || 0), 1446 left: 0, 1447 behavior: smooth ? 'smooth' : undefined, 1448 }); 1449 } 1450 } 1451 } 1452 1453 scrollToDepth(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true, depth: number) { 1454 let rootRow = 1455 this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`) || 1456 this.favoriteChartListEL!.getCollectRow((row) => row.rowId === rowId && row.rowType === rowType); 1457 if (rootRow && rootRow!.collect) { 1458 this.favoriteAreaSearchHandler(rootRow); 1459 rootRow.expandFunc(); 1460 this.favoriteChartListEL!.scroll({ 1461 top: (rootRow?.offsetTop || 0) - this.favoriteChartListEL!.getCanvas()!.offsetHeight + (++depth * 20 || 0), 1462 left: 0, 1463 behavior: smooth ? 'smooth' : undefined, 1464 }); 1465 } else { 1466 let row = this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`); 1467 if (row && !row.expansion) { 1468 row.expansion = true; 1469 } 1470 if (rootRow) { 1471 rootRow.expandFunc(); 1472 } 1473 if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) { 1474 let top = (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + (++depth * 20 || 0); 1475 this.rowsPaneEL!.scroll({ 1476 top: top, 1477 left: 0, 1478 behavior: smooth ? 'smooth' : undefined, 1479 }); 1480 } 1481 } 1482 } 1483 1484 scrollToFunction(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) { 1485 let condition = `trace-row[row-id='${rowId}'][row-type='${rowType}'][row-parent-id='${rowParentId}']`; 1486 let rootRow = 1487 this.rowsEL!.querySelector<TraceRow<any>>(condition) || 1488 this.favoriteChartListEL!.getCollectRow((row) => { 1489 return row.rowId === rowId && row.rowType === rowType && row.rowParentId === rowParentId; 1490 }); 1491 if (rootRow?.collect) { 1492 this.favoriteAreaSearchHandler(rootRow); 1493 this.favoriteChartListEL!.scroll({ 1494 top: 1495 (rootRow?.offsetTop || 0) - 1496 this.favoriteChartListEL!.getCanvas()!.offsetHeight + 1497 (rootRow?.offsetHeight || 0), 1498 left: 0, 1499 behavior: smooth ? 'smooth' : undefined, 1500 }); 1501 } else { 1502 let row = this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`); 1503 if (row && !row.expansion) { 1504 row.expansion = true; 1505 } 1506 if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) { 1507 this.rowsPaneEL!.scroll({ 1508 top: (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + 20, 1509 left: 0, 1510 behavior: smooth ? 'smooth' : undefined, 1511 }); 1512 } 1513 } 1514 } 1515 1516 disconnectedCallback() { 1517 this.timerShaftEL?.removeEventListener('range-change', this.timerShaftELRangeChange); 1518 this.rowsPaneEL?.removeEventListener('scroll', this.rowsElOnScroll); 1519 this.favoriteChartListEL?.removeEventListener('scroll', this.favoriteRowsElOnScroll); 1520 this.removeEventListener('mousemove', this.documentOnMouseMove); 1521 this.removeEventListener('click', this.documentOnClick); 1522 this.removeEventListener('mousedown', this.documentOnMouseDown); 1523 this.removeEventListener('mouseup', this.documentOnMouseUp); 1524 this.removeEventListener('mouseout', this.documentOnMouseOut); 1525 document.removeEventListener('keypress', this.documentOnKeyPress); 1526 document.removeEventListener('keydown', this.documentOnKeyDown); 1527 document.removeEventListener('keyup', this.documentOnKeyUp); 1528 document.removeEventListener('contextmenu', this.onContextMenuHandler); 1529 window.unsubscribe(window.SmartEvent.UI.SliceMark, this.sliceMarkEventHandler.bind(this)); 1530 } 1531 1532 sliceMarkEventHandler(ev: any) { 1533 SpSystemTrace.sliceRangeMark = ev; 1534 let startNS = ev.timestamp - (window as any).recordStartNS; 1535 let endNS = ev.maxDuration + startNS; 1536 TraceRow.rangeSelectObject = { 1537 startX: 0, 1538 startNS: startNS, 1539 endNS: endNS, 1540 endX: 0, 1541 }; 1542 window.publish(window.SmartEvent.UI.MenuTrace, {}); 1543 window.publish(window.SmartEvent.UI.TimeRange, { 1544 startNS: startNS - ev.maxDuration, 1545 endNS: endNS + ev.maxDuration, 1546 }); 1547 this.queryAllTraceRow().forEach((it) => (it.checkType = '-1')); 1548 this.rangeSelect.rangeTraceRow = []; 1549 this.selectStructNull(); 1550 this.wakeupListNull(); 1551 this.traceSheetEL?.setAttribute('mode', 'hidden'); 1552 this.removeLinkLinesByBusinessType('janks'); 1553 TraceRow.range!.refresh = true; 1554 this.refreshCanvas(false); 1555 } 1556 1557 loadDatabaseUrl( 1558 url: string, 1559 progress: Function, 1560 complete?: ((res: { status: boolean; msg: string }) => void) | undefined 1561 ) { 1562 this.observerScrollHeightEnable = false; 1563 this.init({ url: url }, '', progress).then((res) => { 1564 if (complete) { 1565 complete(res); 1566 window.publish(window.SmartEvent.UI.MouseEventEnable, { 1567 mouseEnable: true, 1568 }); 1569 } 1570 }); 1571 } 1572 1573 loadDatabaseArrayBuffer( 1574 buf: ArrayBuffer, 1575 thirdPartyWasmConfigUrl: string, 1576 progress: (name: string, percent: number) => void, 1577 complete?: ((res: { status: boolean; msg: string }) => void) | undefined 1578 ) { 1579 this.observerScrollHeightEnable = false; 1580 this.init({ buf }, thirdPartyWasmConfigUrl, progress).then((res) => { 1581 this.rowsEL?.querySelectorAll('trace-row').forEach((it: any) => this.observer.observe(it)); 1582 if (complete) { 1583 complete(res); 1584 window.publish(window.SmartEvent.UI.MouseEventEnable, { 1585 mouseEnable: true, 1586 }); 1587 } 1588 }); 1589 } 1590 1591 queryAllTraceRow<T>(selectors?: string, filter?: (row: TraceRow<any>) => boolean): TraceRow<any>[] { 1592 return [ 1593 ...this.rowsEL!.querySelectorAll<TraceRow<any>>(selectors ?? 'trace-row'), 1594 ...this.favoriteChartListEL!.getCollectRows(filter), 1595 ]; 1596 } 1597 1598 search(query: string) { 1599 this.queryAllTraceRow().forEach((item) => { 1600 if (query == null || query == undefined || query == '') { 1601 if ( 1602 item.rowType == TraceRow.ROW_TYPE_CPU || 1603 item.rowType == TraceRow.ROW_TYPE_CPU_FREQ || 1604 item.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY || 1605 item.rowType == TraceRow.ROW_TYPE_FPS || 1606 item.rowType == TraceRow.ROW_TYPE_PROCESS || 1607 item.rowType == TraceRow.ROW_TYPE_CPU_ABILITY || 1608 item.rowType == TraceRow.ROW_TYPE_MEMORY_ABILITY || 1609 item.rowType == TraceRow.ROW_TYPE_DISK_ABILITY || 1610 item.rowType == TraceRow.ROW_TYPE_NETWORK_ABILITY 1611 ) { 1612 item.expansion = false; 1613 item.rowHidden = false; 1614 } else { 1615 item.rowHidden = true; 1616 } 1617 } else { 1618 item.rowHidden = item.name.toLowerCase().indexOf(query.toLowerCase()) < 0; 1619 } 1620 }); 1621 this.visibleRows.forEach((it) => (it.rowHidden = false && it.draw(true))); 1622 } 1623 1624 async searchCPU(query: string): Promise<Array<any>> { 1625 let pidArr: Array<number> = []; 1626 let tidArr: Array<number> = []; 1627 for (let key of Utils.PROCESS_MAP.keys()) { 1628 if (`${key}`.includes(query) || (Utils.PROCESS_MAP.get(key) || '').includes(query)) { 1629 pidArr.push(key); 1630 } 1631 } 1632 for (let key of Utils.THREAD_MAP.keys()) { 1633 if (`${key}`.includes(query) || (Utils.THREAD_MAP.get(key) || '').includes(query)) { 1634 tidArr.push(key); 1635 } 1636 } 1637 return await searchCpuDataSender(pidArr, tidArr); 1638 } 1639 1640 async searchFunction(cpuList: Array<any>, query: string): Promise<Array<any>> { 1641 let processList: Array<string> = []; 1642 let traceRow = 1643 this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[scene]`) || 1644 this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene')); 1645 if (traceRow) { 1646 this.shadowRoot!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='process'][scene]`).forEach((row) => { 1647 processList.push(row.rowId!); 1648 }); 1649 if (query.includes('_')) { 1650 query = query.replace(/_/g, '\\_'); 1651 } 1652 if (query.includes('%')) { 1653 query = query.replace(/%/g, '\\%'); 1654 } 1655 let list = await querySceneSearchFunc(query, processList); 1656 cpuList = cpuList.concat(list); 1657 cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); 1658 return cpuList; 1659 } else { 1660 let list = await querySearchFunc(query); 1661 cpuList = cpuList.concat(list); 1662 cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); 1663 return cpuList; 1664 } 1665 } 1666 1667 searchSdk(dataList: Array<any>, query: string): Array<any> { 1668 let traceRow = 1669 this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[scene]`) || 1670 this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene')); 1671 let dataAll = `trace-row[row-type^='sdk']`; 1672 if (traceRow) { 1673 dataAll = `trace-row[row-type^='sdk'][scene]`; 1674 } 1675 let allTraceRow: any = []; 1676 let parentRows = this.shadowRoot!.querySelectorAll<TraceRow<any>>(`${dataAll}`); 1677 parentRows.forEach((parentRow: TraceRow<any>) => { 1678 allTraceRow.push(parentRow); 1679 if (parentRow.childrenList && parentRow.childrenList.length > 0) { 1680 allTraceRow.push(...parentRow.childrenList); 1681 } 1682 }); 1683 allTraceRow.forEach((row: any) => { 1684 if (row!.name.indexOf(query) >= 0) { 1685 let searchSdkBean = new SearchSdkBean(); 1686 searchSdkBean.startTime = TraceRow.range!.startNS; 1687 searchSdkBean.dur = TraceRow.range!.totalNS; 1688 searchSdkBean.name = row.name; 1689 searchSdkBean.rowId = row.rowId; 1690 searchSdkBean.type = 'sdk'; 1691 searchSdkBean.rowType = row.rowType; 1692 searchSdkBean.rowParentId = row.rowParentId; 1693 dataList.push(searchSdkBean); 1694 } 1695 }); 1696 return dataList; 1697 } 1698 1699 showStruct(previous: boolean, currentIndex: number, structs: Array<any>, retargetIndex?: number) { 1700 return spSystemTraceShowStruct(this, previous, currentIndex, structs, retargetIndex); 1701 } 1702 1703 private toTargetDepth = (entry: any, funcRowID: number, funcStract: any) => { 1704 if (entry) { 1705 this.hoverStructNull(); 1706 this.selectStructNull(); 1707 this.wakeupListNull(); 1708 FuncStruct.hoverFuncStruct = entry; 1709 FuncStruct.selectFuncStruct = entry; 1710 this.onClickHandler(TraceRow.ROW_TYPE_FUNC); 1711 this.scrollToDepth(`${funcRowID}`, `${funcStract.pid}`, 'func', true, entry.depth || 0); 1712 } 1713 }; 1714 1715 scrollToActFunc(funcStract: any, highlight: boolean): void { 1716 if (!Utils.isBinder(funcStract)) { 1717 if (funcStract.dur === -1 || funcStract.dur === null || funcStract.dur === undefined) { 1718 funcStract.dur = (TraceRow.range?.totalNS || 0) - (funcStract.startTs || 0); 1719 funcStract.flag = 'Did not end'; 1720 } 1721 } 1722 1723 let funcRowID = funcStract.cookie == null ? funcStract.tid : `${funcStract.funName}-${funcStract.pid}`; 1724 let targetRow = this.favoriteChartListEL?.getCollectRow((row) => { 1725 return row.rowId === funcRowID && row.rowType === 'func'; 1726 }); 1727 if (targetRow) { 1728 targetRow.fixedList[0] = funcStract; 1729 targetRow.highlight = highlight; 1730 //如果目标泳道图在收藏上面,则跳转至收藏 1731 this.toTargetDepth(funcStract, funcRowID, funcStract); 1732 return; 1733 } 1734 let parentRow = this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${funcStract.pid}'][folder]`); 1735 if (!parentRow) { 1736 return; 1737 } 1738 let filterRow = parentRow.childrenList.filter((child) => child.rowId == funcRowID && child.rowType == 'func')[0]; 1739 if (filterRow == null) { 1740 let funcRow = this.rowsEL?.querySelector<TraceRow<any>>(`trace-row[row-id='${funcRowID}'][row-type='func']`); 1741 if (funcRow) { 1742 filterRow = funcRow; 1743 } else { 1744 return; 1745 } 1746 } 1747 filterRow.fixedList = [funcStract]; 1748 filterRow!.highlight = highlight; 1749 let row = this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${funcStract.pid}'][folder]`); 1750 this.currentRow = row; 1751 if (row && !row.expansion) { 1752 row.expansion = true; 1753 } 1754 const completeEntry = () => { 1755 this.toTargetDepth(filterRow.fixedList[0], funcRowID, funcStract); 1756 }; 1757 if (filterRow!.isComplete) { 1758 completeEntry(); 1759 } else { 1760 this.scrollToProcess(`${funcStract.tid}`, `${funcStract.pid}`, 'thread', false); 1761 this.scrollToFunction(`${funcStract.tid}`, `${funcStract.pid}`, 'func', true); 1762 filterRow!.onComplete = completeEntry; 1763 } 1764 } 1765 1766 closeAllExpandRows(pid: string) { 1767 let expandRows = this.rowsEL?.querySelectorAll<TraceRow<ProcessStruct>>(`trace-row[row-type='process'][expansion]`); 1768 expandRows?.forEach((row) => { 1769 if (row.rowId != pid) { 1770 row.expansion = false; 1771 } 1772 }); 1773 } 1774 1775 moveRangeToCenter(startTime: number, dur: number) { 1776 let startNS = this.timerShaftEL?.getRange()?.startNS || 0; 1777 let endNS = this.timerShaftEL?.getRange()?.endNS || 0; 1778 let harfDur = Math.trunc((endNS - startNS) / 2 - dur / 2); 1779 let leftNs = startTime - harfDur; 1780 let rightNs = startTime + dur + harfDur; 1781 if (startTime - harfDur < 0) { 1782 leftNs = 0; 1783 rightNs += harfDur - startTime; 1784 } 1785 this.timerShaftEL?.setRangeNS(leftNs, rightNs); 1786 TraceRow.range!.refresh = true; 1787 this.refreshCanvas(true); 1788 } 1789 1790 rechargeCpuData(it: CpuStruct, next: CpuStruct | undefined): void { 1791 let p = Utils.PROCESS_MAP.get(it.processId!); 1792 let t = Utils.THREAD_MAP.get(it.tid!); 1793 let slice = Utils.SCHED_SLICE_MAP.get(`${it.id}-${it.startTime}`); 1794 if (slice) { 1795 it.end_state = slice.endState; 1796 it.priority = slice.priority; 1797 } 1798 it.processName = p; 1799 it.processCmdLine = p; 1800 it.name = t; 1801 it.type = 'thread'; 1802 if (next) { 1803 if (it.startTime! + it.dur! > next!.startTime! || it.dur == -1 || it.dur === null || it.dur === undefined) { 1804 it.dur = next!.startTime! - it.startTime!; 1805 it.nofinish = true; 1806 } 1807 } else { 1808 if (it.dur == -1 || it.dur === null || it.dur === undefined) { 1809 it.dur = TraceRow.range!.endNS - it.startTime!; 1810 it.nofinish = true; 1811 } 1812 } 1813 } 1814 1815 reset(progress: Function | undefined | null) { 1816 this.visibleRows.length = 0; 1817 this.tipEL!.style.display = 'none'; 1818 this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.clientWidth, this.canvasPanel!.offsetHeight); 1819 this.loadTraceCompleted = false; 1820 this.collectRows = []; 1821 this.visibleRows = []; 1822 TraceRowConfig.allTraceRowList.forEach((it) => { 1823 it.clearMemory(); 1824 }); 1825 TraceRowConfig.allTraceRowList = []; 1826 this.favoriteChartListEL!.reset(); 1827 if (this.rowsEL) { 1828 this.rowsEL.querySelectorAll<TraceRow<any>>(`trace-row`).forEach((row) => { 1829 row.clearMemory(); 1830 this.rowsEL!.removeChild(row); 1831 }); 1832 } 1833 this.traceSheetEL?.clearMemory(); 1834 this.spacerEL!.style.height = '0px'; 1835 this.rangeSelect.rangeTraceRow = []; 1836 SpSystemTrace.SDK_CONFIG_MAP = undefined; 1837 SpSystemTrace.sliceRangeMark = undefined; 1838 this.timerShaftEL?.displayCollect(false); 1839 this.timerShaftEL!.collecBtn!.removeAttribute('close'); 1840 CpuStruct.wakeupBean = undefined; 1841 this.selectStructNull(); 1842 this.hoverStructNull(); 1843 this.wakeupListNull(); 1844 this.traceSheetEL?.setAttribute('mode', 'hidden'); 1845 progress?.('rest timershaft', 8); 1846 this.timerShaftEL?.reset(); 1847 progress?.('clear cache', 10); 1848 HeapDataInterface.getInstance().clearData(); 1849 procedurePool.clearCache(); 1850 Utils.clearData(); 1851 InitAnalysis.getInstance().isInitAnalysis = true; 1852 procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: any) => {}); 1853 if (threadPool) { 1854 threadPool.submitProto(QueryEnum.ClearMemoryCache, {}, (res: any, len: number): void => {}); 1855 } 1856 this.times.clear(); 1857 resetVSync(); 1858 SpSystemTrace.keyPathList = []; 1859 } 1860 1861 init = async (param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) => { 1862 return spSystemTraceInit(this, param, wasmConfigUri, progress); 1863 }; 1864 1865 extracted(it: TraceRow<any>) { 1866 return () => { 1867 if (it.hasAttribute('expansion')) { 1868 it.childrenList.forEach((child) => { 1869 if (child.hasAttribute('scene') && !child.collect) { 1870 child.rowHidden = false; 1871 } 1872 if (child.folder) { 1873 child.addEventListener('expansion-change', this.extracted(child)); 1874 } 1875 this.intersectionObserver?.observe(child); 1876 }); 1877 } else { 1878 it.childrenList.forEach((child) => { 1879 if (child.hasAttribute('scene') && !child.collect) { 1880 child.rowHidden = true; 1881 this.intersectionObserver?.unobserve(child); 1882 } 1883 if (child.folder) { 1884 child.removeEventListener('expansion-change', this.extracted(child)); 1885 } 1886 }); 1887 this.linkNodes.map((value) => { 1888 if ('task' === value[0].business && value[0].rowEL.parentRowEl?.rowId === it.rowId) { 1889 value[0].hidden = true; 1890 value[1].hidden = true; 1891 this.clickEmptyArea(); 1892 } 1893 }); 1894 } 1895 if (!this.collapseAll) { 1896 this.refreshCanvas(false); 1897 } 1898 }; 1899 } 1900 1901 displayTip(row: TraceRow<any>, struct: any, html: string) { 1902 let x = row.hoverX + 248; 1903 let y = row.getBoundingClientRect().top - this.getBoundingClientRect().top; 1904 if ((struct === undefined || struct === null) && this.tipEL) { 1905 this.tipEL.style.display = 'none'; 1906 return; 1907 } 1908 if (this.tipEL) { 1909 this.tipEL.innerHTML = html; 1910 if (row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER || row.rowType === TraceRow.ROW_TYPE_PERF_CALLCHART) { 1911 this.tipEL.style.maxWidth = row.clientWidth / 3 + 'px'; 1912 this.tipEL.style.wordBreak = ' break-all'; 1913 this.tipEL.style.height = 'unset'; 1914 this.tipEL.style.display = 'block'; 1915 y = y + struct.depth * 20; 1916 } else { 1917 this.tipEL.style.display = 'flex'; 1918 this.tipEL.style.height = row.style.height; 1919 } 1920 if (x + this.tipEL.clientWidth > (this.canvasPanel!.clientWidth ?? 0)) { 1921 this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px) translateY(${y}px)`; 1922 } else { 1923 this.tipEL.style.transform = `translateX(${x}px) translateY(${y}px)`; 1924 } 1925 } 1926 } 1927 1928 queryCPUWakeUpList(data: WakeupBean): void { 1929 TabPaneCurrentSelection.queryCPUWakeUpListFromBean(data).then((a: any) => { 1930 if (a === null) { 1931 window.publish(window.SmartEvent.UI.WakeupList, SpSystemTrace.wakeupList); 1932 return null; 1933 } 1934 SpSystemTrace.wakeupList.push(a); 1935 this.queryCPUWakeUpList(a); 1936 }); 1937 } 1938 1939 wakeupListNull() { 1940 SpSystemTrace.wakeupList = []; 1941 return this; 1942 } 1943 1944 initPointToEvent(): void { 1945 spSystemTraceInitPointToEvent(this); 1946 } 1947 1948 initHtml(): string { 1949 return SpSystemTraceHtml; 1950 } 1951} 1952