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