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