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