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