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.js'; 17import './trace/TimerShaftElement.js'; 18import './trace/base/TraceRow.js'; 19import { 20 queryBySelectAllocationOrReturn, 21 queryBySelectExecute, 22 queryEbpfSamplesCount, 23 querySceneSearchFunc, 24 querySearchFunc, 25 threadPool, 26} from '../database/SqlLite.js'; 27import { RangeSelectStruct, TraceRow } from './trace/base/TraceRow.js'; 28import { TimerShaftElement } from './trace/TimerShaftElement.js'; 29import './trace/base/TraceSheet.js'; 30import { TraceSheet } from './trace/base/TraceSheet.js'; 31import { RangeSelect } from './trace/base/RangeSelect.js'; 32import { SelectionParam } from '../bean/BoxSelection.js'; 33import { procedurePool } from '../database/Procedure.js'; 34import { SpApplication } from '../SpApplication.js'; 35import { Flag } from './trace/timer-shaft/Flag.js'; 36import { SportRuler, SlicesTime } from './trace/timer-shaft/SportRuler.js'; 37import { SpHiPerf } from './chart/SpHiPerf.js'; 38import { SearchSdkBean, SearchThreadProcessBean } from '../bean/SearchFuncBean.js'; 39import { error, info } from '../../log/Log.js'; 40import { 41 drawFlagLineSegment, 42 drawLines, 43 drawLinkLines, 44 drawWakeUp, 45 drawWakeUpList, 46 isFrameContainPoint, 47 LineType, 48 ns2x, 49 ns2xByTimeShaft, 50 PairPoint, 51 Rect, 52} from '../database/ui-worker/ProcedureWorkerCommon.js'; 53import { SpChartManager } from './chart/SpChartManager.js'; 54import { CpuStruct, WakeupBean } from '../database/ui-worker/ProcedureWorkerCPU.js'; 55import { ProcessStruct } from '../database/ui-worker/ProcedureWorkerProcess.js'; 56import { CpuFreqStruct } from '../database/ui-worker/ProcedureWorkerFreq.js'; 57import { CpuFreqLimitsStruct } from '../database/ui-worker/ProcedureWorkerCpuFreqLimits.js'; 58import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread.js'; 59import { func, FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc.js'; 60import { CpuStateStruct } from '../database/ui-worker/ProcedureWorkerCpuState.js'; 61import { HiPerfCpuStruct } from '../database/ui-worker/ProcedureWorkerHiPerfCPU.js'; 62import { HiPerfProcessStruct } from '../database/ui-worker/ProcedureWorkerHiPerfProcess.js'; 63import { HiPerfThreadStruct } from '../database/ui-worker/ProcedureWorkerHiPerfThread.js'; 64import { HiPerfEventStruct } from '../database/ui-worker/ProcedureWorkerHiPerfEvent.js'; 65import { HiPerfReportStruct } from '../database/ui-worker/ProcedureWorkerHiPerfReport.js'; 66import { FpsStruct } from '../database/ui-worker/ProcedureWorkerFPS.js'; 67import { CpuAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerCpuAbility.js'; 68import { DiskAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerDiskIoAbility.js'; 69import { MemoryAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerMemoryAbility.js'; 70import { NetworkAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerNetworkAbility.js'; 71import { ClockStruct } from '../database/ui-worker/ProcedureWorkerClock.js'; 72import { Utils } from './trace/base/Utils.js'; 73import { IrqStruct } from '../database/ui-worker/ProcedureWorkerIrq.js'; 74import { JanksStruct } from '../bean/JanksStruct.js'; 75import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank.js'; 76import { tabConfig } from './trace/base/TraceSheetConfig.js'; 77import { TabPaneCurrent } from './trace/sheet/TabPaneCurrent.js'; 78import { LitTabpane } from '../../base-ui/tabs/lit-tabpane.js'; 79import { HeapStruct } from '../database/ui-worker/ProcedureWorkerHeap.js'; 80import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil.js'; 81import { HeapSnapshotStruct } from '../database/ui-worker/ProcedureWorkerHeapSnapshot.js'; 82import { HeapDataInterface } from '../../js-heap/HeapDataInterface.js'; 83import { TabPaneSummary } from './trace/sheet/snapshot/TabPaneSummary.js'; 84import { LitTabs } from '../../base-ui/tabs/lit-tabs.js'; 85import { SpJsMemoryChart } from './chart/SpJsMemoryChart.js'; 86import { TraceRowConfig } from './trace/base/TraceRowConfig.js'; 87import { HeapTimelineStruct } from '../database/ui-worker/ProcedureWorkerHeapTimeline.js'; 88import { TabPaneCurrentSelection } from './trace/sheet/TabPaneCurrentSelection.js'; 89import { AppStartupStruct } from '../database/ui-worker/ProcedureWorkerAppStartup.js'; 90import { SoStruct } from '../database/ui-worker/ProcedureWorkerSoInit.js'; 91import { TabPaneTaskFrames } from './trace/sheet/task/TabPaneTaskFrames.js'; 92import { FlagsConfig } from './SpFlags.js'; 93 94function dpr() { 95 return window.devicePixelRatio || 1; 96} 97//节流处理 98function throttle(fn: any, t: number, ev: any): any { 99 let timer: any = null; 100 return function () { 101 if (!timer) { 102 timer = setTimeout(function () { 103 if (ev) { 104 fn(ev); 105 } else { 106 fn(); 107 } 108 timer = null; 109 }, t); 110 } 111 }; 112} 113 114@element('sp-system-trace') 115export class SpSystemTrace extends BaseElement { 116 static mouseCurrentPosition = 0; 117 static offsetMouse = 0; 118 static moveable = true; 119 static scrollViewWidth = 0; 120 static isCanvasOffScreen = true; 121 static DATA_DICT: Map<number, string> = new Map<number, string>(); 122 static DATA_TASK_POOL_CALLSTACK: Map<number, { id: number; ts: number; dur: number; name: string }> = new Map< 123 number, 124 { id: number; ts: number; dur: number; name: string } 125 >(); 126 static SDK_CONFIG_MAP: any; 127 static sliceRangeMark: any; 128 static wakeupList: Array<WakeupBean> = []; 129 intersectionObserver: IntersectionObserver | undefined; 130 tipEL: HTMLDivElement | undefined | null; 131 rowsEL: HTMLDivElement | undefined | null; 132 rowsPaneEL: HTMLDivElement | undefined | null; 133 spacerEL: HTMLDivElement | undefined | null; 134 favoriteRowsEL: HTMLDivElement | undefined | null; 135 visibleRows: Array<TraceRow<any>> = []; 136 collectRows: Array<TraceRow<any>> = []; 137 keyboardEnable = true; 138 currentRowType = ''; /*保存当前鼠标所在行的类型*/ 139 observerScrollHeightEnable: boolean = false; 140 observerScrollHeightCallback: Function | undefined; 141 // @ts-ignore 142 observer = new ResizeObserver((entries) => { 143 if (this.observerScrollHeightEnable && this.observerScrollHeightCallback) { 144 this.observerScrollHeightCallback(); 145 } 146 }); 147 static btnTimer: any = null; 148 isMousePointInSheet = false; 149 hoverFlag: Flag | undefined | null = undefined; 150 selectFlag: Flag | undefined | null; 151 slicestime: SlicesTime | undefined | null = null; 152 public timerShaftEL: TimerShaftElement | null | undefined; 153 private traceSheetEL: TraceSheet | undefined | null; 154 private rangeSelect!: RangeSelect; 155 private chartManager: SpChartManager | undefined | null; 156 private loadTraceCompleted: boolean = false; 157 private rangeTraceRow: Array<TraceRow<any>> | undefined = []; 158 canvasFavoritePanel: HTMLCanvasElement | null | undefined; //绘制收藏泳道图 159 canvasFavoritePanelCtx: CanvasRenderingContext2D | null | undefined; 160 canvasPanel: HTMLCanvasElement | null | undefined; //绘制取消收藏后泳道图 161 canvasPanelCtx: CanvasRenderingContext2D | undefined | null; 162 linkNodes: PairPoint[][] = []; 163 public currentClickRow: HTMLDivElement | undefined | null; 164 private litTabs: LitTabs | undefined | null; 165 eventMap: any = {}; 166 private isSelectClick: boolean = false; 167 private selectionParam: SelectionParam | undefined; 168 169 addPointPair(a: PairPoint, b: PairPoint) { 170 if (a.rowEL.collect) { 171 a.rowEL.translateY = a.rowEL.getBoundingClientRect().top - 195; 172 } else { 173 a.rowEL.translateY = a.rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 174 } 175 if (b.rowEL.collect) { 176 b.rowEL.translateY = b.rowEL.getBoundingClientRect().top - 195; 177 } else { 178 b.rowEL.translateY = b.rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 179 } 180 a.y = a.rowEL!.translateY! + a.offsetY; 181 b.y = b.rowEL!.translateY! + b.offsetY; 182 this.linkNodes.push([a, b]); 183 } 184 185 clearPointPair() { 186 this.linkNodes.length = 0; 187 } 188 189 removeLinkLinesByBusinessType(...businessTypes: string[]) { 190 this.linkNodes = this.linkNodes.filter((pointPair) => { 191 return !(businessTypes.indexOf(pointPair[0].business) > -1); 192 }); 193 } 194 195 hiddenLinkLinesByBusinessType(...businessTypes: string[]) { 196 this.linkNodes.map((value) => { 197 if (businessTypes.indexOf(value[0].business) !== -1) { 198 value[0].hidden = true; 199 value[1].hidden = true; 200 } 201 }); 202 } 203 204 showLinkLinesByBusinessType(...businessTypes: string[]) { 205 this.linkNodes.map((value) => { 206 if (businessTypes.indexOf(value[0].business) !== -1) { 207 value[0].hidden = false; 208 value[1].hidden = false; 209 } 210 }); 211 } 212 213 initElements(): void { 214 let sideColor = document!.querySelector("body > sp-application")!.shadowRoot!.querySelector!("#main-menu")?. 215 shadowRoot?.querySelector("div.bottom > div.color"); 216 let rightButton: HTMLElement | null | undefined = 217 this.shadowRoot?.querySelector("div > trace-sheet")?.shadowRoot?. 218 querySelector("#current-selection > tabpane-current-selection")?.shadowRoot?.querySelector("#rightButton") 219 this.rowsEL = this.shadowRoot?.querySelector<HTMLDivElement>('.rows'); 220 this.tipEL = this.shadowRoot?.querySelector<HTMLDivElement>('.tip'); 221 this.rowsPaneEL = this.shadowRoot?.querySelector<HTMLDivElement>('.rows-pane'); 222 this.spacerEL = this.shadowRoot?.querySelector<HTMLDivElement>('.spacer'); 223 this.canvasFavoritePanel = this.shadowRoot?.querySelector<HTMLCanvasElement>('.panel-canvas-favorite'); 224 this.timerShaftEL = this.shadowRoot?.querySelector('.timer-shaft'); 225 this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet'); 226 this.favoriteRowsEL = this.shadowRoot?.querySelector('.favorite-rows'); 227 this.rangeSelect = new RangeSelect(this); 228 rightButton?.addEventListener('click', (event: any) => { 229 if (SpSystemTrace.btnTimer) { 230 return; 231 } 232 this.wakeupListNull(); 233 SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!); 234 this.queryCPUWakeUpList(CpuStruct.wakeupBean!); 235 setTimeout(() => { 236 requestAnimationFrame(() => this.refreshCanvas(false)); 237 }, 300); 238 SpSystemTrace.btnTimer = setTimeout(() => { 239 SpSystemTrace.btnTimer = null; // 2.清空节流阀,方便下次开启定时器 240 }, 2000); 241 }); 242 sideColor?.addEventListener('click', (event: any) => { 243 requestAnimationFrame(() => this.refreshCanvas(true)); 244 }); 245 document?.addEventListener('triangle-flag', (event: any) => { 246 let temporaryTime = this.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); 247 if (event.detail.timeCallback && temporaryTime) event.detail.timeCallback(temporaryTime); 248 }); 249 document?.addEventListener('flag-change', (event: any) => { 250 this.timerShaftEL?.modifyFlagList(event.detail); 251 if (event.detail.hidden) { 252 this.selectFlag = undefined; 253 this.traceSheetEL?.setAttribute('mode', 'hidden'); 254 this.refreshCanvas(true); 255 } 256 }); 257 document?.addEventListener('slices-change', (event: any) => { 258 this.timerShaftEL?.modifySlicesList(event.detail); 259 if (event.detail.hidden) { 260 this.slicestime = null; 261 this.traceSheetEL?.setAttribute('mode', 'hidden'); 262 this.refreshCanvas(true); 263 } 264 }); 265 if (this.timerShaftEL?.collecBtn) { 266 this.timerShaftEL.collecBtn.onclick = () => { 267 if (this.timerShaftEL!.collecBtn!.hasAttribute('close')) { 268 this.timerShaftEL!.collecBtn!.removeAttribute('close'); 269 } else { 270 this.timerShaftEL!.collecBtn!.setAttribute('close', ''); 271 } 272 if (this.collectRows.length > 0) { 273 this.collectRows.forEach((row) => { 274 row?.collectEL?.onclick?.(new MouseEvent('auto-collect', undefined)); 275 }); 276 } 277 }; 278 } 279 document?.addEventListener('collect', (event: any) => { 280 let currentRow = event.detail.row; 281 if (currentRow.collect) { 282 if ( 283 !this.collectRows.find((find) => { 284 return find === currentRow; 285 }) 286 ) { 287 this.collectRows.push(currentRow); 288 } 289 if (event.detail.type !== 'auto-collect' && this.timerShaftEL!.collecBtn!.hasAttribute('close')) { 290 currentRow.collect = false; 291 this.timerShaftEL!.collecBtn!.click(); 292 return; 293 } 294 let replaceRow = document.createElement('div'); 295 replaceRow.setAttribute('row-id', currentRow.rowId + '-' + currentRow.rowType); 296 replaceRow.setAttribute('type', 'replaceRow'); 297 replaceRow.setAttribute('row-parent-id', currentRow.rowParentId); 298 replaceRow.style.display = 'none'; 299 currentRow.rowHidden = !currentRow.hasAttribute('scene'); 300 // 添加收藏时,在线程名前面追加父亲ID 301 let rowParentId = currentRow.rowParentId; 302 if (rowParentId) { 303 let parentRows = this.shadowRoot?.querySelectorAll<TraceRow<any>>(`trace-row[row-id='${rowParentId}']`); 304 parentRows?.forEach((parentRow) => { 305 if ( 306 parentRow?.name && 307 parentRow?.name != currentRow.name && 308 !parentRow.rowType!.startsWith('cpu') && 309 !parentRow.rowType!.startsWith('thread') && 310 !parentRow.rowType!.startsWith('func') 311 ) { 312 currentRow.name += '(' + parentRow.name + ')'; 313 } 314 }); 315 } 316 if (this.rowsEL!.contains(currentRow)) { 317 this.rowsEL!.replaceChild(replaceRow, currentRow); 318 } else { 319 if (currentRow.hasParentRowEl) { 320 let parent = currentRow.parentRowEl; 321 parent!.replaceTraceRow(replaceRow, currentRow); 322 } 323 } 324 this.favoriteRowsEL!.append(currentRow); 325 } else { 326 this.favoriteRowsEL!.removeChild(currentRow); 327 if (event.detail.type !== 'auto-collect') { 328 let rowIndex = this.collectRows.indexOf(currentRow); 329 if (rowIndex !== -1) { 330 this.collectRows.splice(rowIndex, 1); 331 } 332 } 333 let row = currentRow; 334 let allowExpansionRow = []; 335 while (row.hasParentRowEl) { 336 let parent = row.parentRowEl; 337 allowExpansionRow.push(parent); 338 row = parent; 339 } 340 for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) { 341 if (!allowExpansionRow[index]?.expansion && allowExpansionRow[index]?.hasAttribute('scene')) { 342 allowExpansionRow[index].expansion = true; 343 } 344 } 345 allowExpansionRow.length = 0; 346 let replaceRow = this.rowsEL!.querySelector<HTMLCanvasElement>( 347 `div[row-id='${currentRow.rowId}-${currentRow.rowType}']` 348 ); 349 if (replaceRow != null) { 350 // 取消收藏时,删除父亲ID 351 let rowNameArr = currentRow.name.split('('); 352 if (rowNameArr.length > 1) { 353 let tempName = ''; 354 tempName += rowNameArr[0]; 355 currentRow.name = tempName; 356 } else { 357 currentRow.name = rowNameArr[0]; 358 } 359 this.rowsEL!.replaceChild(currentRow, replaceRow); 360 currentRow.style.boxShadow = `0 10px 10px #00000000`; 361 } 362 this.canvasFavoritePanel!.style.transform = `translateY(${ 363 this.favoriteRowsEL!.scrollTop - currentRow.clientHeight 364 }px)`; 365 } 366 this.timerShaftEL?.displayCollect(this.collectRows.length !== 0); 367 this.refreshFavoriteCanvas(); 368 this.refreshCanvas(true); 369 this.linkNodes.forEach((itln) => { 370 if (itln[0].rowEL === currentRow) { 371 if (itln[0].rowEL.collect) { 372 itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; 373 } else { 374 itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 375 } 376 itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; 377 } else if (itln[1].rowEL === currentRow) { 378 if (itln[1].rowEL.collect) { 379 itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; 380 } else { 381 itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 382 } 383 itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; 384 } 385 }); 386 // 收藏夹元素拖动排序功能 387 this.currentClickRow = null; 388 currentRow.setAttribute('draggable', 'true'); 389 currentRow.addEventListener('dragstart', () => { 390 this.currentClickRow = currentRow; 391 }); 392 currentRow.addEventListener('dragover', (ev: any) => { 393 ev.preventDefault(); 394 ev.dataTransfer.dropEffect = 'move'; 395 }); 396 currentRow.addEventListener('drop', (ev: any) => { 397 if (this.favoriteRowsEL != null && this.currentClickRow != null && this.currentClickRow !== currentRow) { 398 let rect = currentRow.getBoundingClientRect(); 399 if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { 400 //向上移动 401 this.favoriteRowsEL.insertBefore(this.currentClickRow, currentRow); 402 } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { 403 //向下移动 404 this.favoriteRowsEL.insertBefore(this.currentClickRow, currentRow.nextSibling); 405 } 406 this.refreshFavoriteCanvas(); 407 } 408 }); 409 currentRow.addEventListener('dragend', () => { 410 this.linkNodes.forEach((itln) => { 411 if (itln[0].rowEL.collect) { 412 itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; 413 } else { 414 itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 415 } 416 if (itln[1].rowEL.collect) { 417 itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; 418 } else { 419 itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 420 } 421 itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; 422 itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; 423 }); 424 this.currentClickRow = null; 425 }); 426 }); 427 SpSystemTrace.scrollViewWidth = this.getScrollWidth(); 428 this.rangeSelect.selectHandler = (rows, refreshCheckBox) => { 429 rows.forEach((item) => { 430 this.setAttribute('clickRow', item.rowType!); 431 this.setAttribute('rowName', item.name); 432 this.setAttribute('rowId', item.rowId!); 433 }); 434 if (rows.length == 0) { 435 this.shadowRoot!.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => { 436 it.checkType = '-1'; 437 if (it.folder) { 438 it.childrenList.forEach((item) => { 439 it.checkType = '-1'; 440 }); 441 } 442 }); 443 this.refreshCanvas(true); 444 this.traceSheetEL?.setAttribute('mode', 'hidden'); 445 return; 446 } 447 if (refreshCheckBox) { 448 if (rows.length > 0) { 449 this.shadowRoot?.querySelectorAll<TraceRow<any>>('trace-row').forEach((row) => { 450 row.checkType = '0'; 451 if (row.folder) { 452 row.childrenList.forEach((ite) => { 453 ite.checkType = '0'; 454 }); 455 } 456 }); 457 rows.forEach((it) => { 458 it.checkType = '2'; 459 }); 460 } else { 461 this.shadowRoot?.querySelectorAll<TraceRow<any>>('trace-row').forEach((row) => { 462 row.checkType = '-1'; 463 if (row.folder) { 464 row.childrenList.forEach((it) => { 465 it.checkType = '-1'; 466 }); 467 } 468 }); 469 return; 470 } 471 } 472 if (!this.isSelectClick) { 473 this.rangeTraceRow = []; 474 } 475 let selection = new SelectionParam(); 476 selection.leftNs = 0; 477 selection.rightNs = 0; 478 selection.recordStartNs = (window as any).recordStartNS; 479 let native_memory = ['All Heap & Anonymous VM', 'All Heap', 'All Anonymous VM']; 480 rows.forEach((it) => { 481 if (it.rowType == TraceRow.ROW_TYPE_CPU) { 482 selection.cpus.push(parseInt(it.rowId!)); 483 info('load CPU traceRow id is : ', it.rowId); 484 } else if (it.rowType == TraceRow.ROW_TYPE_CPU_STATE) { 485 let filterId = parseInt(it.rowId!); 486 if (selection.cpuStateFilterIds.indexOf(filterId) == -1) { 487 selection.cpuStateFilterIds.push(filterId); 488 } 489 } else if (it.rowType == TraceRow.ROW_TYPE_CPU_FREQ) { 490 let filterId = parseInt(it.rowId!); 491 if (selection.cpuFreqFilterIds.indexOf(filterId) == -1) { 492 selection.cpuFreqFilterIds.push(filterId); 493 } 494 } else if (it.rowType == TraceRow.ROW_TYPE_CPU_FREQ_LIMIT) { 495 selection.cpuFreqLimitDatas.push(it.dataList!); 496 } else if (it.rowType == TraceRow.ROW_TYPE_PROCESS) { 497 this.pushPidToSelection(selection, it.rowId!); 498 if (it.getAttribute('hasStartup') === 'true') { 499 selection.startup = true; 500 } 501 if (it.getAttribute('hasStaticInit') === 'true') { 502 selection.staticInit = true; 503 } 504 let processChildRows: Array<TraceRow<any>> = [ 505 ...this.shadowRoot!.querySelectorAll<TraceRow<any>>(`trace-row[row-parent-id='${it.rowId}']`), 506 ]; 507 if (!it.expansion) { 508 processChildRows = [...it.childrenList]; 509 } 510 selection.processIds.push(parseInt(it.rowId!)); 511 processChildRows.forEach((th) => { 512 th.rangeSelect = true; 513 th.checkType = '2'; 514 if (th.rowType == TraceRow.ROW_TYPE_THREAD) { 515 selection.threadIds.push(parseInt(th.rowId!)); 516 } else if (th.rowType == TraceRow.ROW_TYPE_FUNC) { 517 if (th.asyncFuncName) { 518 selection.funAsync.push({ 519 name: th.asyncFuncName, 520 pid: th.asyncFuncNamePID || 0, 521 }); 522 } else { 523 selection.funTids.push(parseInt(th.rowId!)); 524 } 525 } else if (th.rowType == TraceRow.ROW_TYPE_MEM) { 526 selection.processTrackIds.push(parseInt(th.rowId!)); 527 } 528 }); 529 info('load process traceRow id is : ', it.rowId); 530 } else if (it.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY) { 531 let memoryRows: Array<TraceRow<any>> = [ 532 ...this.shadowRoot!.querySelectorAll<TraceRow<any>>(`trace-row[row-parent-id='${it.rowId}']`), 533 ]; 534 if (!it.expansion) { 535 memoryRows = [...it.childrenList]; 536 } 537 memoryRows.forEach((th) => { 538 th.rangeSelect = true; 539 th.checkType = '2'; 540 if (th.getAttribute('heap-type') === 'native_hook_statistic') { 541 selection.nativeMemoryStatistic.push(th.rowId!); 542 } else { 543 selection.nativeMemory.push(th.rowId!); 544 } 545 }); 546 info('load nativeMemory traceRow id is : ', it.rowId); 547 } else if (it.rowType == TraceRow.ROW_TYPE_STATIC_INIT) { 548 selection.staticInit = true; 549 this.pushPidToSelection(selection, it.rowParentId!); 550 info('load thread traceRow id is : ', it.rowId); 551 } else if (it.rowType == TraceRow.ROW_TYPE_APP_STARTUP) { 552 selection.startup = true; 553 this.pushPidToSelection(selection, it.rowParentId!); 554 info('load thread traceRow id is : ', it.rowId); 555 } else if (it.rowType == TraceRow.ROW_TYPE_THREAD) { 556 this.pushPidToSelection(selection, it.rowParentId!); 557 selection.threadIds.push(parseInt(it.rowId!)); 558 info('load thread traceRow id is : ', it.rowId); 559 } else if (it.rowType == TraceRow.ROW_TYPE_FUNC) { 560 TabPaneTaskFrames.TaskArray = []; 561 this.pushPidToSelection(selection, it.rowParentId!); 562 if (it.asyncFuncName) { 563 selection.funAsync.push({ 564 name: it.asyncFuncName, 565 pid: it.asyncFuncNamePID || 0, 566 }); 567 } else { 568 selection.funTids.push(parseInt(it.rowId!)); 569 } 570 571 let isIntersect = (a: FuncStruct, b: RangeSelectStruct) => 572 Math.max(a.startTs! + a.dur!, b!.endNS || 0) - Math.min(a.startTs!, b!.startNS || 0) < 573 a.dur! + (b!.endNS || 0) - (b!.startNS || 0) && a.funName!.indexOf('H:Task ') >= 0; 574 let taskData = it.dataList.filter((taskData: FuncStruct) => { 575 taskData!.tid = parseInt(it.rowId!); 576 return isIntersect(taskData, TraceRow.rangeSelectObject!); 577 }); 578 if (taskData.length > 0) { 579 selection.taskFramesData.push(taskData); 580 } 581 info('load func traceRow id is : ', it.rowId); 582 } else if (it.rowType == TraceRow.ROW_TYPE_MEM || it.rowType == TraceRow.ROW_TYPE_VIRTUAL_MEMORY) { 583 if (it.rowType == TraceRow.ROW_TYPE_MEM) { 584 selection.processTrackIds.push(parseInt(it.rowId!)); 585 } else { 586 selection.virtualTrackIds.push(parseInt(it.rowId!)); 587 } 588 info('load memory traceRow id is : ', it.rowId); 589 } else if (it.rowType == TraceRow.ROW_TYPE_FPS) { 590 selection.hasFps = true; 591 info('load FPS traceRow id is : ', it.rowId); 592 } else if (it.rowType == TraceRow.ROW_TYPE_HEAP) { 593 if (it.getAttribute('heap-type') === 'native_hook_statistic') { 594 selection.nativeMemoryStatistic.push(it.rowId!); 595 } else { 596 selection.nativeMemory.push(it.rowId!); 597 } 598 info('load nativeMemory traceRow id is : ', it.rowId); 599 } else if (it.rowType == TraceRow.ROW_TYPE_MONITOR) { 600 let abilityChildRows: Array<TraceRow<any>> = [ 601 ...this.shadowRoot!.querySelectorAll<TraceRow<any>>(`trace-row[row-parent-id='${it.rowId}']`), 602 ]; 603 if (!it.expansion) { 604 abilityChildRows = [...it.childrenList]; 605 } 606 abilityChildRows.forEach((th) => { 607 th.rangeSelect = true; 608 th.checkType = '2'; 609 if (th.rowType == TraceRow.ROW_TYPE_CPU_ABILITY) { 610 selection.cpuAbilityIds.push(th.rowId!); 611 } else if (th.rowType == TraceRow.ROW_TYPE_MEMORY_ABILITY) { 612 selection.memoryAbilityIds.push(th.rowId!); 613 } else if (th.rowType == TraceRow.ROW_TYPE_DISK_ABILITY) { 614 selection.diskAbilityIds.push(th.rowId!); 615 } else if (th.rowType == TraceRow.ROW_TYPE_NETWORK_ABILITY) { 616 selection.networkAbilityIds.push(th.rowId!); 617 } 618 }); 619 } else if (it.rowType == TraceRow.ROW_TYPE_CPU_ABILITY) { 620 selection.cpuAbilityIds.push(it.rowId!); 621 info('load CPU Ability traceRow id is : ', it.rowId); 622 } else if (it.rowType == TraceRow.ROW_TYPE_MEMORY_ABILITY) { 623 selection.memoryAbilityIds.push(it.rowId!); 624 info('load Memory Ability traceRow id is : ', it.rowId); 625 } else if (it.rowType == TraceRow.ROW_TYPE_DISK_ABILITY) { 626 selection.diskAbilityIds.push(it.rowId!); 627 info('load DiskIo Ability traceRow id is : ', it.rowId); 628 } else if (it.rowType == TraceRow.ROW_TYPE_NETWORK_ABILITY) { 629 selection.networkAbilityIds.push(it.rowId!); 630 info('load Network Ability traceRow id is : ', it.rowId); 631 } else if (it.rowType?.startsWith(TraceRow.ROW_TYPE_SDK)) { 632 if (it.rowType == TraceRow.ROW_TYPE_SDK) { 633 let sdkRows: Array<TraceRow<any>> = [ 634 ...this.shadowRoot!.querySelectorAll<TraceRow<any>>(`trace-row[row-parent-id='${it.rowId}']`), 635 ]; 636 if (!it.expansion) { 637 sdkRows = [...it.childrenList]; 638 } 639 sdkRows.forEach((th) => { 640 th.rangeSelect = true; 641 th.checkType = '2'; 642 }); 643 } 644 if (it.rowType == TraceRow.ROW_TYPE_SDK_COUNTER) { 645 selection.sdkCounterIds.push(it.rowId!); 646 } 647 if (it.rowType == TraceRow.ROW_TYPE_SDK_SLICE) { 648 selection.sdkSliceIds.push(it.rowId!); 649 } 650 } else if (it.rowType?.startsWith('hiperf')) { 651 if (it.rowType == TraceRow.ROW_TYPE_HIPERF_EVENT || it.rowType == TraceRow.ROW_TYPE_HIPERF_REPORT) { 652 return; 653 } 654 selection.perfSampleIds.push(1); 655 if (it.rowType == TraceRow.ROW_TYPE_HIPERF_PROCESS) { 656 let hiperfProcessRows: Array<TraceRow<any>> = [ 657 ...this.shadowRoot!.querySelectorAll<TraceRow<any>>(`trace-row[row-parent-id='${it.rowId}']`), 658 ]; 659 if (!it.expansion) { 660 hiperfProcessRows = [...it.childrenList]; 661 } 662 hiperfProcessRows.forEach((th) => { 663 th.rangeSelect = true; 664 th.checkType = '2'; 665 }); 666 } 667 if (it.rowType == TraceRow.ROW_TYPE_HIPERF || it.rowId == 'HiPerf-cpu-merge') { 668 selection.perfAll = true; 669 } 670 if (it.rowType == TraceRow.ROW_TYPE_HIPERF_CPU) { 671 selection.perfCpus.push(it.index); 672 } 673 if (it.rowType == TraceRow.ROW_TYPE_HIPERF_PROCESS) { 674 selection.perfProcess.push(parseInt(it.rowId!.split('-')[0])); 675 } 676 if (it.rowType == TraceRow.ROW_TYPE_HIPERF_THREAD) { 677 selection.perfThread.push(parseInt(it.rowId!.split('-')[0])); 678 } 679 } else if (it.rowType == TraceRow.ROW_TYPE_FILE_SYSTEM) { 680 if (it.rowId == 'FileSystemLogicalWrite') { 681 if (selection.fileSystemType.length == 0) { 682 selection.fileSystemType = [0, 1, 3]; 683 } else { 684 if (selection.fileSystemType.indexOf(3) == -1) { 685 selection.fileSystemType.push(3); 686 } 687 } 688 } else if (it.rowId == 'FileSystemLogicalRead') { 689 if (selection.fileSystemType.length == 0) { 690 selection.fileSystemType = [0, 1, 2]; 691 } else { 692 if (selection.fileSystemType.indexOf(2) == -1) { 693 selection.fileSystemType.push(2); 694 } 695 } 696 } else if (it.rowId == 'FileSystemVirtualMemory') { 697 selection.fileSysVirtualMemory = true; 698 } else if (it.rowId == 'FileSystemDiskIOLatency') { 699 selection.diskIOLatency = true; 700 } else { 701 if (!selection.diskIOLatency) { 702 let arr = it.rowId!.split('-').reverse(); 703 let ipid = parseInt(arr[0]); 704 if (selection.diskIOipids.indexOf(ipid) == -1) { 705 selection.diskIOipids.push(ipid); 706 } 707 if (arr[1] == 'read') { 708 selection.diskIOReadIds.indexOf(ipid) == -1 ? selection.diskIOReadIds.push(ipid) : ''; 709 } else if (arr[1] == 'write') { 710 selection.diskIOWriteIds.indexOf(ipid) == -1 ? selection.diskIOWriteIds.push(ipid) : ''; 711 } 712 } 713 } 714 } else if (it.rowType == TraceRow.ROW_TYPE_POWER_ENERGY) { 715 selection.powerEnergy.push(it.rowId!); 716 } else if (it.rowType == TraceRow.ROW_TYPE_SYSTEM_ENERGY) { 717 selection.systemEnergy.push(it.rowId!); 718 } else if (it.rowType == TraceRow.ROW_TYPE_ANOMALY_ENERGY) { 719 selection.anomalyEnergy.push(it.rowId!); 720 } else if (it.rowType == TraceRow.ROW_TYPE_SYSTEM_ENERGY) { 721 info('load anomaly Energy traceRow id is : ', it.rowId); 722 } else if (it.rowType == TraceRow.ROW_TYPE_SMAPS) { 723 selection.smapsType.push(it.rowId!); 724 } else if (it.rowType == TraceRow.ROW_TYPE_CLOCK) { 725 selection.clockMapData.set( 726 it.rowId || '', 727 it.dataList.filter((clockData) => { 728 return Utils.getTimeIsCross( 729 clockData.startNS, 730 clockData.startNS + clockData.dur, 731 TraceRow.rangeSelectObject?.startNS || 0, 732 TraceRow.rangeSelectObject?.endNS || 0 733 ); 734 }) 735 ); 736 } else if (it.rowType == TraceRow.ROW_TYPE_IRQ) { 737 it.dataList.forEach((irqData) => { 738 if ( 739 Utils.getTimeIsCross( 740 irqData.startNS, 741 irqData.startNS + irqData.dur, 742 TraceRow.rangeSelectObject?.startNS || 0, 743 TraceRow.rangeSelectObject?.endNS || 0 744 ) 745 ) { 746 if (selection.irqMapData.has(irqData.name)) { 747 selection.irqMapData.get(irqData.name)?.push(irqData); 748 } else { 749 selection.irqMapData.set(irqData.name, [irqData]); 750 } 751 } 752 }); 753 } else if (it.rowType == TraceRow.ROW_TYPE_JANK) { 754 let isIntersect = (a: JanksStruct, b: RangeSelectStruct) => 755 Math.max(a.ts! + a.dur!, b!.endNS || 0) - Math.min(a.ts!, b!.startNS || 0) < 756 a.dur! + (b!.endNS || 0) - (b!.startNS || 0); 757 if (it.name == 'Actual Timeline') { 758 selection.jankFramesData = []; 759 let jankDatas = it.dataList.filter((jankData: any) => { 760 return isIntersect(jankData, TraceRow.rangeSelectObject!); 761 }); 762 selection.jankFramesData.push(jankDatas); 763 } else if (it.folder) { 764 selection.jankFramesData = []; 765 it.childrenList.forEach((child) => { 766 if (child.rowType == TraceRow.ROW_TYPE_JANK && child.name == 'Actual Timeline') { 767 let jankDatas = child.dataList.filter((jankData: any) => { 768 return isIntersect(jankData, TraceRow.rangeSelectObject!); 769 }); 770 selection.jankFramesData.push(jankDatas); 771 } 772 }); 773 } 774 } else if (it.rowType === TraceRow.ROW_TYPE_HEAP_TIMELINE || it.rowType === TraceRow.ROW_TYPE_JS_MEMORY) { 775 selection.jsMemory.push(it.rowId); 776 let jsMemoryRows: Array<TraceRow<HeapTimelineStruct>> = [ 777 ...this.shadowRoot!.querySelectorAll<TraceRow<HeapTimelineStruct>>( 778 `trace-row[row-parent-id='${it.rowId}']` 779 ), 780 ]; 781 if (!it.expansion) { 782 jsMemoryRows = [...it.childrenList]; 783 } 784 jsMemoryRows.forEach((th) => { 785 if (th.rowType === TraceRow.ROW_TYPE_HEAP_TIMELINE) { 786 it.dataList.length === 0 ? th.dataList : it.dataList; 787 selection.jsMemory.push(th.rowId); 788 } else { 789 selection.jsMemory = []; 790 } 791 }); 792 let endNS = TraceRow.rangeSelectObject?.endNS ? TraceRow.rangeSelectObject?.endNS : TraceRow.range?.endNS; 793 let startNS = TraceRow.rangeSelectObject?.startNS 794 ? TraceRow.rangeSelectObject?.startNS 795 : TraceRow.range?.startNS; 796 let minNodeId, maxNodeId; 797 if (!it.dataList || it.dataList.length === 0) { 798 return; 799 } 800 for (let sample of it.dataList) { 801 if (sample.timestamp * 1000 <= startNS!) { 802 minNodeId = sample.lastAssignedId; 803 } 804 if (sample.timestamp * 1000 >= endNS!) { 805 if (maxNodeId === undefined) { 806 maxNodeId = sample.lastAssignedId; 807 } 808 } 809 } 810 811 // If the start time range of the selected box is greater than the end time of the sampled data 812 if (startNS! >= it.dataList[it.dataList.length - 1].timestamp * 1000) { 813 minNodeId = it.dataList[it.dataList.length - 1].lastAssignedId; 814 } 815 // If you select the box from the beginning 816 if (startNS! <= TraceRow.range?.startNS!) { 817 minNodeId = HeapDataInterface.getInstance().getMinNodeId(SpJsMemoryChart.file.id); 818 } 819 //If you select the box from the ending 820 if (endNS! >= TraceRow.range?.endNS! || endNS! >= it.dataList[it.dataList.length - 1].timestampUs * 1000) { 821 maxNodeId = HeapDataInterface.getInstance().getMaxNodeId(SpJsMemoryChart.file.id); 822 } 823 let summary = (this.traceSheetEL?.shadowRoot?.querySelector('#tabs') as LitTabs) 824 ?.querySelector('#box-heap-summary') 825 ?.querySelector('tabpane-summary') as TabPaneSummary; 826 summary.initSummaryData(SpJsMemoryChart.file, minNodeId, maxNodeId); 827 } 828 if (this.rangeTraceRow!.length !== rows.length) { 829 let event = this.createPointEvent(it); 830 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 831 action: 'trace_row', 832 event: event, 833 }); 834 } 835 }); 836 this.rangeTraceRow = rows; 837 this.isSelectClick = false; 838 if (selection.diskIOipids.length > 0 && !selection.diskIOLatency) { 839 selection.promiseList.push( 840 queryEbpfSamplesCount( 841 TraceRow.rangeSelectObject?.startNS || 0, 842 TraceRow.rangeSelectObject?.endNS || 0, 843 selection.diskIOipids 844 ).then((res) => { 845 if (res.length > 0) { 846 selection.fsCount = res[0].fsCount; 847 selection.vmCount = res[0].vmCount; 848 } 849 return new Promise((resolve) => resolve(1)); 850 }) 851 ); 852 } 853 selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0; 854 selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0; 855 this.selectStructNull(); 856 this.timerShaftEL?.removeTriangle('inverted'); 857 if (selection.promiseList.length > 0) { 858 Promise.all(selection.promiseList).then(() => { 859 selection.promiseList = []; 860 this.traceSheetEL?.rangeSelect(selection); 861 }); 862 } else { 863 this.traceSheetEL?.rangeSelect(selection); 864 } 865 this.timerShaftEL!.selectionList.push(selection); // 保持选中对象,为后面的再次选中该框选区域做准备。 866 this.selectionParam = selection; 867 }; 868 // @ts-ignore 869 new ResizeObserver((entries) => { 870 TraceRow.FRAME_WIDTH = this.clientWidth - 249 - this.getScrollWidth(); 871 requestAnimationFrame(() => { 872 this.timerShaftEL?.updateWidth(this.clientWidth - 1 - this.getScrollWidth()); 873 this.shadowRoot!.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => { 874 it.updateWidth(this.clientWidth); 875 }); 876 }); 877 }).observe(this); 878 879 new ResizeObserver((entries) => { 880 this.canvasPanelConfig(); 881 if (this.traceSheetEL!.getAttribute('mode') == 'hidden') { 882 this.timerShaftEL?.removeTriangle('triangle'); 883 } 884 this.refreshFavoriteCanvas(); 885 this.refreshCanvas(true); 886 }).observe(this.rowsPaneEL!); 887 new MutationObserver((mutations, observer) => { 888 for (const mutation of mutations) { 889 if (mutation.type === 'attributes') { 890 if (this.style.visibility === 'visible') { 891 if (TraceRow.rangeSelectObject && SpSystemTrace.sliceRangeMark) { 892 this.timerShaftEL?.setSlicesMark( 893 TraceRow.rangeSelectObject.startNS || 0, 894 TraceRow.rangeSelectObject.endNS || 0, 895 false 896 ); 897 SpSystemTrace.sliceRangeMark = undefined; 898 window.publish(window.SmartEvent.UI.RefreshCanvas, {}); 899 } 900 } 901 } 902 } 903 }).observe(this, { 904 attributes: true, 905 childList: false, 906 subtree: false, 907 }); 908 909 this.intersectionObserver = new IntersectionObserver((entries) => { 910 entries.forEach((it) => { 911 let tr = it.target as TraceRow<any>; 912 if (!it.isIntersecting) { 913 tr.sleeping = true; 914 this.visibleRows = this.visibleRows.filter((it) => !it.sleeping); 915 } else { 916 if ( 917 !this.visibleRows.find( 918 (vr) => vr.rowId === tr.rowId && vr.rowType === tr.rowType && vr.rowParentId === tr.rowParentId 919 ) 920 ) { 921 this.visibleRows.push(tr); 922 } 923 tr.sleeping = false; 924 } 925 if (this.handler) clearTimeout(this.handler); 926 this.handler = setTimeout(() => this.refreshCanvas(false), 100); 927 }); 928 }); 929 window.addEventListener('keydown', (ev) => { 930 if (ev.key.toLocaleLowerCase() === 'escape') { 931 this.shadowRoot?.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => { 932 it.checkType = '-1'; 933 }); 934 TraceRow.rangeSelectObject = undefined; 935 this.rangeSelect.rangeTraceRow = []; 936 this.selectStructNull(); 937 this.timerShaftEL?.setSlicesMark(); 938 this.traceSheetEL?.setAttribute('mode', 'hidden'); 939 this.removeLinkLinesByBusinessType('janks', 'task'); 940 } 941 }); 942 this.chartManager = new SpChartManager(this); 943 this.canvasPanel = this.shadowRoot!.querySelector<HTMLCanvasElement>('#canvas-panel')!; 944 this.canvasFavoritePanel = this.shadowRoot!.querySelector<HTMLCanvasElement>('#canvas-panel-favorite')!; 945 this.canvasPanelCtx = this.canvasPanel.getContext('2d'); 946 947 this.canvasFavoritePanelCtx = this.canvasFavoritePanel.getContext('2d'); 948 this.canvasPanelConfig(); 949 window.subscribe(window.SmartEvent.UI.SliceMark, (data) => { 950 this.sliceMarkEventHandler(data); 951 }); 952 window.subscribe(window.SmartEvent.UI.TraceRowComplete, (tr) => {}); 953 window.subscribe(window.SmartEvent.UI.RefreshCanvas, () => { 954 this.refreshCanvas(false); 955 }); 956 window.subscribe(window.SmartEvent.UI.KeyboardEnable, (tr) => { 957 this.keyboardEnable = tr.enable; 958 if (!this.keyboardEnable) { 959 this.stopWASD(); 960 } 961 }); 962 } 963 964 pushPidToSelection(selection: SelectionParam, id: string) { 965 let pid = parseInt(id); 966 if (!selection.processIds.includes(pid)) { 967 selection.processIds.push(pid); 968 } 969 } 970 971 private createPointEvent(it: TraceRow<any>) { 972 let event = this.eventMap[it.rowType + '']; 973 if (event) { 974 return event; 975 } else { 976 if (it.rowType === TraceRow.ROW_TYPE_HEAP) { 977 event = it.name; 978 } else if (it.rowType === TraceRow.ROW_TYPE_HIPERF_CPU) { 979 event = 'HiPerf Cpu'; 980 if (it.rowId === 'HiPerf-cpu-merge') { 981 event = 'HiPerf'; 982 } 983 } else if (it.rowType === TraceRow.ROW_TYPE_FILE_SYSTEM) { 984 if (it.rowId === 'FileSystemLogicalWrite') { 985 event = 'FileSystem Logical Write'; 986 } else if (it.rowId === 'FileSystemLogicalRead') { 987 event = 'FileSystem Logical Read'; 988 } else if (it.rowId === 'FileSystemVirtualMemory') { 989 event = 'Page Fault Trace'; 990 } else if (it.rowId!.startsWith('FileSystemDiskIOLatency')) { 991 event = 'Disk I/O Latency'; 992 if (it.rowId!.startsWith('FileSystemDiskIOLatency-')) { 993 event = 'Bio Process'; 994 } 995 } 996 } else if (it.rowType === TraceRow.ROW_TYPE_STATE_ENERGY) { 997 event = it.name; 998 } else if (it.rowType === TraceRow.ROW_TYPE_SMAPS) { 999 if (it.rowParentId === '') { 1000 event = 'VM Tracker'; 1001 } else { 1002 event = it.name; 1003 } 1004 } else if (it.rowType === TraceRow.ROW_TYPE_JANK) { 1005 if (it.rowId === 'frameTime' || it.rowParentId === 'frameTime') { 1006 event = 'FrameTimeLine'; 1007 } else if (it.hasAttribute('frame_type')) { 1008 event = it.getAttribute('frame_type') + ''; 1009 } 1010 } else if (it.rowType === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) { 1011 event = 'DeliverInputEvent'; 1012 if (it.rowParentId === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) { 1013 event = 'DeliverInputEvent Func'; 1014 } 1015 } else { 1016 event = it.name; 1017 } 1018 return event; 1019 } 1020 } 1021 1022 refreshFavoriteCanvas() { 1023 let collectList = this.favoriteRowsEL?.querySelectorAll<TraceRow<any>>(`trace-row[collect-type]`) || []; 1024 let height = 0; 1025 collectList.forEach((row, index) => { 1026 height += row.offsetHeight; 1027 if (index == collectList.length - 1) { 1028 row.style.boxShadow = `0 10px 10px #00000044`; 1029 } else { 1030 row.style.boxShadow = `0 10px 10px #00000000`; 1031 } 1032 }); 1033 if (height > this.rowsPaneEL!.offsetHeight) { 1034 this.favoriteRowsEL!.style.height = this.rowsPaneEL!.offsetHeight + 'px'; 1035 } else { 1036 this.favoriteRowsEL!.style.height = height + 'px'; 1037 } 1038 this.favoriteRowsEL!.style.width = this.canvasPanel?.offsetWidth + 'px'; 1039 this.spacerEL!.style.height = height + 'px'; 1040 this.canvasFavoritePanel!.style.height = this.favoriteRowsEL!.style.height; 1041 this.canvasFavoritePanel!.style.width = this.canvasPanel?.offsetWidth + 'px'; 1042 this.canvasFavoritePanel!.width = this.canvasFavoritePanel!.offsetWidth * dpr(); 1043 this.canvasFavoritePanel!.height = this.canvasFavoritePanel!.offsetHeight * dpr(); 1044 this.canvasFavoritePanel!.getContext('2d')!.scale(dpr(), dpr()); 1045 } 1046 1047 expansionAllParentRow(currentRow: TraceRow<any>) { 1048 let parentRow = this.rowsEL!.querySelector<TraceRow<any>>( 1049 `trace-row[row-id='${currentRow.rowParentId}'][folder][scene]` 1050 ); 1051 if (parentRow) { 1052 parentRow.expansion = true; 1053 if (this.rowsEL!.querySelector<TraceRow<any>>(`trace-row[row-id='${parentRow.rowParentId}'][folder]`)) { 1054 this.expansionAllParentRow(parentRow); 1055 } 1056 } 1057 } 1058 1059 canvasPanelConfig() { 1060 this.canvasPanel!.style.left = `${this.timerShaftEL!.canvas!.offsetLeft!}px`; 1061 this.canvasPanel!.width = this.canvasPanel!.offsetWidth * dpr(); 1062 this.canvasPanel!.height = this.canvasPanel!.offsetHeight * dpr(); 1063 this.canvasPanelCtx!.scale(dpr(), dpr()); 1064 1065 this.canvasFavoritePanel!.style.left = `${this.timerShaftEL!.canvas!.offsetLeft!}px`; 1066 this.canvasFavoritePanel!.width = this.canvasFavoritePanel!.offsetWidth * dpr(); 1067 this.canvasFavoritePanel!.height = this.canvasFavoritePanel!.offsetHeight * dpr(); 1068 this.canvasFavoritePanelCtx!.scale(dpr(), dpr()); 1069 } 1070 1071 getScrollWidth() { 1072 let totalScrollDiv, 1073 scrollDiv, 1074 overflowDiv = document.createElement('div'); 1075 overflowDiv.style.cssText = 'position:absolute; top:-2000px;width:200px; height:200px; overflow:hidden;'; 1076 totalScrollDiv = document.body.appendChild(overflowDiv).clientWidth; 1077 overflowDiv.style.overflowY = 'scroll'; 1078 scrollDiv = overflowDiv.clientWidth; 1079 document.body.removeChild(overflowDiv); 1080 return totalScrollDiv - scrollDiv; 1081 } 1082 1083 timerShaftELFlagClickHandler = (flag: Flag | undefined | null) => { 1084 if (flag) { 1085 setTimeout(() => { 1086 this.traceSheetEL?.displayFlagData(flag); 1087 }, 100); 1088 } 1089 }; 1090 1091 timerShaftELFlagChange = (hoverFlag: Flag | undefined | null, selectFlag: Flag | undefined | null) => { 1092 this.hoverFlag = hoverFlag; 1093 this.selectFlag = selectFlag; 1094 this.refreshCanvas(true, 'flagChange'); 1095 }; 1096 1097 timerShaftELRangeClick = (sliceTime: SlicesTime | undefined | null) => { 1098 if (sliceTime) { 1099 setTimeout(() => { 1100 this.traceSheetEL?.displayCurrent(sliceTime); // 给当前pane准备数据 1101 let selection = this.timerShaftEL!.selectionMap.get(sliceTime.id); 1102 if (selection) { 1103 selection.isCurrentPane = true; // 设置当前面板为可以显示的状态 1104 this.traceSheetEL?.rangeSelect(selection); // 显示选中区域对应的面板 1105 } 1106 }, 0); 1107 } 1108 }; 1109 1110 timerShaftELRangeChange = (e: any) => { 1111 TraceRow.range = e; 1112 if (TraceRow.rangeSelectObject) { 1113 TraceRow.rangeSelectObject!.startX = Math.floor( 1114 ns2x( 1115 TraceRow.rangeSelectObject!.startNS!, 1116 TraceRow.range?.startNS!, 1117 TraceRow.range?.endNS!, 1118 TraceRow.range?.totalNS!, 1119 this.timerShaftEL!.sportRuler!.frame 1120 ) 1121 ); 1122 TraceRow.rangeSelectObject!.endX = Math.floor( 1123 ns2x( 1124 TraceRow.rangeSelectObject!.endNS!, 1125 TraceRow.range?.startNS!, 1126 TraceRow.range?.endNS!, 1127 TraceRow.range?.totalNS!, 1128 this.timerShaftEL!.sportRuler!.frame 1129 ) 1130 ); 1131 } 1132 //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知 1133 this.linkNodes.forEach((it) => { 1134 it[0].x = ns2xByTimeShaft(it[0].ns, this.timerShaftEL!); 1135 it[1].x = ns2xByTimeShaft(it[1].ns, this.timerShaftEL!); 1136 }); 1137 this.refreshCanvas(false, 'rangeChange'); 1138 }; 1139 tim: number = -1; 1140 top: number = 0; 1141 handler: any = undefined; 1142 rowsElOnScroll = (e: any) => { 1143 this.linkNodes.forEach((itln) => { 1144 if (itln[0].rowEL.collect) { 1145 itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; 1146 } else { 1147 itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 1148 } 1149 if (itln[1].rowEL.collect) { 1150 itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; 1151 } else { 1152 itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 1153 } 1154 itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; 1155 itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; 1156 }); 1157 if (this.scrollTimer) { 1158 clearTimeout(this.scrollTimer); 1159 } 1160 this.scrollTimer = setTimeout(() => { 1161 TraceRow.range!.refresh = true; 1162 requestAnimationFrame(() => this.refreshCanvas(false)); 1163 }, 200); 1164 requestAnimationFrame(() => this.refreshCanvas(false)); 1165 }; 1166 1167 private scrollTimer: any; 1168 1169 favoriteRowsElOnScroll = (e: any) => { 1170 this.rowsElOnScroll(e); 1171 }; 1172 1173 offset = 147; 1174 1175 getRowsContentHeight(): number { 1176 return [...this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row:not([sleeping])`)] 1177 .map((it) => it.clientHeight) 1178 .reduce((acr, cur) => acr + cur, 0); 1179 } 1180 1181 // refresh main canvas and favorite canvas 1182 refreshCanvas(cache: boolean, from?: string) { 1183 if (this.visibleRows.length == 0) { 1184 return; 1185 } 1186 //clear main canvas 1187 this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.offsetWidth, this.canvasPanel!.offsetHeight); 1188 //clear favorite canvas 1189 this.canvasFavoritePanelCtx?.clearRect( 1190 0, 1191 0, 1192 this.canvasFavoritePanel!.offsetWidth, 1193 this.canvasFavoritePanel!.offsetHeight 1194 ); 1195 //draw lines for main canvas 1196 let rowsContentHeight = this.getRowsContentHeight(); 1197 let canvasHeight = 1198 rowsContentHeight > this.canvasPanel!.clientHeight ? this.canvasPanel!.clientHeight : rowsContentHeight; 1199 canvasHeight += this.canvasFavoritePanel!.clientHeight; 1200 drawLines(this.canvasPanelCtx!, TraceRow.range?.xs || [], canvasHeight, this.timerShaftEL!.lineColor()); 1201 //draw lines for favorite canvas 1202 drawLines( 1203 this.canvasFavoritePanelCtx!, 1204 TraceRow.range?.xs || [], 1205 this.canvasFavoritePanel!.clientHeight, 1206 this.timerShaftEL!.lineColor() 1207 ); 1208 //canvas translate 1209 this.canvasPanel!.style.transform = `translateY(${this.rowsPaneEL!.scrollTop}px)`; 1210 this.canvasFavoritePanel!.style.transform = `translateY(${this.favoriteRowsEL!.scrollTop}px)`; 1211 //draw trace row 1212 this.visibleRows.forEach((v, i) => { 1213 if (v.collect) { 1214 v.translateY = v.getBoundingClientRect().top - 195; 1215 } else { 1216 v.translateY = v.offsetTop - this.rowsPaneEL!.scrollTop; 1217 } 1218 v.draw(cache); 1219 }); 1220 //draw flag line segment for canvas 1221 drawFlagLineSegment( 1222 this.canvasPanelCtx, 1223 this.hoverFlag, 1224 this.selectFlag, 1225 { 1226 x: 0, 1227 y: 0, 1228 width: this.timerShaftEL?.canvas?.clientWidth, 1229 height: this.canvasPanel?.clientHeight, 1230 }, 1231 this.timerShaftEL! 1232 ); 1233 //draw flag line segment for favorite canvas 1234 drawFlagLineSegment( 1235 this.canvasFavoritePanelCtx, 1236 this.hoverFlag, 1237 this.selectFlag, 1238 { 1239 x: 0, 1240 y: 0, 1241 width: this.timerShaftEL?.canvas?.clientWidth, 1242 height: this.canvasFavoritePanel?.clientHeight, 1243 }, 1244 this.timerShaftEL! 1245 ); 1246 //draw wakeup for main canvas 1247 drawWakeUp( 1248 this.canvasPanelCtx, 1249 CpuStruct.wakeupBean, 1250 TraceRow.range!.startNS, 1251 TraceRow.range!.endNS, 1252 TraceRow.range!.totalNS, 1253 { 1254 x: 0, 1255 y: 0, 1256 width: TraceRow.FRAME_WIDTH, 1257 height: this.canvasPanel!.clientHeight!, 1258 } as Rect 1259 ); 1260 //draw wakeup for favorite canvas 1261 drawWakeUp( 1262 this.canvasFavoritePanelCtx, 1263 CpuStruct.wakeupBean, 1264 TraceRow.range!.startNS, 1265 TraceRow.range!.endNS, 1266 TraceRow.range!.totalNS, 1267 { 1268 x: 0, 1269 y: 0, 1270 width: TraceRow.FRAME_WIDTH, 1271 height: this.canvasFavoritePanel!.clientHeight!, 1272 } as Rect 1273 ); 1274 // draw wakeuplist for main canvas 1275 for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) { 1276 if (i + 1 == SpSystemTrace.wakeupList.length) { 1277 return; 1278 } 1279 drawWakeUpList( 1280 this.canvasPanelCtx, 1281 SpSystemTrace.wakeupList[i + 1], 1282 TraceRow.range!.startNS, 1283 TraceRow.range!.endNS, 1284 TraceRow.range!.totalNS, 1285 { 1286 x: 0, 1287 y: 0, 1288 width: this.timerShaftEL!.canvas!.clientWidth, 1289 height: this.canvasPanel!.clientHeight!, 1290 } as Rect 1291 ); 1292 drawWakeUpList( 1293 this.canvasFavoritePanelCtx, 1294 SpSystemTrace.wakeupList[i + 1], 1295 TraceRow.range!.startNS, 1296 TraceRow.range!.endNS, 1297 TraceRow.range!.totalNS, 1298 { 1299 x: 0, 1300 y: 0, 1301 width: this.timerShaftEL!.canvas!.clientWidth, 1302 height: this.canvasFavoritePanel!.clientHeight!, 1303 } as Rect 1304 ); 1305 } 1306 // Draw the connection curve 1307 if (this.linkNodes) { 1308 drawLinkLines(this.canvasPanelCtx!, this.linkNodes, this.timerShaftEL!, false); 1309 drawLinkLines(this.canvasFavoritePanelCtx!, this.linkNodes, this.timerShaftEL!, true); 1310 } 1311 } 1312 1313 documentOnMouseDown = (ev: MouseEvent) => { 1314 if (!this.loadTraceCompleted) return; 1315 if (this.isWASDKeyPress()) { 1316 ev.preventDefault(); 1317 ev.stopPropagation(); 1318 return; 1319 } 1320 TraceRow.isUserInteraction = true; 1321 if (this.isMouseInSheet(ev)) return; 1322 this.observerScrollHeightEnable = false; 1323 if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft) { 1324 let x = ev.offsetX - this.timerShaftEL!.canvas!.offsetLeft; 1325 let y = ev.offsetY; 1326 this.timerShaftEL?.documentOnMouseDown(ev); 1327 if ( 1328 this.timerShaftEL!.sportRuler!.frame.contains(x, y) && 1329 x > (TraceRow.rangeSelectObject?.startX || 0) && 1330 x < (TraceRow.rangeSelectObject?.endX || 0) 1331 ) { 1332 let findSlicestime = this.timerShaftEL!.sportRuler?.findSlicesTime(x, y); // 查找帽子 1333 if (!findSlicestime) { 1334 // 如果没有找到帽子,则绘制一个三角形的旗子 1335 let time = Math.round( 1336 (x * (TraceRow.range?.endNS! - TraceRow.range?.startNS!)) / this.timerShaftEL!.canvas!.offsetWidth + 1337 TraceRow.range?.startNS! 1338 ); 1339 this.timerShaftEL!.sportRuler!.drawTriangle(time, 'triangle'); 1340 } 1341 } else { 1342 this.rangeSelect.mouseDown(ev); 1343 this.rangeSelect.drag = true; 1344 } 1345 } else { 1346 this.rangeSelect.drag = false; 1347 } 1348 }; 1349 1350 onContextMenuHandler = (e: Event) => { 1351 setTimeout(() => { 1352 for (let key of this.keyPressMap.keys()) { 1353 if (this.keyPressMap.get(key)) { 1354 this.timerShaftEL?.stopWASD({ key: key }); 1355 this.keyPressMap.set(key, false); 1356 } 1357 } 1358 }, 100); 1359 }; 1360 1361 documentOnMouseUp = (ev: MouseEvent) => { 1362 if (!this.loadTraceCompleted) return; 1363 if (this.isWASDKeyPress()) { 1364 ev.preventDefault(); 1365 ev.stopPropagation(); 1366 return; 1367 } 1368 TraceRow.isUserInteraction = false; 1369 this.rangeSelect.isMouseDown = false; 1370 if ((window as any).isSheetMove) return; 1371 if (this.isMouseInSheet(ev)) return; 1372 this.rangeSelect.mouseUp(ev); 1373 this.timerShaftEL?.documentOnMouseUp(ev); 1374 ev.preventDefault(); 1375 ev.stopPropagation(); 1376 }; 1377 1378 documentOnMouseOut = (ev: MouseEvent) => { 1379 if (!this.loadTraceCompleted) return; 1380 TraceRow.isUserInteraction = false; 1381 if (this.isMouseInSheet(ev)) return; 1382 if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft) { 1383 this.rangeSelect.mouseOut(ev); 1384 this.timerShaftEL?.documentOnMouseOut(ev); 1385 } 1386 }; 1387 1388 private keyPressMap: Map<string, boolean> = new Map([ 1389 ['w', false], 1390 ['s', false], 1391 ['a', false], 1392 ['d', false], 1393 ]); 1394 documentOnKeyPress = (ev: KeyboardEvent) => { 1395 if (!this.loadTraceCompleted) return; 1396 let keyPress = ev.key.toLocaleLowerCase(); 1397 TraceRow.isUserInteraction = true; 1398 if (this.isMousePointInSheet) { 1399 return; 1400 } 1401 this.observerScrollHeightEnable = false; 1402 if (this.keyboardEnable) { 1403 if (keyPress == 'm') { 1404 this.slicestime = this.setSLiceMark(ev.shiftKey); 1405 // 设置currentPane可以显示,并且修改调色板颜色和刚刚绘制的帽子颜色保持一致。 1406 this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet'); 1407 let currentPane = this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current'); 1408 if (this.slicestime) { 1409 currentPane?.setCurrentSlicesTime(this.slicestime); 1410 } 1411 // 显示对应的面板信息 1412 this.timerShaftEL!.selectionList.forEach((selection, index) => { 1413 if (this.timerShaftEL!.selectionList.length - 1 == index) { 1414 // 把最新添加的 SelectionParam 对象设置为可以显示当前面板 1415 selection.isCurrentPane = true; 1416 this.traceSheetEL?.rangeSelect(selection); 1417 } else { 1418 // 其他 SelectionParam 对象设置为不显示当前面板 1419 selection.isCurrentPane = false; 1420 } 1421 }); 1422 } 1423 let keyPressWASD = keyPress === 'w' || keyPress === 'a' || keyPress === 's' || keyPress === 'd'; 1424 if (keyPressWASD) { 1425 this.keyPressMap.set(keyPress, true); 1426 this.hoverFlag = null; 1427 } 1428 this.timerShaftEL!.documentOnKeyPress(ev); 1429 } else { 1430 this.stopWASD(); 1431 } 1432 }; 1433 1434 setSLiceMark(shiftKey: boolean): SlicesTime | null | undefined { 1435 if (CpuStruct.selectCpuStruct) { 1436 this.slicestime = this.timerShaftEL?.setSlicesMark( 1437 CpuStruct.selectCpuStruct.startTime || 0, 1438 (CpuStruct.selectCpuStruct.startTime || 0) + (CpuStruct.selectCpuStruct.dur || 0), 1439 shiftKey 1440 ); 1441 } else if (ThreadStruct.selectThreadStruct) { 1442 this.slicestime = this.timerShaftEL?.setSlicesMark( 1443 ThreadStruct.selectThreadStruct.startTime || 0, 1444 (ThreadStruct.selectThreadStruct.startTime || 0) + (ThreadStruct.selectThreadStruct.dur || 0), 1445 shiftKey 1446 ); 1447 } else if (FuncStruct.selectFuncStruct) { 1448 this.slicestime = this.timerShaftEL?.setSlicesMark( 1449 FuncStruct.selectFuncStruct.startTs || 0, 1450 (FuncStruct.selectFuncStruct.startTs || 0) + (FuncStruct.selectFuncStruct.dur || 0), 1451 shiftKey 1452 ); 1453 } else if (IrqStruct.selectIrqStruct) { 1454 this.slicestime = this.timerShaftEL?.setSlicesMark( 1455 IrqStruct.selectIrqStruct.startNS || 0, 1456 (IrqStruct.selectIrqStruct.startNS || 0) + (IrqStruct.selectIrqStruct.dur || 0), 1457 shiftKey 1458 ); 1459 } else if (TraceRow.rangeSelectObject) { 1460 this.slicestime = this.timerShaftEL?.setSlicesMark( 1461 TraceRow.rangeSelectObject.startNS || 0, 1462 TraceRow.rangeSelectObject.endNS || 0, 1463 shiftKey 1464 ); 1465 } else if (JankStruct.selectJankStruct) { 1466 this.slicestime = this.timerShaftEL?.setSlicesMark( 1467 JankStruct.selectJankStruct.ts || 0, 1468 (JankStruct.selectJankStruct.ts || 0) + (JankStruct.selectJankStruct.dur || 0), 1469 shiftKey 1470 ); 1471 } else if (AppStartupStruct.selectStartupStruct) { 1472 this.slicestime = this.timerShaftEL?.setSlicesMark( 1473 AppStartupStruct.selectStartupStruct.startTs || 0, 1474 (AppStartupStruct.selectStartupStruct.startTs || 0) + (AppStartupStruct.selectStartupStruct.dur || 0), 1475 shiftKey 1476 ); 1477 } else if (SoStruct.selectSoStruct) { 1478 this.slicestime = this.timerShaftEL?.setSlicesMark( 1479 SoStruct.selectSoStruct.startTs || 0, 1480 (SoStruct.selectSoStruct.startTs || 0) + (SoStruct.selectSoStruct.dur || 0), 1481 shiftKey 1482 ); 1483 } else { 1484 this.slicestime = this.timerShaftEL?.setSlicesMark(); 1485 } 1486 return this.slicestime; 1487 } 1488 1489 stopWASD = () => { 1490 setTimeout(() => { 1491 for (let key of this.keyPressMap.keys()) { 1492 if (this.keyPressMap.get(key)) { 1493 this.timerShaftEL?.stopWASD({ key: key }); 1494 this.keyPressMap.set(key, false); 1495 } 1496 } 1497 }, 100); 1498 }; 1499 1500 documentOnKeyUp = (ev: KeyboardEvent) => { 1501 if (!this.loadTraceCompleted) return; 1502 let keyPress = ev.key.toLocaleLowerCase(); 1503 if (keyPress === 'w' || keyPress === 'a' || keyPress === 's' || keyPress === 'd') { 1504 this.keyPressMap.set(keyPress, false); 1505 } 1506 TraceRow.isUserInteraction = false; 1507 this.observerScrollHeightEnable = false; 1508 this.keyboardEnable && this.timerShaftEL!.documentOnKeyUp(ev); 1509 if (ev.code == 'Enter') { 1510 if (ev.shiftKey) { 1511 this.dispatchEvent( 1512 new CustomEvent('previous-data', { 1513 detail: {}, 1514 composed: false, 1515 }) 1516 ); 1517 } else { 1518 this.dispatchEvent( 1519 new CustomEvent('next-data', { 1520 detail: {}, 1521 composed: false, 1522 }) 1523 ); 1524 } 1525 } 1526 }; 1527 1528 isMouseInSheet = (ev: MouseEvent) => { 1529 this.isMousePointInSheet = 1530 this.traceSheetEL?.getAttribute('mode') != 'hidden' && 1531 ev.offsetX > this.traceSheetEL!.offsetLeft && 1532 ev.offsetY > this.traceSheetEL!.offsetTop; 1533 return this.isMousePointInSheet; 1534 }; 1535 1536 favoriteChangeHandler = (row: TraceRow<any>) => { 1537 info('favoriteChangeHandler', row.frame, row.offsetTop, row.offsetHeight); 1538 }; 1539 1540 selectChangeHandler = (rows: Array<TraceRow<any>>) => { 1541 this.isSelectClick = true; 1542 this.rangeSelect.rangeTraceRow = rows; 1543 let changeTraceRows: Array<TraceRow<any>> = []; 1544 if (this.rangeTraceRow!.length < rows.length) { 1545 rows!.forEach((currentTraceRow: TraceRow<any>) => { 1546 let changeFilter = this.rangeTraceRow!.filter( 1547 (prevTraceRow: TraceRow<any>) => prevTraceRow === currentTraceRow 1548 ); 1549 if (changeFilter.length < 1) { 1550 changeTraceRows.push(currentTraceRow); 1551 } 1552 }); 1553 if (changeTraceRows.length > 0) { 1554 changeTraceRows!.forEach((changeTraceRow: TraceRow<any>) => { 1555 let pointEvent = this.createPointEvent(changeTraceRow); 1556 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 1557 action: 'trace_row', 1558 event: pointEvent, 1559 }); 1560 }); 1561 } 1562 } 1563 this.rangeTraceRow = rows; 1564 this.rangeSelect.selectHandler?.(this.rangeSelect.rangeTraceRow, false); 1565 }; 1566 inFavoriteArea: boolean | undefined; 1567 documentOnMouseMove = (ev: MouseEvent) => { 1568 if (!this.loadTraceCompleted || (window as any).flagInputFocus) return; 1569 if (this.isWASDKeyPress()) { 1570 this.hoverFlag = null; 1571 ev.preventDefault(); 1572 return; 1573 } 1574 this.inFavoriteArea = this.favoriteRowsEL?.containPoint(ev); 1575 if ((window as any).isSheetMove) return; 1576 if (this.isMouseInSheet(ev)) { 1577 this.hoverStructNull(); 1578 return; 1579 } 1580 let isMouseInTimeShaft = this.timerShaftEL?.containPoint(ev); 1581 if (isMouseInTimeShaft) { 1582 this.tipEL!.style.display = 'none'; 1583 this.hoverStructNull(); 1584 } 1585 let rows = this.visibleRows; 1586 if (this.timerShaftEL?.isScaling()) { 1587 return; 1588 } 1589 this.timerShaftEL?.documentOnMouseMove(ev); 1590 if (isMouseInTimeShaft) { 1591 return; 1592 } 1593 this.rangeSelect.mouseMove(rows, ev); 1594 if (this.rangeSelect.isMouseDown) { 1595 this.refreshCanvas(true); 1596 } else { 1597 if (!this.rowsPaneEL!.containPoint(ev, { left: 248 })) { 1598 this.tipEL!.style.display = 'none'; 1599 this.hoverStructNull(); 1600 } 1601 rows 1602 .filter((it) => it.focusContain(ev, this.inFavoriteArea!) && it.collect === this.inFavoriteArea) 1603 .filter((it) => { 1604 if (it.collect) { 1605 return true; 1606 } else { 1607 return ( 1608 it.getBoundingClientRect().bottom + it.getBoundingClientRect().height > 1609 this.favoriteRowsEL!.getBoundingClientRect().bottom 1610 ); 1611 } 1612 }) 1613 .forEach((tr) => { 1614 if (this.currentRowType != tr.rowType) { 1615 this.hoverStructNull(); 1616 this.tipEL!.style.display = 'none'; 1617 this.currentRowType = tr.rowType || ''; 1618 } 1619 if (tr.rowType == TraceRow.ROW_TYPE_CPU) { 1620 CpuStruct.hoverCpuStruct = undefined; 1621 for (let re of tr.dataListCache) { 1622 if (re.frame && isFrameContainPoint(re.frame, tr.hoverX, tr.hoverY)) { 1623 CpuStruct.hoverCpuStruct = re; 1624 break; 1625 } 1626 } 1627 } else { 1628 CpuStruct.hoverCpuStruct = undefined; 1629 } 1630 tr.focusHandler?.(ev); 1631 }); 1632 requestAnimationFrame(() => this.refreshCanvas(true)); 1633 } 1634 }; 1635 1636 hoverStructNull() { 1637 CpuStruct.hoverCpuStruct = undefined; 1638 CpuFreqStruct.hoverCpuFreqStruct = undefined; 1639 ThreadStruct.hoverThreadStruct = undefined; 1640 FuncStruct.hoverFuncStruct = undefined; 1641 HiPerfCpuStruct.hoverStruct = undefined; 1642 HiPerfProcessStruct.hoverStruct = undefined; 1643 HiPerfThreadStruct.hoverStruct = undefined; 1644 HiPerfEventStruct.hoverStruct = undefined; 1645 HiPerfReportStruct.hoverStruct = undefined; 1646 CpuStateStruct.hoverStateStruct = undefined; 1647 CpuAbilityMonitorStruct.hoverCpuAbilityStruct = undefined; 1648 DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined; 1649 MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = undefined; 1650 NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = undefined; 1651 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined; 1652 FpsStruct.hoverFpsStruct = undefined; 1653 ClockStruct.hoverClockStruct = undefined; 1654 IrqStruct.hoverIrqStruct = undefined; 1655 HeapStruct.hoverHeapStruct = undefined; 1656 JankStruct.hoverJankStruct = undefined; 1657 AppStartupStruct.hoverStartupStruct = undefined; 1658 SoStruct.hoverSoStruct = undefined; 1659 HeapSnapshotStruct.hoverSnapshotStruct = undefined; 1660 } 1661 1662 selectStructNull() { 1663 CpuStruct.selectCpuStruct = undefined; 1664 CpuStruct.wakeupBean = null; 1665 CpuFreqStruct.selectCpuFreqStruct = undefined; 1666 ThreadStruct.selectThreadStruct = undefined; 1667 FuncStruct.selectFuncStruct = undefined; 1668 SpHiPerf.selectCpuStruct = undefined; 1669 CpuStateStruct.selectStateStruct = undefined; 1670 CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = undefined; 1671 ClockStruct.selectClockStruct = undefined; 1672 IrqStruct.selectIrqStruct = undefined; 1673 JankStruct.selectJankStruct = undefined; 1674 HeapStruct.selectHeapStruct = undefined; 1675 AppStartupStruct.selectStartupStruct = undefined; 1676 SoStruct.selectSoStruct = undefined; 1677 HeapSnapshotStruct.selectSnapshotStruct = undefined; 1678 } 1679 1680 isWASDKeyPress() { 1681 return ( 1682 this.keyPressMap.get('w') || this.keyPressMap.get('a') || this.keyPressMap.get('d') || this.keyPressMap.get('s') 1683 ); 1684 } 1685 1686 documentOnClick = (ev: MouseEvent) => { 1687 if (!this.loadTraceCompleted) return; 1688 if (this.isWASDKeyPress()) { 1689 this.hoverFlag = null; 1690 ev.preventDefault(); 1691 ev.stopPropagation(); 1692 return; 1693 } 1694 if ((window as any).isSheetMove) return; 1695 if (this.isMouseInSheet(ev)) return; 1696 if ((window as any).isPackUpTable) { 1697 (window as any).isPackUpTable = false; 1698 return; 1699 } 1700 let x = ev.offsetX - this.timerShaftEL!.canvas!.offsetLeft; 1701 let y = ev.offsetY; 1702 if (this.timerShaftEL?.getRangeRuler()?.frame.contains(x, y)) { 1703 this.clickEmptyArea(); 1704 return; 1705 } 1706 if (this.rangeSelect.isDrag()) { 1707 return; 1708 } 1709 if ( 1710 this.timerShaftEL!.sportRuler!.frame.contains(x, y) && 1711 x > (TraceRow.rangeSelectObject?.startX || 0) && 1712 x < (TraceRow.rangeSelectObject?.endX || 0) 1713 ) { 1714 } else { 1715 let inFavoriteArea = this.favoriteRowsEL?.containPoint(ev); 1716 let rows = this.visibleRows.filter((it) => it.focusContain(ev, inFavoriteArea!) && it.collect == inFavoriteArea); 1717 if (JankStruct.delJankLineFlag) { 1718 this.removeLinkLinesByBusinessType('janks'); 1719 } 1720 if (rows && rows[0] && this.traceRowClickJudgmentConditions.get(rows[0]!.rowType!)?.()) { 1721 this.onClickHandler(rows[0]!.rowType!, rows[0]); 1722 this.documentOnMouseMove(ev); 1723 } else { 1724 this.clickEmptyArea(); 1725 } 1726 } 1727 ev.preventDefault(); 1728 }; 1729 1730 clickEmptyArea() { 1731 this.shadowRoot?.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => { 1732 it.checkType = '-1'; 1733 it.rangeSelect = false; 1734 }); 1735 this.rangeSelect.rangeTraceRow = []; 1736 TraceRow.rangeSelectObject = undefined; 1737 this.selectStructNull(); 1738 this.wakeupListNull(); 1739 this.observerScrollHeightEnable = false; 1740 this.selectFlag = null; 1741 this.timerShaftEL?.removeTriangle('inverted'); 1742 this.traceSheetEL?.setAttribute('mode', 'hidden'); 1743 this.removeLinkLinesByBusinessType('task'); 1744 this.refreshCanvas(true); 1745 JankStruct.delJankLineFlag = true; 1746 } 1747 1748 //泳道图点击判定条件 1749 private traceRowClickJudgmentConditions: Map<string, () => boolean> = new Map<string, () => boolean>([ 1750 [TraceRow.ROW_TYPE_CPU, () => CpuStruct.hoverCpuStruct !== null && CpuStruct.hoverCpuStruct !== undefined], 1751 [ 1752 TraceRow.ROW_TYPE_THREAD, 1753 () => ThreadStruct.hoverThreadStruct !== null && ThreadStruct.hoverThreadStruct !== undefined, 1754 ], 1755 [TraceRow.ROW_TYPE_FUNC, () => FuncStruct.hoverFuncStruct !== null && FuncStruct.hoverFuncStruct !== undefined], 1756 [ 1757 TraceRow.ROW_TYPE_CPU_FREQ, 1758 () => CpuFreqStruct.hoverCpuFreqStruct !== null && CpuFreqStruct.hoverCpuFreqStruct !== undefined, 1759 ], 1760 [ 1761 TraceRow.ROW_TYPE_CPU_STATE, 1762 () => CpuStateStruct.hoverStateStruct !== null && CpuStateStruct.hoverStateStruct !== undefined, 1763 ], 1764 [ 1765 TraceRow.ROW_TYPE_CPU_FREQ_LIMIT, 1766 () => 1767 CpuFreqLimitsStruct.selectCpuFreqLimitsStruct !== null && 1768 CpuFreqLimitsStruct.selectCpuFreqLimitsStruct !== undefined, 1769 ], 1770 [ 1771 TraceRow.ROW_TYPE_CLOCK, 1772 () => ClockStruct.hoverClockStruct !== null && ClockStruct.hoverClockStruct !== undefined, 1773 ], 1774 [TraceRow.ROW_TYPE_IRQ, () => IrqStruct.hoverIrqStruct !== null && IrqStruct.hoverIrqStruct !== undefined], 1775 [ 1776 TraceRow.ROW_TYPE_APP_STARTUP, 1777 () => AppStartupStruct.hoverStartupStruct !== null && AppStartupStruct.hoverStartupStruct !== undefined, 1778 ], 1779 [TraceRow.ROW_TYPE_STATIC_INIT, () => SoStruct.hoverSoStruct !== null && SoStruct.hoverSoStruct !== undefined], 1780 [TraceRow.ROW_TYPE_JANK, () => JankStruct.hoverJankStruct !== null && JankStruct.hoverJankStruct !== undefined], 1781 [TraceRow.ROW_TYPE_HEAP, () => HeapStruct.hoverHeapStruct !== null && HeapStruct.hoverHeapStruct !== undefined], 1782 [ 1783 TraceRow.ROW_TYPE_HEAP_SNAPSHOT, 1784 () => HeapSnapshotStruct.hoverSnapshotStruct !== null && HeapSnapshotStruct.hoverSnapshotStruct !== undefined, 1785 ], 1786 ]); 1787 1788 onClickHandler(clickRowType: string, row?: TraceRow<any>) { 1789 if (row) { 1790 this.setAttribute('clickRow', clickRowType); 1791 this.setAttribute('rowName', row.name!); 1792 this.setAttribute('rowId', row.rowId!); 1793 } 1794 if (!this.loadTraceCompleted) return; 1795 this.shadowRoot?.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => (it.rangeSelect = false)); 1796 this.selectStructNull(); 1797 this.wakeupListNull(); 1798 let threadClickHandler: any; 1799 let cpuClickHandler: any; 1800 let jankClickHandler: any; 1801 let snapshotClickHandler: any; 1802 let scrollToFuncHandler: any; 1803 threadClickHandler = (d: ThreadStruct) => { 1804 this.observerScrollHeightEnable = false; 1805 this.scrollToProcess(`${d.cpu}`, '', 'cpu-data', true); 1806 let cpuRow = this.shadowRoot?.querySelectorAll<TraceRow<CpuStruct>>( 1807 `trace-row[row-id='${d.cpu}'][row-type='cpu-data']` 1808 )[0]; 1809 let findEntry = cpuRow!.dataList!.find((dat: any) => dat.startTime === d.startTime); 1810 if ( 1811 findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || 1812 findEntry!.startTime! > TraceRow.range!.endNS 1813 ) { 1814 this.timerShaftEL?.setRangeNS( 1815 findEntry!.startTime! - findEntry!.dur! * 2, 1816 findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2 1817 ); 1818 } 1819 this.hoverStructNull(); 1820 this.selectStructNull(); 1821 this.wakeupListNull(); 1822 CpuStruct.hoverCpuStruct = findEntry; 1823 CpuStruct.selectCpuStruct = findEntry; 1824 this.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, 'inverted'); 1825 this.traceSheetEL?.displayCpuData( 1826 CpuStruct.selectCpuStruct!, 1827 (wakeUpBean) => { 1828 CpuStruct.wakeupBean = wakeUpBean; 1829 this.refreshCanvas(true); 1830 }, 1831 cpuClickHandler 1832 ); 1833 }; 1834 1835 cpuClickHandler = (d: CpuStruct) => { 1836 let traceRow = this.shadowRoot?.querySelector<TraceRow<any>>( 1837 `trace-row[row-id='${d.processId}'][row-type='process']` 1838 ); 1839 if (traceRow) { 1840 traceRow.expansion = true; 1841 } 1842 this.observerScrollHeightEnable = true; 1843 let threadRow = this.shadowRoot?.querySelectorAll<TraceRow<ThreadStruct>>( 1844 `trace-row[row-id='${d.tid}'][row-type='thread']` 1845 )[0]; 1846 let task = () => { 1847 if (threadRow) { 1848 let findEntry = threadRow!.dataList!.find((dat) => dat.startTime === d.startTime); 1849 if ( 1850 findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || 1851 findEntry!.startTime! > TraceRow.range!.endNS 1852 ) { 1853 this.timerShaftEL?.setRangeNS( 1854 findEntry!.startTime! - findEntry!.dur! * 2, 1855 findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2 1856 ); 1857 } 1858 this.hoverStructNull(); 1859 this.selectStructNull(); 1860 this.wakeupListNull(); 1861 ThreadStruct.hoverThreadStruct = findEntry; 1862 ThreadStruct.selectThreadStruct = findEntry; 1863 this.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, 'inverted'); 1864 this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct!, threadClickHandler, cpuClickHandler); 1865 this.scrollToProcess(`${d.tid}`, `${d.processId}`, 'thread', true); 1866 } 1867 }; 1868 if (threadRow) { 1869 this.scrollToProcess(`${d.tid}`, `${d.processId}`, 'process', false); 1870 this.scrollToProcess(`${d.tid}`, `${d.processId}`, 'thread', true); 1871 if (threadRow!.isComplete) { 1872 task(); 1873 } else { 1874 threadRow!.onComplete = task; 1875 } 1876 } 1877 }; 1878 1879 jankClickHandler = (d: any) => { 1880 this.observerScrollHeightEnable = true; 1881 let jankRowParent: any; 1882 if (d.rowId === 'actual frameTime') { 1883 jankRowParent = this.shadowRoot?.querySelector<TraceRow<JankStruct>>(`trace-row[row-id='frameTime']`); 1884 } else { 1885 jankRowParent = this.shadowRoot?.querySelector<TraceRow<JankStruct>>(`trace-row[row-id='${d.pid}']`); 1886 } 1887 // jankRowParent!.expansion = true; 1888 let jankRow: any; 1889 jankRowParent.childrenList.forEach((item: TraceRow<JankStruct>) => { 1890 if (item.rowId === `${d.rowId}` && item.rowType === 'janks') { 1891 jankRow = item; 1892 } 1893 }); 1894 let task = () => { 1895 if (jankRow) { 1896 JankStruct.selectJankStructList.length = 0; 1897 let findJankEntry = jankRow!.dataList!.find((dat: any) => dat.name == d.name && dat.pid == d.pid); 1898 if (findJankEntry) { 1899 if ( 1900 findJankEntry!.ts! + findJankEntry!.dur! < TraceRow.range!.startNS || 1901 findJankEntry!.ts! > TraceRow.range!.endNS 1902 ) { 1903 this.timerShaftEL?.setRangeNS( 1904 findJankEntry!.ts! - findJankEntry!.dur! * 2, 1905 findJankEntry!.ts! + findJankEntry!.dur! + findJankEntry!.dur! * 2 1906 ); 1907 } 1908 this.hoverStructNull(); 1909 this.selectStructNull(); 1910 this.wakeupListNull(); 1911 JankStruct.hoverJankStruct = findJankEntry; 1912 JankStruct.selectJankStruct = findJankEntry; 1913 this.timerShaftEL?.drawTriangle(findJankEntry!.ts || 0, 'inverted'); 1914 this.traceSheetEL?.displayJankData( 1915 JankStruct.selectJankStruct!, 1916 (datas) => { 1917 this.removeLinkLinesByBusinessType('janks'); 1918 // 绘制跟自己关联的线 1919 datas.forEach((data) => { 1920 let endParentRow = this.shadowRoot?.querySelector<TraceRow<any>>( 1921 `trace-row[row-id='${data.pid}'][folder]` 1922 ); 1923 this.drawJankLine(endParentRow, JankStruct.selectJankStruct!, data); 1924 }); 1925 }, 1926 jankClickHandler 1927 ); 1928 } 1929 this.scrollToProcess(jankRow.rowId!, jankRow.rowParentId!, jankRow.rowType!, true); 1930 } 1931 }; 1932 if (jankRow) { 1933 this.scrollToProcess(jankRow.rowId!, jankRow.rowParentId!, jankRow.rowType!, false); 1934 } 1935 task(); 1936 }; 1937 1938 scrollToFuncHandler = (funcStract: any) => { 1939 this.observerScrollHeightEnable = true; 1940 this.moveRangeToCenter(funcStract.startTime!, funcStract.dur!); 1941 this.scrollToActFunc(funcStract, false); 1942 }; 1943 1944 snapshotClickHandler = (d: HeapSnapshotStruct) => { 1945 this.observerScrollHeightEnable = true; 1946 let snapshotRow = this.shadowRoot?.querySelector<TraceRow<HeapSnapshotStruct>>( 1947 `trace-row[row-id='heapsnapshot']` 1948 ); 1949 let task = () => { 1950 if (snapshotRow) { 1951 let findEntry = snapshotRow!.dataList!.find((dat) => dat.startTs === d.startTs); 1952 this.hoverStructNull(); 1953 this.selectStructNull(); 1954 this.wakeupListNull(); 1955 HeapSnapshotStruct.hoverSnapshotStruct = findEntry; 1956 HeapSnapshotStruct.selectSnapshotStruct = findEntry; 1957 } 1958 }; 1959 if (snapshotRow) { 1960 if (snapshotRow!.isComplete) { 1961 task(); 1962 } else { 1963 snapshotRow!.onComplete = task; 1964 } 1965 } 1966 }; 1967 if (clickRowType === TraceRow.ROW_TYPE_CPU && CpuStruct.hoverCpuStruct) { 1968 CpuStruct.selectCpuStruct = CpuStruct.hoverCpuStruct; 1969 this.timerShaftEL?.drawTriangle(CpuStruct.selectCpuStruct!.startTime || 0, 'inverted'); 1970 this.traceSheetEL?.displayCpuData( 1971 CpuStruct.selectCpuStruct, 1972 (wakeUpBean) => { 1973 CpuStruct.wakeupBean = wakeUpBean; 1974 this.refreshCanvas(false); 1975 }, 1976 cpuClickHandler 1977 ); 1978 this.timerShaftEL?.modifyFlagList(undefined); 1979 } else if (clickRowType === TraceRow.ROW_TYPE_THREAD && ThreadStruct.hoverThreadStruct) { 1980 ThreadStruct.selectThreadStruct = ThreadStruct.hoverThreadStruct; 1981 this.timerShaftEL?.drawTriangle(ThreadStruct.selectThreadStruct!.startTime || 0, 'inverted'); 1982 this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct, threadClickHandler, cpuClickHandler); 1983 this.timerShaftEL?.modifyFlagList(undefined); 1984 } else if (clickRowType === TraceRow.ROW_TYPE_FUNC && FuncStruct.hoverFuncStruct) { 1985 TabPaneTaskFrames.TaskArray = []; 1986 this.removeLinkLinesByBusinessType('task'); 1987 FuncStruct.selectFuncStruct = FuncStruct.hoverFuncStruct; 1988 let hoverFuncStruct = FuncStruct.hoverFuncStruct; 1989 this.timerShaftEL?.drawTriangle(FuncStruct.selectFuncStruct!.startTs || 0, 'inverted'); 1990 FuncStruct.selectFuncStruct = hoverFuncStruct; 1991 let flagConfig = FlagsConfig.getFlagsConfig('TaskPool'); 1992 let showTabArray: Array<string> = ['current-selection']; 1993 if (flagConfig!.TaskPool === 'Enabled') { 1994 if (FuncStruct.selectFuncStruct !== undefined && FuncStruct.selectFuncStruct.funName !== undefined) { 1995 if (FuncStruct.selectFuncStruct.funName.indexOf('H:Task ') >= 0) { 1996 showTabArray.push('box-task-frames'); 1997 this.drawTaskPollLine(row); 1998 } 1999 } 2000 } 2001 this.traceSheetEL?.displayFuncData(showTabArray, FuncStruct.selectFuncStruct, scrollToFuncHandler); 2002 this.timerShaftEL?.modifyFlagList(undefined); 2003 } else if (clickRowType === TraceRow.ROW_TYPE_CPU_FREQ && CpuFreqStruct.hoverCpuFreqStruct) { 2004 CpuFreqStruct.selectCpuFreqStruct = CpuFreqStruct.hoverCpuFreqStruct; 2005 this.traceSheetEL?.displayFreqData(); 2006 this.timerShaftEL?.modifyFlagList(undefined); 2007 } else if (clickRowType === TraceRow.ROW_TYPE_CPU_STATE && CpuStateStruct.hoverStateStruct) { 2008 CpuStateStruct.selectStateStruct = CpuStateStruct.hoverStateStruct; 2009 this.traceSheetEL?.displayCpuStateData(); 2010 this.timerShaftEL?.modifyFlagList(undefined); 2011 } else if (clickRowType === TraceRow.ROW_TYPE_CPU_FREQ_LIMIT && CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct) { 2012 CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct; 2013 this.traceSheetEL?.displayFreqLimitData(); 2014 this.timerShaftEL?.modifyFlagList(undefined); 2015 } else if (clickRowType === TraceRow.ROW_TYPE_CLOCK && ClockStruct.hoverClockStruct) { 2016 ClockStruct.selectClockStruct = ClockStruct.hoverClockStruct; 2017 this.traceSheetEL?.displayClockData(ClockStruct.selectClockStruct); 2018 this.timerShaftEL?.modifyFlagList(undefined); 2019 } else if (clickRowType === TraceRow.ROW_TYPE_IRQ && IrqStruct.hoverIrqStruct) { 2020 IrqStruct.selectIrqStruct = IrqStruct.hoverIrqStruct; 2021 this.traceSheetEL?.displayIrqData(IrqStruct.selectIrqStruct); 2022 this.timerShaftEL?.modifyFlagList(undefined); 2023 } else if ( 2024 clickRowType === TraceRow.ROW_TYPE_HEAP && 2025 row && 2026 row.getAttribute('heap-type') === 'native_hook_statistic' && 2027 HeapStruct.hoverHeapStruct 2028 ) { 2029 HeapStruct.selectHeapStruct = HeapStruct.hoverHeapStruct; 2030 this.traceSheetEL?.displayNativeHookData(HeapStruct.selectHeapStruct, row.rowId!); 2031 this.timerShaftEL?.modifyFlagList(undefined); 2032 } else if (clickRowType === TraceRow.ROW_TYPE_JANK && JankStruct.hoverJankStruct) { 2033 JankStruct.selectJankStructList.length = 0; 2034 this.removeLinkLinesByBusinessType('janks'); 2035 JankStruct.selectJankStruct = JankStruct.hoverJankStruct; 2036 this.timerShaftEL?.drawTriangle(JankStruct.selectJankStruct!.ts || 0, 'inverted'); 2037 this.traceSheetEL?.displayJankData( 2038 JankStruct.selectJankStruct, 2039 (datas) => { 2040 datas.forEach((data) => { 2041 let endParentRow; 2042 if (data.frame_type == 'frameTime') { 2043 endParentRow = this.shadowRoot?.querySelector<TraceRow<JankStruct>>( 2044 `trace-row[row-id='frameTime'][row-type='janks']` 2045 ); 2046 } else { 2047 endParentRow = this.shadowRoot?.querySelector<TraceRow<any>>(`trace-row[row-id='${data.pid}'][folder]`); 2048 } 2049 this.drawJankLine(endParentRow, JankStruct.selectJankStruct!, data); 2050 }); 2051 }, 2052 jankClickHandler 2053 ); 2054 } else if (clickRowType === TraceRow.ROW_TYPE_HEAP_SNAPSHOT && HeapSnapshotStruct.hoverSnapshotStruct) { 2055 let snapshotRow = this.shadowRoot?.querySelector<TraceRow<HeapSnapshotStruct>>( 2056 `trace-row[row-id='heapsnapshot']` 2057 ); 2058 HeapSnapshotStruct.selectSnapshotStruct = HeapSnapshotStruct.hoverSnapshotStruct; 2059 this.traceSheetEL?.displaySnapshotData( 2060 HeapSnapshotStruct.selectSnapshotStruct!, 2061 snapshotRow!.dataList, 2062 snapshotClickHandler 2063 ); 2064 } else if (clickRowType === TraceRow.ROW_TYPE_APP_STARTUP && AppStartupStruct.hoverStartupStruct) { 2065 AppStartupStruct.selectStartupStruct = AppStartupStruct.hoverStartupStruct; 2066 this.traceSheetEL?.displayStartupData(AppStartupStruct.selectStartupStruct, scrollToFuncHandler); 2067 this.timerShaftEL?.modifyFlagList(undefined); 2068 } else if (clickRowType === TraceRow.ROW_TYPE_STATIC_INIT && SoStruct.hoverSoStruct) { 2069 SoStruct.selectSoStruct = SoStruct.hoverSoStruct; 2070 this.traceSheetEL?.displayStaticInitData(SoStruct.selectSoStruct, scrollToFuncHandler); 2071 this.timerShaftEL?.modifyFlagList(undefined); 2072 } else { 2073 if (!JankStruct.hoverJankStruct && JankStruct.delJankLineFlag) { 2074 this.removeLinkLinesByBusinessType('janks'); 2075 } 2076 this.observerScrollHeightEnable = false; 2077 this.selectFlag = null; 2078 this.timerShaftEL?.removeTriangle('inverted'); 2079 if (!SportRuler.isMouseInSportRuler) { 2080 this.traceSheetEL?.setAttribute('mode', 'hidden'); 2081 this.refreshCanvas(true); 2082 } 2083 } 2084 if (!JankStruct.selectJankStruct) { 2085 this.removeLinkLinesByBusinessType('janks'); 2086 } 2087 if (row) { 2088 let pointEvent = this.createPointEvent(row); 2089 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 2090 action: 'trace_row', 2091 event: pointEvent, 2092 }); 2093 } 2094 } 2095 2096 makePoint( 2097 ts: number, 2098 dur: number, 2099 translateY: number, 2100 rowStruct: any, 2101 offsetY: number, 2102 business: string, 2103 lineType: LineType, 2104 isRight: boolean 2105 ): PairPoint { 2106 return { 2107 x: ns2xByTimeShaft(ts + dur, this.timerShaftEL!), 2108 y: translateY!, 2109 offsetY: offsetY, 2110 ns: ts + dur, 2111 rowEL: rowStruct!, 2112 isRight: isRight, 2113 business: business, 2114 lineType: lineType, 2115 }; 2116 } 2117 2118 drawTaskPollLine(row?: TraceRow<any>) { 2119 let executeID = TabPaneTaskFrames.getExecuteId(FuncStruct.selectFuncStruct!.funName!); 2120 TabPaneTaskFrames.TaskArray.push(FuncStruct.selectFuncStruct!); 2121 if (!row) { 2122 return; 2123 } 2124 if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task Perform:') >= 0) { 2125 TabPaneTaskFrames.IsShowConcurrency = true; 2126 queryBySelectExecute(executeID).then((res) => { 2127 if (res.length === 1) { 2128 let allocationRowId = res[0].tid; 2129 let selectRow = this.shadowRoot?.querySelector<TraceRow<FuncStruct>>( 2130 `trace-row[row-id='${allocationRowId}'][row-type=\'func\']` 2131 ); 2132 selectRow!.dataList.forEach((value) => { 2133 // allocation to execute 2134 if (value.id === res[0].allocation_task_row) { 2135 TabPaneTaskFrames.TaskArray.push(value); 2136 this.addPointPair( 2137 this.makePoint( 2138 value.startTs!, 2139 0, 2140 selectRow?.translateY!, 2141 selectRow, 2142 (value.depth! + 0.5) * 20, 2143 'task', 2144 LineType.bezierCurve, 2145 true 2146 ), 2147 this.makePoint( 2148 FuncStruct.selectFuncStruct!.startTs!, 2149 0, 2150 row?.translateY!, 2151 row, 2152 25, 2153 'task', 2154 LineType.bezierCurve, 2155 true 2156 ) 2157 ); 2158 } 2159 // execute to return 2160 if (value.id === res[0].return_task_row) { 2161 TabPaneTaskFrames.TaskArray.push(value); 2162 this.addPointPair( 2163 this.makePoint( 2164 FuncStruct.selectFuncStruct!.startTs!, 2165 FuncStruct.selectFuncStruct!.dur!, 2166 row?.translateY!, 2167 row, 2168 25, 2169 'task', 2170 LineType.bezierCurve, 2171 false 2172 ), 2173 this.makePoint( 2174 value.startTs!, 2175 value.dur!, 2176 selectRow?.translateY!, 2177 selectRow, 2178 (value.depth! + 0.5) * 20, 2179 'task', 2180 LineType.bezierCurve, 2181 false 2182 ) 2183 ); 2184 } 2185 }); 2186 this.refreshCanvas(true); 2187 } 2188 }); 2189 } else { 2190 TabPaneTaskFrames.IsShowConcurrency = false; 2191 queryBySelectAllocationOrReturn(executeID).then((res) => { 2192 if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task Allocation:') >= 0 && res.length > 0) { 2193 let executeRow = this.shadowRoot?.querySelector<TraceRow<FuncStruct>>( 2194 `trace-row[row-id='${res[0].tid}'][row-type='func']` 2195 ); 2196 let endStruct: FuncStruct; 2197 row!.dataList.forEach((value) => { 2198 if (value.id === res[0].return_task_row) { 2199 TabPaneTaskFrames.TaskArray.push(value); 2200 endStruct = value; 2201 } 2202 }); 2203 if (!executeRow) { 2204 return; 2205 } 2206 executeRow!.dataList.forEach((value) => { 2207 if (value.id === res[0].execute_task_row) { 2208 TabPaneTaskFrames.TaskArray.push(value); 2209 this.addPointPair( 2210 this.makePoint( 2211 FuncStruct.selectFuncStruct!.startTs!, 2212 0, 2213 row?.translateY!, 2214 row, 2215 (FuncStruct.selectFuncStruct!.depth! + 0.5) * 20, 2216 'task', 2217 LineType.bezierCurve, 2218 true 2219 ), 2220 this.makePoint( 2221 value.startTs!, 2222 0, 2223 executeRow?.translateY!, 2224 executeRow, 2225 (value.depth! + 0.5) * 20, 2226 'task', 2227 LineType.bezierCurve, 2228 true 2229 ) 2230 ); 2231 this.addPointPair( 2232 this.makePoint( 2233 value.startTs!, 2234 value.dur!, 2235 executeRow?.translateY!, 2236 executeRow, 2237 (value.depth! + 0.5) * 20, 2238 'task', 2239 LineType.bezierCurve, 2240 false 2241 ), 2242 this.makePoint( 2243 endStruct.startTs!, 2244 endStruct.dur!, 2245 row?.translateY!, 2246 row, 2247 (value.depth! + 0.5) * 20, 2248 'task', 2249 LineType.bezierCurve, 2250 false 2251 ) 2252 ); 2253 } 2254 }); 2255 } else if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task PerformTask End:') >= 0) { 2256 let executeRow = this.shadowRoot?.querySelector<TraceRow<FuncStruct>>( 2257 `trace-row[row-id='${res[0].tid}'][row-type='func']` 2258 ); 2259 TabPaneTaskFrames.TaskArray.push(FuncStruct.selectFuncStruct!); 2260 let startStruct: FuncStruct; 2261 row!.dataList.forEach((value) => { 2262 if (value.id === res[0].allocation_task_row) { 2263 TabPaneTaskFrames.TaskArray.push(value); 2264 startStruct = value; 2265 } 2266 }); 2267 executeRow!.dataList.forEach((value) => { 2268 if (value.id === res[0].execute_task_row) { 2269 TabPaneTaskFrames.TaskArray.push(value); 2270 this.addPointPair( 2271 this.makePoint( 2272 startStruct!.startTs!, 2273 0, 2274 row?.translateY!, 2275 row, 2276 (startStruct!.depth! + 0.5) * 20, 2277 'task', 2278 LineType.bezierCurve, 2279 true 2280 ), 2281 this.makePoint( 2282 value.startTs!, 2283 0, 2284 executeRow?.translateY!, 2285 executeRow, 2286 (value.depth! + 0.5) * 20, 2287 'task', 2288 LineType.bezierCurve, 2289 true 2290 ) 2291 ); 2292 this.addPointPair( 2293 this.makePoint( 2294 value.startTs!, 2295 value.dur!, 2296 executeRow?.translateY!, 2297 executeRow, 2298 (value.depth! + 0.5) * 20, 2299 'task', 2300 LineType.bezierCurve, 2301 false 2302 ), 2303 this.makePoint( 2304 FuncStruct.selectFuncStruct!.startTs!, 2305 FuncStruct.selectFuncStruct!.dur!, 2306 row?.translateY!, 2307 row, 2308 (value.depth! + 0.5) * 20, 2309 'task', 2310 LineType.bezierCurve, 2311 false 2312 ) 2313 ); 2314 } 2315 }); 2316 } 2317 this.refreshCanvas(true); 2318 }); 2319 } 2320 } 2321 drawJankLine(endParentRow: any, selectJankStruct: JankStruct, data: any) { 2322 let startRow: any; 2323 if (selectJankStruct == undefined || selectJankStruct == null) { 2324 return; 2325 } 2326 if (selectJankStruct.frame_type == 'frameTime') { 2327 startRow = this.shadowRoot?.querySelector<TraceRow<JankStruct>>( 2328 "trace-row[row-id='actual frameTime'][row-type='janks']" 2329 ); 2330 } else { 2331 startRow = this.shadowRoot?.querySelector<TraceRow<JankStruct>>( 2332 `trace-row[row-id='${`${selectJankStruct?.type}-${selectJankStruct?.pid}`}'][row-type='janks']` 2333 ); 2334 } 2335 if (endParentRow) { 2336 //终点的父泳道过滤出选中的Struct 2337 let endRowStruct: any; 2338 //泳道展开的情况,查找endRowStruct 2339 if (data.frame_type == 'frameTime') { 2340 endRowStruct = this.shadowRoot?.querySelector<TraceRow<JankStruct>>( 2341 "trace-row[row-id='actual frameTime'][row-type='janks']" 2342 ); 2343 } else { 2344 endRowStruct = this.shadowRoot?.querySelector<TraceRow<JankStruct>>( 2345 `trace-row[row-id='${`${data.type}-${data.pid}`}'][row-type='janks']` 2346 ); 2347 } 2348 //泳道未展开的情况,查找endRowStruct 2349 if (!endRowStruct) { 2350 if (data.frame_type == 'frameTime') { 2351 endParentRow.childrenList.forEach((item: TraceRow<JankStruct>) => { 2352 if (item.rowId === 'actual frameTime' && item.rowType === 'janks') { 2353 endRowStruct = item; 2354 } 2355 }); 2356 //frameTime未展开 2357 if (!endRowStruct) { 2358 endParentRow = this.shadowRoot?.querySelector<TraceRow<JankStruct>>( 2359 "trace-row[row-id='frameTime'][folder]" 2360 ); 2361 endParentRow?.childrenList?.forEach((item: TraceRow<JankStruct>) => { 2362 if (item.rowId === 'actual frameTime' && item.rowType === 'janks') { 2363 endRowStruct = item; 2364 } 2365 }); 2366 } 2367 } else { 2368 endParentRow.childrenList.forEach((item: TraceRow<JankStruct>) => { 2369 if (item.rowId === `${data.type}-${data.pid}` && item.rowType === 'janks') { 2370 endRowStruct = item; 2371 } 2372 }); 2373 } 2374 } 2375 if (endRowStruct) { 2376 let findJankEntry = endRowStruct!.dataList!.find((dat: any) => dat.name == data.name && dat.pid == data.pid); 2377 //连线规则:frametimeline的头----app的头,app的尾----renderservice的头 2378 let tts: number = 0; 2379 if (findJankEntry) { 2380 if (selectJankStruct.frame_type == 'app') { 2381 tts = 2382 findJankEntry.frame_type == 'frameTime' 2383 ? selectJankStruct.ts! 2384 : selectJankStruct.ts! + selectJankStruct.dur!; 2385 let startParentRow: any; 2386 // startRow为子泳道,子泳道不存在,使用父泳道 2387 if (startRow) { 2388 startParentRow = this.shadowRoot?.querySelector<TraceRow<JankStruct>>( 2389 `trace-row[row-id='${startRow.rowParentId}'][folder]` 2390 ); 2391 } else { 2392 startRow = this.shadowRoot?.querySelector<TraceRow<JankStruct>>( 2393 `trace-row[row-id='${selectJankStruct?.pid}'][folder]` 2394 ); 2395 } 2396 let endY = endRowStruct!.translateY! + 20 * (findJankEntry!.depth! + 0.5); 2397 let endRowEl = endRowStruct; 2398 let endOffSetY = 20 * (findJankEntry!.depth! + 0.5); 2399 if (!endParentRow.expansion) { 2400 endY = endParentRow!.translateY! + 10 * (findJankEntry!.depth! + 0.5); 2401 endRowEl = endParentRow; 2402 endOffSetY = 10 * (findJankEntry!.depth! + 0.5); 2403 } 2404 let startY = startRow!.translateY! + 20 * (selectJankStruct!.depth! + 0.5); 2405 let startRowEl = startRow; 2406 let startOffSetY = 20 * (selectJankStruct!.depth! + 0.5); 2407 if (startParentRow && !startParentRow.expansion) { 2408 startY = startParentRow!.translateY! + 10 * (selectJankStruct!.depth! + 0.5); 2409 startRowEl = startParentRow; 2410 startOffSetY = 10 * (selectJankStruct!.depth! + 0.5); 2411 } 2412 this.addPointPair( 2413 { 2414 x: ns2xByTimeShaft(tts, this.timerShaftEL!), 2415 y: startY, 2416 offsetY: startOffSetY, 2417 ns: tts, 2418 rowEL: startRowEl!, 2419 isRight: selectJankStruct.ts == tts, 2420 business: 'janks', 2421 }, 2422 { 2423 x: ns2xByTimeShaft(findJankEntry.ts!, this.timerShaftEL!), 2424 y: endY, 2425 offsetY: endOffSetY, 2426 ns: findJankEntry.ts!, 2427 rowEL: endRowEl, 2428 isRight: true, 2429 business: 'janks', 2430 } 2431 ); 2432 } 2433 if (findJankEntry.frame_type == 'app') { 2434 tts = 2435 selectJankStruct.frame_type == 'frameTime' ? findJankEntry.ts : findJankEntry.ts! + findJankEntry.dur!; 2436 let endY = endRowStruct!.translateY! + 20 * (findJankEntry!.depth! + 0.5); 2437 let endRowEl = endRowStruct; 2438 let endOffSetY = 20 * (findJankEntry!.depth! + 0.5); 2439 if (!endParentRow.expansion) { 2440 endY = endParentRow!.translateY! + 10 * (findJankEntry!.depth! + 0.5); 2441 endRowEl = endParentRow; 2442 endOffSetY = 10 * (findJankEntry!.depth! + 0.5); 2443 } 2444 let startY = startRow!.translateY! + 20 * (selectJankStruct!.depth! + 0.5); 2445 let startRowEl = startRow; 2446 let startOffsetY = 20 * (selectJankStruct!.depth! + 0.5); 2447 let startParentRow = this.shadowRoot?.querySelector<TraceRow<JankStruct>>( 2448 `trace-row[row-id='${startRow.rowParentId}'][folder]` 2449 ); 2450 if (startParentRow && !startParentRow.expansion) { 2451 startY = startParentRow!.translateY! + 10 * (selectJankStruct!.depth! + 0.5); 2452 startRowEl = startParentRow; 2453 startOffsetY = 10 * (selectJankStruct!.depth! + 0.5); 2454 } 2455 this.addPointPair( 2456 { 2457 x: ns2xByTimeShaft(selectJankStruct.ts!, this.timerShaftEL!), 2458 y: startY, 2459 offsetY: startOffsetY, 2460 ns: selectJankStruct.ts!, 2461 rowEL: startRowEl!, 2462 isRight: true, 2463 business: 'janks', 2464 }, 2465 { 2466 x: ns2xByTimeShaft(tts, this.timerShaftEL!), 2467 y: endY, 2468 offsetY: endOffSetY, 2469 ns: tts, 2470 rowEL: endRowEl!, 2471 isRight: selectJankStruct.ts == tts, 2472 business: 'janks', 2473 } 2474 ); 2475 } 2476 if (data.children.length >= 1) { 2477 let endP; 2478 if (data.children[0].frame_type == 'frameTime') { 2479 endP = this.shadowRoot?.querySelector<TraceRow<any>>("trace-row[row-id='frameTime']"); 2480 } else { 2481 endP = this.shadowRoot?.querySelector<TraceRow<any>>( 2482 `trace-row[row-id='${data.children[0].pid}'][folder]` 2483 ); 2484 } 2485 this.drawJankLine(endP, findJankEntry, data.children[0]); 2486 } 2487 this.refreshCanvas(true); 2488 } 2489 } 2490 } 2491 } 2492 2493 myMouseMove = (ev: MouseEvent) => { 2494 if (ev.ctrlKey) { 2495 ev.preventDefault(); 2496 SpSystemTrace.offsetMouse = ev.clientX - SpSystemTrace.mouseCurrentPosition; 2497 let eventA = new KeyboardEvent('keypress', { 2498 key: 'a', 2499 code: '65', 2500 keyCode: 65, 2501 }); 2502 let eventD = new KeyboardEvent('keypress', { 2503 key: 'd', 2504 code: '68', 2505 keyCode: 68, 2506 }); 2507 if (ev.button == 0) { 2508 if (SpSystemTrace.offsetMouse < 0 && SpSystemTrace.moveable) { 2509 // 向右拖动,则泳道图右移 2510 this.timerShaftEL!.documentOnKeyPress(eventD); 2511 setTimeout(() => { 2512 this.timerShaftEL!.documentOnKeyUp(eventD); 2513 }, 350); 2514 } 2515 if (SpSystemTrace.offsetMouse > 0 && SpSystemTrace.moveable) { 2516 // 向左拖动,则泳道图左移 2517 this.timerShaftEL!.documentOnKeyPress(eventA); 2518 setTimeout(() => { 2519 this.timerShaftEL!.documentOnKeyUp(eventA); 2520 }, 350); 2521 } 2522 } 2523 SpSystemTrace.moveable = false; 2524 } 2525 }; 2526 2527 connectedCallback() { 2528 this.initPointToEvent(); 2529 /** 2530 * 监听时间轴区间变化 2531 */ 2532 this.timerShaftEL!.rangeChangeHandler = this.timerShaftELRangeChange; 2533 this.timerShaftEL!.rangeClickHandler = this.timerShaftELRangeClick; 2534 this.timerShaftEL!.flagChangeHandler = this.timerShaftELFlagChange; 2535 this.timerShaftEL!.flagClickHandler = this.timerShaftELFlagClickHandler; 2536 /** 2537 * 监听rowsEL的滚动时间,刷新可见区域的trace-row组件的时间区间(将触发trace-row组件重绘) 2538 */ 2539 this.rowsPaneEL?.addEventListener('scroll', this.rowsElOnScroll, { 2540 passive: true, 2541 }); 2542 this.favoriteRowsEL?.addEventListener('scroll', this.favoriteRowsElOnScroll, { passive: true }); 2543 /** 2544 * 监听document的mousemove事件 坐标通过换算后找到当前鼠标所在的trace-row组件,将坐标传入 2545 */ 2546 this.addEventListener('mousemove', this.documentOnMouseMove); 2547 this.addEventListener('click', this.documentOnClick); 2548 this.addEventListener('mousedown', this.documentOnMouseDown); 2549 this.addEventListener('mouseup', this.documentOnMouseUp); 2550 this.addEventListener('mouseout', this.documentOnMouseOut); 2551 2552 document.addEventListener('keypress', this.documentOnKeyPress); 2553 document.addEventListener('keyup', this.documentOnKeyUp); 2554 document.addEventListener('contextmenu', this.onContextMenuHandler); 2555 2556 /** 2557 * 获取并保存鼠标当前的x轴坐标位置,配合ctrl+鼠标左键拖动完成泳道图的左移或右移 2558 */ 2559 this.addEventListener( 2560 'mousedown', 2561 (e) => { 2562 if (e.ctrlKey) { 2563 e.preventDefault(); 2564 this.removeEventListener('mousemove', this.documentOnMouseMove); 2565 this.removeEventListener('click', this.documentOnClick); 2566 this.removeEventListener('mousedown', this.documentOnMouseDown); 2567 this.removeEventListener('mouseup', this.documentOnMouseUp); 2568 this.style.cursor = 'move'; 2569 SpSystemTrace.moveable = true; 2570 SpSystemTrace.mouseCurrentPosition = e.clientX; 2571 } 2572 }, 2573 { passive: false } 2574 ); 2575 /** 2576 * ctrl+鼠标移动,实现泳道图左移或者右移。 2577 */ 2578 this.addEventListener('mousemove', (ev) => throttle(this.myMouseMove, 350, ev)(), { passive: false }); 2579 2580 this.addEventListener( 2581 'mouseup', 2582 (e) => { 2583 if (e.ctrlKey) { 2584 e.preventDefault(); 2585 SpSystemTrace.offsetMouse = 0; 2586 SpSystemTrace.mouseCurrentPosition = 0; 2587 SpSystemTrace.moveable = false; 2588 this.style.cursor = 'default'; 2589 this.addEventListener('mousemove', this.documentOnMouseMove); 2590 this.addEventListener('click', this.documentOnClick); 2591 this.addEventListener('mousedown', this.documentOnMouseDown); 2592 this.addEventListener('mouseup', this.documentOnMouseUp); 2593 } 2594 }, 2595 { passive: false } 2596 ); 2597 2598 /** 2599 * 泳道图中添加ctrl+鼠标滚轮事件,对泳道图进行放大缩小。 2600 * 鼠标滚轮事件转化为键盘事件,keyPress和keyUp两个事件需要配合使用, 2601 * 否则泳道图会一直放大或一直缩小。 2602 * setTimeout()函数中的时间参数可以控制鼠标滚轮的频率。 2603 */ 2604 document.addEventListener( 2605 'wheel', 2606 (e) => { 2607 if (e.ctrlKey) { 2608 if (e.deltaY > 0) { 2609 e.preventDefault(); 2610 e.stopPropagation(); 2611 let eventS = new KeyboardEvent('keypress', { 2612 key: 's', 2613 code: '83', 2614 keyCode: 83, 2615 }); 2616 this.timerShaftEL!.documentOnKeyPress(eventS); 2617 setTimeout(() => { 2618 this.timerShaftEL!.documentOnKeyUp(eventS); 2619 }, 200); 2620 } 2621 if (e.deltaY < 0) { 2622 e.preventDefault(); 2623 e.stopPropagation(); 2624 let eventW = new KeyboardEvent('keypress', { 2625 key: 'w', 2626 code: '87', 2627 keyCode: 87, 2628 }); 2629 this.timerShaftEL!.documentOnKeyPress(eventW); 2630 setTimeout(() => { 2631 this.timerShaftEL!.documentOnKeyUp(eventW); 2632 }, 200); 2633 } 2634 } 2635 }, 2636 { passive: false } 2637 ); 2638 2639 SpApplication.skinChange2 = (val: boolean) => { 2640 this.timerShaftEL?.render(); 2641 }; 2642 window.subscribe(window.SmartEvent.UI.UploadSOFile, (data) => { 2643 this.chartManager?.importSoFileUpdate().then(() => { 2644 window.publish(window.SmartEvent.UI.Loading, false); 2645 let updateCanvas = this.traceSheetEL?.updateRangeSelect(); 2646 if (updateCanvas) { 2647 this.refreshCanvas(true); 2648 } 2649 }); 2650 }); 2651 window.subscribe(window.SmartEvent.UI.CheckALL, (data) => { 2652 this.favoriteRowsEL?.querySelectorAll<TraceRow<any>>(`trace-row[row-parent-id='${data.rowId}']`).forEach((it) => { 2653 it.checkType = data.isCheck ? '2' : '0'; 2654 }); 2655 }); 2656 } 2657 2658 scrollToProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) { 2659 let rootRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); 2660 if (rootRow?.collect) { 2661 this.favoriteRowsEL!.scroll({ 2662 top: (rootRow?.offsetTop || 0) - this.canvasFavoritePanel!.offsetHeight + (rootRow?.offsetHeight || 0), 2663 left: 0, 2664 behavior: smooth ? 'smooth' : undefined, 2665 }); 2666 } else { 2667 let row = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`); 2668 if (row && !row.expansion) { 2669 row.expansion = true; 2670 } 2671 if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) { 2672 this.rowsPaneEL!.scroll({ 2673 top: (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + (rootRow?.offsetHeight || 0), 2674 left: 0, 2675 behavior: smooth ? 'smooth' : undefined, 2676 }); 2677 } 2678 } 2679 } 2680 2681 scrollToDepth(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true, depth: number) { 2682 let rootRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); 2683 if (rootRow && rootRow!.collect) { 2684 this.favoriteRowsEL!.scroll({ 2685 top: (rootRow?.offsetTop || 0) - this.canvasFavoritePanel!.offsetHeight + (++depth * 20 || 0), 2686 left: 0, 2687 behavior: smooth ? 'smooth' : undefined, 2688 }); 2689 } else { 2690 let row = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`); 2691 if (row && !row.expansion) { 2692 row.expansion = true; 2693 } 2694 if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) { 2695 this.rowsPaneEL!.scroll({ 2696 top: (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + (++depth * 20 || 0), 2697 left: 0, 2698 behavior: smooth ? 'smooth' : undefined, 2699 }); 2700 } 2701 } 2702 } 2703 2704 scrollToFunction(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) { 2705 let condition = `trace-row[row-id='${rowId}'][row-type='${rowType}'][row-parent-id='${rowParentId}']`; 2706 let rootRow = this.shadowRoot!.querySelector<TraceRow<any>>(condition); 2707 if (rootRow?.collect) { 2708 this.favoriteRowsEL!.scroll({ 2709 top: (rootRow?.offsetTop || 0) - this.canvasFavoritePanel!.offsetHeight + (rootRow?.offsetHeight || 0), 2710 left: 0, 2711 behavior: smooth ? 'smooth' : undefined, 2712 }); 2713 } else { 2714 let row = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`); 2715 if (row && !row.expansion) { 2716 row.expansion = true; 2717 } 2718 if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) { 2719 this.rowsPaneEL!.scroll({ 2720 top: (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + 20, 2721 left: 0, 2722 behavior: smooth ? 'smooth' : undefined, 2723 }); 2724 } 2725 } 2726 } 2727 2728 rowScrollTo(offset: number, callback: Function) { 2729 const fixedOffset = offset; 2730 const onScroll = () => { 2731 if (this.rowsPaneEL!.scrollTop === fixedOffset) { 2732 this.rowsEL!.removeEventListener('scroll', onScroll); 2733 callback(); 2734 } 2735 }; 2736 2737 this.rowsEL!.addEventListener('scroll', onScroll); 2738 onScroll(); 2739 this.rowsPaneEL!.scrollTo({ 2740 top: offset, 2741 behavior: 'smooth', 2742 }); 2743 } 2744 2745 disconnectedCallback() { 2746 this.timerShaftEL?.removeEventListener('range-change', this.timerShaftELRangeChange); 2747 this.rowsPaneEL?.removeEventListener('scroll', this.rowsElOnScroll); 2748 this.favoriteRowsEL?.removeEventListener('scroll', this.favoriteRowsElOnScroll); 2749 this.removeEventListener('mousemove', this.documentOnMouseMove); 2750 this.removeEventListener('click', this.documentOnClick); 2751 this.removeEventListener('mousedown', this.documentOnMouseDown); 2752 this.removeEventListener('mouseup', this.documentOnMouseUp); 2753 this.removeEventListener('mouseout', this.documentOnMouseOut); 2754 document.removeEventListener('keypress', this.documentOnKeyPress); 2755 document.removeEventListener('keyup', this.documentOnKeyUp); 2756 document.removeEventListener('contextmenu', this.onContextMenuHandler); 2757 window.unsubscribe(window.SmartEvent.UI.SliceMark, this.sliceMarkEventHandler.bind(this)); 2758 } 2759 2760 sliceMarkEventHandler(ev: any) { 2761 SpSystemTrace.sliceRangeMark = ev; 2762 let startNS = ev.timestamp - (window as any).recordStartNS; 2763 let endNS = ev.maxDuration + startNS; 2764 TraceRow.rangeSelectObject = { 2765 startX: 0, 2766 startNS: startNS, 2767 endNS: endNS, 2768 endX: 0, 2769 }; 2770 window.publish(window.SmartEvent.UI.MenuTrace, {}); 2771 window.publish(window.SmartEvent.UI.TimeRange, { 2772 startNS: startNS - ev.maxDuration, 2773 endNS: endNS + ev.maxDuration, 2774 }); 2775 this.shadowRoot?.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => { 2776 it.checkType = '-1'; 2777 }); 2778 this.rangeSelect.rangeTraceRow = []; 2779 this.selectStructNull(); 2780 this.wakeupListNull(); 2781 this.traceSheetEL?.setAttribute('mode', 'hidden'); 2782 this.removeLinkLinesByBusinessType('janks'); 2783 TraceRow.range!.refresh = true; 2784 this.refreshCanvas(false); 2785 } 2786 2787 loadDatabaseUrl( 2788 url: string, 2789 progress: Function, 2790 complete?: ((res: { status: boolean; msg: string }) => void) | undefined 2791 ) { 2792 this.observerScrollHeightEnable = false; 2793 this.init({ url: url }, '', progress).then((res) => { 2794 if (complete) { 2795 complete(res); 2796 } 2797 }); 2798 } 2799 2800 loadDatabaseArrayBuffer( 2801 buf: ArrayBuffer, 2802 thirdPartyWasmConfigUrl: string, 2803 progress: (name: string, percent: number) => void, 2804 complete?: ((res: { status: boolean; msg: string }) => void) | undefined 2805 ) { 2806 this.observerScrollHeightEnable = false; 2807 this.init({ buf }, thirdPartyWasmConfigUrl, progress).then((res) => { 2808 let scrollTop = this.rowsEL?.scrollTop || 0; 2809 let scrollHeight = this.rowsEL?.clientHeight || 0; 2810 this.rowsEL?.querySelectorAll('trace-row').forEach((it: any) => this.observer.observe(it)); 2811 if (complete) { 2812 complete(res); 2813 } 2814 }); 2815 } 2816 2817 search(query: string) { 2818 this.shadowRoot?.querySelectorAll<TraceRow<any>>('trace-row').forEach((item) => { 2819 if (query == null || query == undefined || query == '') { 2820 if ( 2821 item.rowType == TraceRow.ROW_TYPE_CPU || 2822 item.rowType == TraceRow.ROW_TYPE_CPU_FREQ || 2823 item.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY || 2824 item.rowType == TraceRow.ROW_TYPE_FPS || 2825 item.rowType == TraceRow.ROW_TYPE_PROCESS || 2826 item.rowType == TraceRow.ROW_TYPE_CPU_ABILITY || 2827 item.rowType == TraceRow.ROW_TYPE_MEMORY_ABILITY || 2828 item.rowType == TraceRow.ROW_TYPE_DISK_ABILITY || 2829 item.rowType == TraceRow.ROW_TYPE_NETWORK_ABILITY 2830 ) { 2831 item.expansion = false; 2832 item.rowHidden = false; 2833 } else { 2834 item.rowHidden = true; 2835 } 2836 } else { 2837 if (item.name.toLowerCase().indexOf(query.toLowerCase()) >= 0) { 2838 item.rowHidden = false; 2839 } else { 2840 item.rowHidden = true; 2841 } 2842 } 2843 }); 2844 this.visibleRows.forEach((it) => (it.rowHidden = false && it.draw(true))); 2845 } 2846 2847 searchCPU(query: string): Array<CpuStruct> { 2848 let traceRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[scene]`); 2849 let dataAll = `trace-row[row-type='cpu-data']`; 2850 if (traceRow) { 2851 dataAll = `trace-row[row-type='cpu-data'][scene]`; 2852 } 2853 let searchResults: Array<CpuStruct> = []; 2854 this.shadowRoot!.querySelectorAll<TraceRow<any>>(`${dataAll}`).forEach((item) => { 2855 let res = item!.dataList!.filter( 2856 (it) => 2857 (it.name && it.name.indexOf(query) >= 0) || 2858 it.tid == query || 2859 it.processId == query || 2860 (it.processName && it.processName.indexOf(query) >= 0) 2861 ); 2862 searchResults.push(...res); 2863 }); 2864 searchResults.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); 2865 return searchResults; 2866 } 2867 2868 async searchFunction(cpuList: Array<any>, query: string): Promise<Array<any>> { 2869 let processList: Array<string> = []; 2870 let traceRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[scene]`); 2871 if (traceRow) { 2872 this.shadowRoot!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='process'][scene]`).forEach((row) => { 2873 processList.push(row.rowId!); 2874 }); 2875 let list = await querySceneSearchFunc(query, processList); 2876 cpuList = cpuList.concat(list); 2877 cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); 2878 return cpuList; 2879 } else { 2880 let list = await querySearchFunc(query); 2881 cpuList = cpuList.concat(list); 2882 cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); 2883 return cpuList; 2884 } 2885 } 2886 2887 searchSdk(dataList: Array<any>, query: string): Array<any> { 2888 let traceRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[scene]`); 2889 let dataAll = `trace-row[row-type^='sdk']`; 2890 if (traceRow) { 2891 dataAll = `trace-row[row-type^='sdk'][scene]`; 2892 } 2893 let allTraceRow: any = []; 2894 let parentRows = this.shadowRoot!.querySelectorAll<TraceRow<any>>(`${dataAll}`); 2895 parentRows.forEach((parentRow: TraceRow<any>) => { 2896 allTraceRow.push(parentRow); 2897 if (parentRow.childrenList && parentRow.childrenList.length > 0) { 2898 allTraceRow.push(...parentRow.childrenList); 2899 } 2900 }); 2901 allTraceRow.forEach((row: any) => { 2902 if (row!.name.indexOf(query) >= 0) { 2903 let searchSdkBean = new SearchSdkBean(); 2904 searchSdkBean.startTime = TraceRow.range!.startNS; 2905 searchSdkBean.dur = TraceRow.range!.totalNS; 2906 searchSdkBean.name = row.name; 2907 searchSdkBean.rowId = row.rowId; 2908 searchSdkBean.type = 'sdk'; 2909 searchSdkBean.rowType = row.rowType; 2910 searchSdkBean.rowParentId = row.rowParentId; 2911 dataList.push(searchSdkBean); 2912 } 2913 }); 2914 return dataList; 2915 } 2916 2917 searchThreadsAndProcesses(query: string): Array<any> { 2918 let searchResults: Array<any> = []; 2919 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='thread'][row-type='process']`).forEach((item) => { 2920 if (item!.name.indexOf(query) >= 0) { 2921 let searchBean = new SearchThreadProcessBean(); 2922 searchBean.name = item.name; 2923 searchBean.rowId = item.rowId; 2924 searchBean.type = 'thread||process'; 2925 searchBean.rowType = item.rowType; 2926 searchBean.rowParentId = item.rowParentId; 2927 searchResults.push(searchBean); 2928 } 2929 }); 2930 return searchResults; 2931 } 2932 2933 showStruct(previous: boolean, currentIndex: number, structs: Array<any>) { 2934 if (structs.length == 0) { 2935 return 0; 2936 } 2937 let findIndex = -1; 2938 if (previous) { 2939 for (let i = structs.length - 1; i >= 0; i--) { 2940 let it = structs[i]; 2941 if ( 2942 i < currentIndex && 2943 it.startTime! >= TraceRow.range!.startNS && 2944 it.startTime! + it.dur! <= TraceRow.range!.endNS 2945 ) { 2946 findIndex = i; 2947 break; 2948 } 2949 } 2950 } else { 2951 findIndex = structs.findIndex((it, idx) => { 2952 return ( 2953 idx > currentIndex && 2954 it.startTime! >= TraceRow.range!.startNS && 2955 it.startTime! + it.dur! <= TraceRow.range!.endNS 2956 ); 2957 }); 2958 } 2959 let findEntry: any; 2960 if (findIndex >= 0) { 2961 findEntry = structs[findIndex]; 2962 } else { 2963 if (previous) { 2964 for (let i = structs.length - 1; i >= 0; i--) { 2965 let it = structs[i]; 2966 if (it.startTime! + it.dur! < TraceRow.range!.startNS) { 2967 findIndex = i; 2968 break; 2969 } 2970 } 2971 if (findIndex == -1) { 2972 findIndex = structs.length - 1; 2973 } 2974 } else { 2975 findIndex = structs.findIndex((it) => it.startTime! > TraceRow.range!.endNS); 2976 if (findIndex == -1) { 2977 findIndex = 0; 2978 } 2979 } 2980 findEntry = structs[findIndex]; 2981 } 2982 this.moveRangeToCenter(findEntry.startTime!, findEntry.dur!); 2983 this.shadowRoot!.querySelectorAll<TraceRow<any>>(`trace-row`).forEach((item) => { 2984 item.highlight = false; 2985 }); 2986 if (findEntry.type == 'thread') { 2987 CpuStruct.selectCpuStruct = findEntry; 2988 CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; 2989 this.shadowRoot!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach((item) => { 2990 item.highlight = item.rowId == `${findEntry.cpu}`; 2991 item.draw(true); 2992 }); 2993 this.scrollToProcess(`${findEntry.cpu}`, '', 'cpu-data', true); 2994 this.onClickHandler(TraceRow.ROW_TYPE_CPU); 2995 } else if (findEntry.type == 'func') { 2996 this.observerScrollHeightEnable = true; 2997 this.scrollToActFunc(findEntry, true); 2998 } else if (findEntry.type == 'thread||process') { 2999 let threadProcessRow = this.rowsEL?.querySelectorAll<TraceRow<ThreadStruct>>('trace-row')[0]; 3000 if (threadProcessRow) { 3001 let filterRow = threadProcessRow.childrenList.filter( 3002 (row) => row.rowId === findEntry.rowId && row.rowId === findEntry.rowType 3003 )[0]; 3004 filterRow!.highlight = true; 3005 this.closeAllExpandRows(findEntry.rowParentId); 3006 this.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); 3007 let completeEntry = () => { 3008 let searchEntry = filterRow!.dataList!.find((dat) => dat.startTime === findEntry.startTime); 3009 this.hoverStructNull(); 3010 this.selectStructNull(); 3011 this.wakeupListNull(); 3012 ThreadStruct.hoverThreadStruct = searchEntry; 3013 ThreadStruct.selectThreadStruct = searchEntry; 3014 this.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); 3015 }; 3016 if (filterRow!.isComplete) { 3017 completeEntry(); 3018 } else { 3019 filterRow!.onComplete = completeEntry; 3020 } 3021 } 3022 } else if (findEntry.type == 'sdk') { 3023 let parentRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-type='sdk'][folder]`); 3024 if (parentRow) { 3025 let sdkRow = parentRow.childrenList.filter( 3026 (child) => child.rowId === findEntry.rowId && child.rowType === findEntry.rowType 3027 )[0]; 3028 sdkRow!.highlight = true; 3029 } 3030 this.hoverStructNull(); 3031 this.selectStructNull(); 3032 this.wakeupListNull(); 3033 this.onClickHandler(findEntry.rowType!); 3034 this.closeAllExpandRows(findEntry.rowParentId); 3035 this.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); 3036 } 3037 this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, 'inverted'); 3038 return findIndex; 3039 } 3040 3041 scrollToActFunc(funcStract: any, highlight: boolean) { 3042 const toTargetDepth = (entry: any) => { 3043 if (entry) { 3044 this.hoverStructNull(); 3045 this.selectStructNull(); 3046 this.wakeupListNull(); 3047 FuncStruct.hoverFuncStruct = entry; 3048 FuncStruct.selectFuncStruct = entry; 3049 this.onClickHandler(TraceRow.ROW_TYPE_FUNC); 3050 this.scrollToDepth(`${funcRowID}`, `${funcStract.pid}`, funcStract.type, true, entry.depth || 0); 3051 } 3052 }; 3053 let funcRowID = funcStract.cookie == null ? funcStract.tid : `${funcStract.funName}-${funcStract.pid}`; 3054 let targetRow = this.favoriteRowsEL!.querySelector<TraceRow<any>>( 3055 `trace-row[row-id='${funcRowID}'][row-type='func']` 3056 ); 3057 if (targetRow) { 3058 targetRow.highlight = highlight; 3059 //如果目标泳道图在收藏上面,则跳转至收藏 3060 let searchEntry = targetRow!.dataList!.find((dat) => dat.startTs === funcStract.startTime); 3061 toTargetDepth(searchEntry); 3062 return; 3063 } 3064 let parentRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${funcStract.pid}'][folder]`); 3065 if (!parentRow) { 3066 return; 3067 } 3068 let filterRow = parentRow.childrenList.filter((child) => child.rowId == funcRowID && child.rowType == 'func')[0]; 3069 if (filterRow == null) { 3070 let funcRow = this.shadowRoot?.querySelector<TraceRow<any>>(`trace-row[row-id='${funcRowID}'][row-type='func']`); 3071 if (funcRow) { 3072 filterRow = funcRow; 3073 } else { 3074 return; 3075 } 3076 } 3077 filterRow!.highlight = highlight; 3078 if (funcStract.keepOpen !== true) { 3079 this.closeAllExpandRows(funcStract.pid); 3080 } 3081 let row = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${funcStract.pid}'][folder]`); 3082 if (row && !row.expansion) { 3083 row.expansion = true; 3084 } 3085 const completeEntry = () => { 3086 let entry = filterRow!.dataList!.find((dat) => dat.startTs === funcStract.startTime); 3087 toTargetDepth(entry); 3088 }; 3089 if (filterRow!.isComplete) { 3090 completeEntry(); 3091 } else { 3092 FuncStruct.hoverFuncStruct = funcStract; 3093 FuncStruct.selectFuncStruct = funcStract; 3094 this.onClickHandler(TraceRow.ROW_TYPE_FUNC); 3095 this.scrollToProcess(`${funcStract.tid}`, `${funcStract.pid}`, 'process', false); 3096 this.scrollToFunction(`${funcStract.tid}`, `${funcStract.pid}`, 'func', true); 3097 filterRow!.onComplete = completeEntry; 3098 } 3099 } 3100 3101 closeAllExpandRows(pid: string) { 3102 let expandRows = this.rowsEL?.querySelectorAll<TraceRow<ProcessStruct>>(`trace-row[row-type='process'][expansion]`); 3103 expandRows?.forEach((row) => { 3104 if (row.rowId != pid) { 3105 row.expansion = false; 3106 } 3107 }); 3108 } 3109 3110 moveRangeToCenter(startTime: number, dur: number) { 3111 let startNS = this.timerShaftEL?.getRange()?.startNS || 0; 3112 let endNS = this.timerShaftEL?.getRange()?.endNS || 0; 3113 let harfDur = Math.trunc((endNS - startNS) / 2 - dur / 2); 3114 let leftNs = startTime - harfDur; 3115 let rightNs = startTime + dur + harfDur; 3116 if (startTime - harfDur < 0) { 3117 leftNs = 0; 3118 rightNs += harfDur - startTime; 3119 } 3120 this.timerShaftEL?.setRangeNS(leftNs, rightNs); 3121 TraceRow.range!.refresh = true; 3122 this.refreshCanvas(true); 3123 } 3124 3125 showPreCpuStruct(currentIndex: number, cpuStructs: Array<CpuStruct>): number { 3126 if (cpuStructs.length == 0) { 3127 return 0; 3128 } 3129 let findIndex = -1; 3130 for (let i = cpuStructs.length - 1; i >= 0; i--) { 3131 let it = cpuStructs[i]; 3132 if ( 3133 i < currentIndex && 3134 it.startTime! >= TraceRow.range!.startNS && 3135 it.startTime! + it.dur! <= TraceRow.range!.endNS 3136 ) { 3137 findIndex = i; 3138 break; 3139 } 3140 } 3141 if (findIndex >= 0) { 3142 let findEntry = cpuStructs[findIndex]; 3143 CpuStruct.selectCpuStruct = findEntry; 3144 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach((item) => { 3145 item.highlight = item.rowId == `${findEntry.cpu}`; 3146 item.draw(true); 3147 }); 3148 this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, 'inverted'); 3149 } else { 3150 for (let i = cpuStructs.length - 1; i >= 0; i--) { 3151 let it = cpuStructs[i]; 3152 if (it.startTime! + it.dur! < TraceRow.range!.startNS) { 3153 findIndex = i; 3154 break; 3155 } 3156 } 3157 let findEntry: CpuStruct; 3158 if (findIndex == -1) { 3159 findIndex = cpuStructs.length - 1; 3160 } 3161 findEntry = cpuStructs[findIndex]; 3162 CpuStruct.selectCpuStruct = findEntry; 3163 let startNS = this.timerShaftEL?.getRange()?.startNS || 0; 3164 let endNS = this.timerShaftEL?.getRange()?.endNS || 0; 3165 let harfDur = Math.trunc((endNS - startNS) / 2 - findEntry.dur! / 2); 3166 this.timerShaftEL?.setRangeNS(findEntry.startTime! - harfDur, findEntry.startTime! + findEntry.dur! + harfDur); 3167 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach((item) => { 3168 item.highlight = item.rowId == `${findEntry.cpu}`; 3169 item.draw(true); 3170 }); 3171 this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, 'inverted'); 3172 } 3173 CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; 3174 this.onClickHandler(TraceRow.ROW_TYPE_CPU); 3175 return findIndex; 3176 } 3177 3178 showNextCpuStruct(currentIndex: number, cpuStructs: Array<CpuStruct>): number { 3179 if (cpuStructs.length == 0) { 3180 return 0; 3181 } 3182 let findIndex = cpuStructs.findIndex((it, idx) => { 3183 return ( 3184 idx > currentIndex && 3185 it.startTime! >= TraceRow.range!.startNS && 3186 it.startTime! + it.dur! <= TraceRow.range!.endNS 3187 ); 3188 }); 3189 if (findIndex >= 0) { 3190 let findEntry = cpuStructs[findIndex]; 3191 CpuStruct.selectCpuStruct = findEntry; 3192 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach((item) => { 3193 item.highlight = item.rowId == `${findEntry.cpu}`; 3194 item.draw(true); 3195 }); 3196 this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, 'inverted'); 3197 } else { 3198 findIndex = cpuStructs.findIndex((it) => it.startTime! > TraceRow.range!.endNS); 3199 let findEntry: CpuStruct; 3200 if (findIndex == -1) { 3201 findIndex = 0; 3202 } 3203 findEntry = cpuStructs[findIndex]; 3204 CpuStruct.selectCpuStruct = findEntry; 3205 let startNS = this.timerShaftEL?.getRange()?.startNS || 0; 3206 let endNS = this.timerShaftEL?.getRange()?.endNS || 0; 3207 let harfDur = Math.trunc((endNS - startNS) / 2 - findEntry.dur! / 2); 3208 this.timerShaftEL?.setRangeNS(findEntry.startTime! - harfDur, findEntry.startTime! + findEntry.dur! + harfDur); 3209 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach((item) => { 3210 item.highlight = item.rowId == `${findEntry.cpu}`; 3211 item.draw(true); 3212 }); 3213 this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, 'inverted'); 3214 } 3215 CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; 3216 this.onClickHandler(TraceRow.ROW_TYPE_CPU); 3217 return findIndex; 3218 } 3219 3220 reset(progress: Function | undefined | null) { 3221 this.visibleRows.length = 0; 3222 this.tipEL!.style.display = 'none'; 3223 this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.clientWidth, this.canvasPanel!.offsetHeight); 3224 this.canvasFavoritePanelCtx?.clearRect( 3225 0, 3226 0, 3227 this.canvasFavoritePanel!.clientWidth, 3228 this.canvasFavoritePanel!.clientHeight 3229 ); 3230 this.favoriteRowsEL!.style.height = '0'; 3231 this.canvasFavoritePanel!.style.height = '0'; 3232 this.loadTraceCompleted = false; 3233 this.collectRows = []; 3234 this.visibleRows = []; 3235 TraceRowConfig.allTraceRowList.forEach((it) => { 3236 it.clearMemory(); 3237 }); 3238 TraceRowConfig.allTraceRowList = []; 3239 if (this.favoriteRowsEL) { 3240 this.favoriteRowsEL.querySelectorAll<TraceRow<any>>(`trace-row`).forEach((row) => { 3241 row.clearMemory(); 3242 this.favoriteRowsEL!.removeChild(row); 3243 }); 3244 } 3245 if (this.rowsEL) { 3246 this.rowsEL.querySelectorAll<TraceRow<any>>(`trace-row`).forEach((row) => { 3247 row.clearMemory(); 3248 this.rowsEL!.removeChild(row); 3249 }); 3250 this.rowsEL.innerHTML = ''; 3251 } 3252 this.traceSheetEL?.clearMemory(); 3253 this.spacerEL!.style.height = '0px'; 3254 this.rangeSelect.rangeTraceRow = []; 3255 SpSystemTrace.SDK_CONFIG_MAP = undefined; 3256 SpSystemTrace.sliceRangeMark = undefined; 3257 this.timerShaftEL?.displayCollect(false); 3258 this.timerShaftEL!.collecBtn!.removeAttribute('close'); 3259 CpuStruct.wakeupBean = undefined; 3260 this.selectStructNull(); 3261 this.hoverStructNull(); 3262 this.wakeupListNull(); 3263 this.traceSheetEL?.setAttribute('mode', 'hidden'); 3264 progress && progress('rest timershaft', 8); 3265 this.timerShaftEL?.reset(); 3266 progress && progress('clear cache', 10); 3267 HeapDataInterface.getInstance().clearData(); 3268 procedurePool.clearCache(); 3269 Utils.clearData(); 3270 procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: any) => {}); 3271 procedurePool.submitWithName('logic1', 'clear', {}, undefined, (res: any) => {}); 3272 } 3273 3274 init = async (param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) => { 3275 progress('Load database', 6); 3276 this.rowsPaneEL!.scroll({ 3277 top: 0, 3278 left: 0, 3279 }); 3280 if (param.buf) { 3281 let configJson = ''; 3282 try { 3283 configJson = await fetch(wasmConfigUri).then((res) => res.text()); 3284 } catch (e) { 3285 error('getWasmConfigFailed', e); 3286 } 3287 let { status, msg, sdkConfigMap } = await threadPool.initSqlite(param.buf, configJson, progress); 3288 if (!status) { 3289 return { status: false, msg: msg }; 3290 } 3291 SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap == undefined ? undefined : sdkConfigMap; 3292 } 3293 if (param.url) { 3294 let { status, msg } = await threadPool.initServer(param.url, progress); 3295 if (!status) { 3296 return { status: false, msg: msg }; 3297 } 3298 } 3299 await this.chartManager?.init(progress); 3300 this.rowsEL?.querySelectorAll<TraceRow<any>>('trace-row').forEach((it: any) => { 3301 it.addEventListener('expansion-change', this.extracted(it)); 3302 }); 3303 progress('completed', 100); 3304 info('All TraceRow Data initialized'); 3305 this.loadTraceCompleted = true; 3306 this.rowsEL!.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => { 3307 if (it.folder) { 3308 let offsetYTimeOut: any = undefined; 3309 it.addEventListener('expansion-change', (event: any) => { 3310 JankStruct.delJankLineFlag = false; 3311 if (offsetYTimeOut) { 3312 clearTimeout(offsetYTimeOut); 3313 } 3314 if (event.detail.expansion) { 3315 offsetYTimeOut = setTimeout(() => { 3316 this.linkNodes.forEach((linkNode) => { 3317 JankStruct.selectJankStructList?.forEach((selectStruct: any) => { 3318 if (event.detail.rowId == selectStruct.pid) { 3319 JankStruct.selectJankStruct = selectStruct; 3320 JankStruct.hoverJankStruct = selectStruct; 3321 } 3322 }); 3323 if (linkNode[0].rowEL.collect) { 3324 linkNode[0].rowEL.translateY = linkNode[0].rowEL.getBoundingClientRect().top - 195; 3325 } else { 3326 linkNode[0].rowEL.translateY = linkNode[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 3327 } 3328 linkNode[0].y = linkNode[0].rowEL!.translateY! + linkNode[0].offsetY; 3329 if (linkNode[1].rowEL.collect) { 3330 linkNode[1].rowEL.translateY = linkNode[1].rowEL.getBoundingClientRect().top - 195; 3331 } else { 3332 linkNode[1].rowEL.translateY = linkNode[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 3333 } 3334 linkNode[1].y = linkNode[1].rowEL!.translateY! + linkNode[1].offsetY; 3335 }); 3336 }, 300); 3337 } else { 3338 if (JankStruct!.selectJankStruct) { 3339 JankStruct.selectJankStructList?.push(<JankStruct>JankStruct!.selectJankStruct); 3340 } 3341 offsetYTimeOut = setTimeout(() => { 3342 this.linkNodes?.forEach((linkNode) => { 3343 if (linkNode[0].rowEL.collect) { 3344 linkNode[0].rowEL.translateY = linkNode[0].rowEL.getBoundingClientRect().top - 195; 3345 } else { 3346 linkNode[0].rowEL.translateY = linkNode[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 3347 } 3348 linkNode[0].y = linkNode[0].rowEL!.translateY! + linkNode[0].offsetY; 3349 if (linkNode[1].rowEL.collect) { 3350 linkNode[1].rowEL.translateY = linkNode[1].rowEL.getBoundingClientRect().top - 195; 3351 } else { 3352 linkNode[1].rowEL.translateY = linkNode[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; 3353 } 3354 linkNode[1].y = linkNode[1].rowEL!.translateY! + linkNode[1].offsetY; 3355 }); 3356 }, 300); 3357 } 3358 let refreshTimeOut = setTimeout(() => { 3359 this.refreshCanvas(true); 3360 clearTimeout(refreshTimeOut); 3361 }, 360); 3362 }); 3363 } 3364 this.intersectionObserver?.observe(it); 3365 }); 3366 return { status: true, msg: 'success' }; 3367 }; 3368 3369 private extracted(it: any) { 3370 return () => { 3371 if (it.hasAttribute('expansion')) { 3372 this.shadowRoot?.querySelectorAll<any>(`[row-parent-id='${it.rowId}']`).forEach((child) => { 3373 if (child.folder) { 3374 child.addEventListener('expansion-change', this.extracted(child)); 3375 } 3376 this.intersectionObserver?.observe(child); 3377 }); 3378 } else { 3379 this.shadowRoot?.querySelectorAll<any>(`[row-parent-id='${it.rowId}']`).forEach((child) => { 3380 this.intersectionObserver?.unobserve(child); 3381 }); 3382 } 3383 this.refreshCanvas(false); 3384 }; 3385 } 3386 3387 displayTip(row: TraceRow<any>, struct: any, html: string) { 3388 let x = row.hoverX + 248; 3389 let y = row.getBoundingClientRect().top - 195 + (this.rowsPaneEL?.scrollTop ?? 0); 3390 if ((struct == undefined || struct == null) && this.tipEL) { 3391 this.tipEL.style.display = 'none'; 3392 return; 3393 } 3394 if (this.tipEL) { 3395 this.tipEL.innerHTML = html; 3396 this.tipEL.style.display = 'flex'; 3397 this.tipEL.style.height = row.style.height; 3398 if (x + this.tipEL.clientWidth > (this.canvasPanel!.clientWidth ?? 0)) { 3399 this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px) translateY(${y}px)`; 3400 } else { 3401 this.tipEL.style.transform = `translateX(${x}px) translateY(${y}px)`; 3402 } 3403 } 3404 } 3405 3406 queryCPUWakeUpList(data: WakeupBean) { 3407 TabPaneCurrentSelection.queryCPUWakeUpListFromBean(data).then((a: any) => { 3408 if (a === null) { 3409 return null; 3410 } 3411 SpSystemTrace.wakeupList.push(a); 3412 this.queryCPUWakeUpList(a); 3413 }); 3414 } 3415 3416 wakeupListNull() { 3417 SpSystemTrace.wakeupList = []; 3418 } 3419 3420 initPointToEvent() { 3421 this.eventMap = { 3422 'cpu-data': 'Cpu', 3423 'cpu-state': 'Cpu State', 3424 'cpu-freq': 'Cpu Frequency', 3425 'cpu-limit-freq': 'Cpu Freq Limit', 3426 process: 'Process', 3427 'native-memory': 'Native Memory', 3428 thread: 'Thread', 3429 func: 'Func', 3430 mem: 'Memory', 3431 'virtual-memory-cell': 'Virtual Memory', 3432 'virtual-memory-group': 'Virtual Memory', 3433 fps: 'FPS', 3434 'ability-monitor': 'Ability Monitor', 3435 'cpu-ability': 'Cpu Ability', 3436 'memory-ability': 'Memory Ability', 3437 'disk-ability': 'DiskIO Ability', 3438 'network-ability': 'Network Ability', 3439 sdk: 'Sdk', 3440 'sdk-counter': 'SDK Counter', 3441 'sdk-slice': 'Sdk Slice', 3442 energy: 'Energy', 3443 'power-energy': 'Power Event', 3444 'system-energy': 'System Event', 3445 'anomaly-energy': 'Anomaly Event', 3446 'clock-group': 'Clocks', 3447 clock: 'clock', 3448 'irq-group': 'Irqs', 3449 irq: 'irq', 3450 hiperf: 'HiPerf (All)', 3451 'hiperf-event': 'HiPerf Event', 3452 'hiperf-report': 'HiPerf Report', 3453 'hiperf-process': 'HiPerf Process', 3454 'hiperf-thread': 'HiPerf Thread', 3455 'js-memory': 'Js Memory', 3456 }; 3457 } 3458 3459 initHtml(): string { 3460 return ` 3461 <style> 3462 :host{ 3463 display: block; 3464 width: 100%; 3465 height: 100%; 3466 } 3467 .timer-shaft{ 3468 width: 100%; 3469 z-index: 2; 3470 } 3471 .rows-pane{ 3472 overflow: overlay; 3473 overflow-anchor: none; 3474 /*height: 100%;*/ 3475 max-height: calc(100vh - 147px - 48px); 3476 } 3477 .rows{ 3478 color: #fff; 3479 display: flex; 3480 box-sizing: border-box; 3481 flex-direction: column; 3482 overflow-y: auto; 3483 flex: 1; 3484 width: 100%; 3485 background: var(--dark-background4,#ffffff); 3486 /*scroll-behavior: smooth;*/ 3487 } 3488 .favorite-rows{ 3489 width: 100%; 3490 position:fixed; 3491 overflow-y: auto; 3492 overflow-x: hidden; 3493 z-index:1001; 3494 background: var(--dark-background5,#ffffff); 3495 box-shadow: 0 10px 10px #00000044; 3496 } 3497 .container{ 3498 width: 100%; 3499 box-sizing: border-box; 3500 height: 100%; 3501 display: grid; 3502 grid-template-columns: 1fr; 3503 grid-template-rows: min-content 1fr min-content; 3504 /*grid-template-areas: 'head'*/ 3505 /*'body'*/ 3506 /*'sheet';*/ 3507 position:relative; 3508 } 3509 .panel-canvas{ 3510 position: absolute; 3511 top: 0; 3512 right: 0px; 3513 bottom: 0px; 3514 width: 100%; 3515 /*height: calc(100vh - 195px);*/ 3516 height: 100%; 3517 box-sizing: border-box; 3518 /*background: #f0f0f0;*/ 3519 /*border: 1px solid #000000;*/ 3520 z-index: 0; 3521 } 3522 .panel-canvas-favorite{ 3523 width: 100% ; 3524 display: block; 3525 position: absolute; 3526 height: 0; 3527 top: 0; 3528 right: 0; 3529 box-sizing: border-box; 3530 z-index: 100; 3531 } 3532 .trace-sheet{ 3533 cursor: default; 3534 } 3535 .tip{ 3536 z-index: 1001; 3537 position: absolute; 3538 top: 0; 3539 left: 0; 3540 /*height: 100%;*/ 3541 background-color: white; 3542 border: 1px solid #f9f9f9; 3543 width: auto; 3544 font-size: 8px; 3545 color: #50809e; 3546 flex-direction: column; 3547 justify-content: center; 3548 align-items: flex-start; 3549 padding: 2px 10px; 3550 box-sizing: border-box; 3551 display: none; 3552 user-select: none; 3553 } 3554 3555 </style> 3556 <div class="container"> 3557 <timer-shaft-element class="timer-shaft" style="position: relative;top: 0"></timer-shaft-element> 3558 <div class="rows-pane" style="position: relative;flex-direction: column;overflow-x: hidden;"> 3559 <div class="favorite-rows"> 3560 <canvas id="canvas-panel-favorite" class="panel-canvas-favorite" ondragstart="return false"></canvas> 3561 </div> 3562 <canvas id="canvas-panel" class="panel-canvas" ondragstart="return false"></canvas> 3563 <div class="spacer" ondragstart="return false"></div> 3564 <div class="rows" ondragstart="return false"></div> 3565 <div id="tip" class="tip"></div> 3566 </div> 3567 <trace-sheet class="trace-sheet" mode="hidden" ondragstart="return false"></trace-sheet> 3568 </div> 3569 `; 3570 } 3571} 3572