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 querySearchFunc, 21 threadPool 22} from "../database/SqlLite.js"; 23import {TraceRow} from "./trace/base/TraceRow.js"; 24import {TimerShaftElement} from "./trace/TimerShaftElement.js"; 25import {CpuStruct} from "../bean/CpuStruct.js"; 26import {CpuFreqStruct} from "../bean/CpuFreqStruct.js"; 27import {ColorUtils} from "./trace/base/ColorUtils.js"; 28import "./trace/base/TraceSheet.js"; 29import {TraceSheet} from "./trace/base/TraceSheet.js"; 30import {ThreadStruct} from "../bean/ThreadStruct.js"; 31import {ProcessMemStruct} from "../bean/ProcessMemStruct.js"; 32import {FuncStruct} from "../bean/FuncStruct.js"; 33import {FpsStruct} from "../bean/FpsStruct.js"; 34import {RangeSelect} from "./trace/base/RangeSelect.js"; 35import {SelectionParam} from "../bean/BoxSelection.js"; 36import {HeapStruct} from "../bean/HeapStruct.js"; 37import {procedurePool} from "../database/Procedure.js"; 38import {Utils} from "./trace/base/Utils.js"; 39import {SpApplication} from "../SpApplication.js"; 40import {SPT} from "../bean/StateProcessThread.js"; 41import {Flag} from "./trace/timer-shaft/Flag.js"; 42import {SportRuler} from "./trace/timer-shaft/SportRuler.js"; 43import {CpuAbilityMonitorStruct} from "../bean/CpuAbilityMonitorStruct.js"; 44import {MemoryAbilityMonitorStruct} from "../bean/MemoryAbilityMonitorStruct.js"; 45import {DiskAbilityMonitorStruct} from "../bean/DiskAbilityMonitorStruct.js"; 46import {NetworkAbilityMonitorStruct} from "../bean/NetworkAbilityMonitorStruct.js"; 47import {SpHiPerf} from "./chart/SpHiPerf.js"; 48import {perfDataQuery} from "./chart/PerfDataQuery.js"; 49import {SearchThreadProcessBean} from "../bean/SearchFuncBean.js"; 50import {error, info} from "../../log/Log.js"; 51import {ns2x} from "../database/ui-worker/ProcedureWorkerCommon.js"; 52import {SpChartManager} from "./chart/SpChartManager.js"; 53import {VirtualMemoryStruct} from "../database/ui-worker/ProcedureWorkerVirtualMemory.js"; 54import {ProcessStruct} from "../bean/ProcessStruct.js"; 55import {SpFileSystemChart} from "./chart/SpFileSystemChart.js"; 56import {CounterStruct, SdkSliceStruct} from "../bean/SdkStruct.js"; 57import {SpFreqChart} from "./chart/SpFreqChart.js"; 58import {EnergyStateStruct,EnergyAnomalyStruct, EnergyPowerStruct, EnergySystemStruct} from "../bean/EnergyStruct.js"; 59import {SmapsShowStruct} from "../bean/SmapsShowStruct.js"; 60import {CpuFreqLimitsStruct} from "../database/ui-worker/ProcedureWorkerCpuFreqLimits.js"; 61 62@element('sp-system-trace') 63export class SpSystemTrace extends BaseElement { 64 static scrollViewWidth = 0 65 static isCanvasOffScreen = true; 66 static SPT_DATA: Array<SPT> = []; 67 static DATA_DICT: Map<number, string> = new Map<number, string>(); 68 static SDK_CONFIG_MAP: any; 69 rowsEL: HTMLDivElement | undefined | null; 70 spacerEL: HTMLDivElement | undefined | null; 71 visibleRows: Array<TraceRow<any>> = []; 72 keyboardEnable = true; 73 currentRowType = "";/*保存当前鼠标所在行的类型*/ 74 observerScrollHeightEnable: boolean = false; 75 observerScrollHeightCallback: Function | undefined; 76 // @ts-ignore 77 observer = new ResizeObserver((entries) => { 78 if (this.observerScrollHeightEnable && this.observerScrollHeightCallback) { 79 this.observerScrollHeightCallback(); 80 } 81 }); 82 isMousePointInSheet = false; 83 hoverFlag: Flag | undefined | null = undefined 84 selectFlag: Flag | undefined | null = undefined 85 public timerShaftEL: TimerShaftElement | null | undefined; 86 private traceSheetEL: TraceSheet | undefined | null; 87 private rangeSelect!: RangeSelect; 88 private chartManager: SpChartManager | undefined | null; 89 private loadTraceCompleted: boolean = false; 90 91 initElements(): void { 92 this.rowsEL = this.shadowRoot?.querySelector<HTMLDivElement>('.rows'); 93 this.spacerEL = this.shadowRoot?.querySelector<HTMLDivElement>('.spacer'); 94 this.timerShaftEL = this.shadowRoot?.querySelector('.timer-shaft'); 95 this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet'); 96 this.rangeSelect = new RangeSelect(this.timerShaftEL); 97 this.rangeSelect.rowsEL = this.rowsEL; 98 document?.addEventListener("triangle-flag", (event: any) => { 99 let temporaryTime = this.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); 100 if (event.detail.timeCallback && temporaryTime) event.detail.timeCallback(temporaryTime); 101 }) 102 103 document?.addEventListener("flag-change", (event: any) => { 104 this.timerShaftEL?.modifyFlagList(event.detail) 105 if (event.detail.hidden) { 106 this.selectFlag = undefined; 107 this.traceSheetEL?.setAttribute("mode", 'hidden'); 108 this.visibleRows.forEach(it => it.draw(true)); 109 } 110 }) 111 112 SpSystemTrace.scrollViewWidth = this.getScrollWidth(); 113 this.rangeSelect.selectHandler = (rows, refreshCheckBox) => { 114 if (rows.length == 0) { 115 this.rowsEL!.querySelectorAll<TraceRow<any>>("trace-row").forEach(it => { 116 it.checkType = "-1" 117 }) 118 this.getVisibleRows().forEach(it => { 119 it.draw(true); 120 }); 121 this.traceSheetEL?.setAttribute("mode", 'hidden'); 122 return; 123 } 124 if (refreshCheckBox) { 125 if (rows.length > 0) { 126 this.rowsEL?.querySelectorAll<TraceRow<any>>("trace-row").forEach(row => row.checkType = "0") 127 rows.forEach(it => it.checkType = "2") 128 } else { 129 this.rowsEL?.querySelectorAll<TraceRow<any>>("trace-row").forEach(row => row.checkType = "-1") 130 return 131 } 132 } 133 let selection = new SelectionParam(); 134 selection.leftNs = 0; 135 selection.rightNs = 0; 136 selection.recordStartNs = (window as any).recordStartNS 137 let native_memory = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]; 138 rows.forEach(it => { 139 if (it.rowType == TraceRow.ROW_TYPE_CPU) { 140 selection.cpus.push(parseInt(it.rowId!)) 141 info("load CPU traceRow id is : ", it.rowId) 142 } else if (it.rowType == TraceRow.ROW_TYPE_CPU_STATE) { 143 let filterId = parseInt(it.rowId!); 144 if (selection.cpuStateFilterIds.indexOf(filterId) == -1) { 145 selection.cpuStateFilterIds.push(filterId); 146 } 147 } else if(it.rowType == TraceRow.ROW_TYPE_CPU_FREQ){ 148 let filterId = parseInt(it.rowId!); 149 if(selection.cpuFreqFilterIds.indexOf(filterId) == -1){ 150 selection.cpuFreqFilterIds.push(filterId); 151 } 152 } else if(it.rowType == TraceRow.ROW_TYPE_CPU_FREQ_LIMIT){ 153 selection.cpuFreqLimitDatas.push(it.dataList!) 154 } else if (it.rowType == TraceRow.ROW_TYPE_PROCESS) { 155 this.rowsEL?.querySelectorAll<TraceRow<any>>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { 156 th.rangeSelect = true; 157 th.checkType = "2" 158 if (th.rowType == TraceRow.ROW_TYPE_THREAD) { 159 selection.threadIds.push(parseInt(th.rowId!)) 160 } else if (th.rowType == TraceRow.ROW_TYPE_FUNC) { 161 if (th.asyncFuncName) { 162 selection.funAsync.push({ 163 name: th.asyncFuncName, 164 pid: th.asyncFuncNamePID || 0, 165 }) 166 } else { 167 selection.funTids.push(parseInt(th.rowId!)) 168 } 169 } else if (th.rowType == TraceRow.ROW_TYPE_MEM) { 170 selection.processTrackIds.push(parseInt(th.rowId!)) 171 } 172 }) 173 info("load process traceRow id is : ", it.rowId) 174 } else if (it.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY) { 175 this.rowsEL?.querySelectorAll<TraceRow<any>>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { 176 th.rangeSelect = true; 177 th.checkType = "2" 178 selection.nativeMemory.push(th.rowId!); 179 }) 180 info("load nativeMemory traceRow id is : ", it.rowId) 181 } else if (it.rowType == TraceRow.ROW_TYPE_THREAD) { 182 selection.threadIds.push(parseInt(it.rowId!)) 183 info("load thread traceRow id is : ", it.rowId) 184 } else if (it.rowType == TraceRow.ROW_TYPE_FUNC) { 185 if (it.asyncFuncName) { 186 selection.funAsync.push({ 187 name: it.asyncFuncName, 188 pid: it.asyncFuncNamePID || 0, 189 }) 190 } else { 191 selection.funTids.push(parseInt(it.rowId!)) 192 } 193 info("load func traceRow id is : ", it.rowId) 194 } else if (it.rowType == TraceRow.ROW_TYPE_MEM || it.rowType == TraceRow.ROW_TYPE_VIRTUAL_MEMORY) { 195 if (it.rowType == TraceRow.ROW_TYPE_MEM) { 196 selection.processTrackIds.push(parseInt(it.rowId!)) 197 } else { 198 selection.virtualTrackIds.push(parseInt(it.rowId!)) 199 } 200 info("load memory traceRow id is : ", it.rowId) 201 } else if (it.rowType == TraceRow.ROW_TYPE_FPS) { 202 selection.hasFps = true; 203 info("load FPS traceRow id is : ", it.rowId) 204 } else if (it.rowType == TraceRow.ROW_TYPE_HEAP) { 205 if (native_memory.indexOf(it.rowId ?? "") != -1) { 206 selection.nativeMemory.push(it.rowId!); 207 info("load nativeMemory traceRow id is : ", it.rowId) 208 } else { 209 selection.heapIds.push(parseInt(it.rowId!)) 210 info("load heap traceRow id is : ", it.rowId) 211 } 212 } else if (it.rowType == TraceRow.ROW_TYPE_CPU_ABILITY) { 213 selection.cpuAbilityIds.push(it.rowId!) 214 info("load CPU Ability traceRow id is : ", it.rowId) 215 } else if (it.rowType == TraceRow.ROW_TYPE_MEMORY_ABILITY) { 216 selection.memoryAbilityIds.push(it.rowId!) 217 info("load Memory Ability traceRow id is : ", it.rowId) 218 } else if (it.rowType == TraceRow.ROW_TYPE_DISK_ABILITY) { 219 selection.diskAbilityIds.push(it.rowId!) 220 info("load DiskIo Ability traceRow id is : ", it.rowId) 221 } else if (it.rowType == TraceRow.ROW_TYPE_NETWORK_ABILITY) { 222 selection.networkAbilityIds.push(it.rowId!) 223 info("load Network Ability traceRow id is : ", it.rowId) 224 } else if (it.rowType == TraceRow.ROW_TYPE_SDK_COUNTER) { 225 selection.sdkCounterIds.push(it.rowId!) 226 } else if (it.rowType == TraceRow.ROW_TYPE_SDK_SLICE) { 227 selection.sdkSliceIds.push(it.rowId!) 228 } else if (it.rowType?.startsWith("hiperf")) { 229 if (it.rowType == TraceRow.ROW_TYPE_HIPERF_EVENT || it.rowType == TraceRow.ROW_TYPE_HIPERF_REPORT) { 230 return; 231 } 232 selection.perfSampleIds.push(1) 233 if (it.rowType == TraceRow.ROW_TYPE_HIPERF_PROCESS) { 234 this.rowsEL?.querySelectorAll<TraceRow<any>>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { 235 th.rangeSelect = true; 236 th.checkType = "2" 237 }) 238 } 239 if (it.rowType == TraceRow.ROW_TYPE_HIPERF || it.rowId == "HiPerf-cpu-merge") { 240 selection.perfAll = true; 241 } 242 if (it.rowType == TraceRow.ROW_TYPE_HIPERF_CPU) { 243 selection.perfCpus.push(it.index); 244 } 245 if (it.rowType == TraceRow.ROW_TYPE_HIPERF_PROCESS) { 246 selection.perfProcess.push(parseInt(it.rowId!.split("-")[0])); 247 } 248 if (it.rowType == TraceRow.ROW_TYPE_HIPERF_THREAD) { 249 selection.perfThread.push(parseInt(it.rowId!.split("-")[0])); 250 } 251 } else if (it.rowType == TraceRow.ROW_TYPE_FILE_SYSTEM) { 252 if (it.rowId == "FileSystemLogicalWrite" || it.rowId == "FileSystemLogicalRead") { 253 selection.fileSystemType = [0, 1, 2, 3]; 254 } else if (it.rowId == "FileSystemVirtualMemory") { 255 selection.fileSysVirtualMemory = true; 256 } else if (it.rowId == "FileSystemDiskIOLatency") { 257 selection.diskIOLatency = true; 258 } else { 259 let arr = it.rowId!.split("-").reverse(); 260 let ipid = parseInt(arr[0]); 261 if (selection.diskIOipids.indexOf(ipid) == -1) { 262 selection.diskIOipids.push(ipid); 263 } 264 } 265 } else if (it.rowType == TraceRow.ROW_TYPE_POWER_ENERGY) { 266 selection.powerEnergy.push(it.rowId!) 267 } else if (it.rowType == TraceRow.ROW_TYPE_SYSTEM_ENERGY) { 268 selection.systemEnergy.push(it.rowId!) 269 } else if (it.rowType == TraceRow.ROW_TYPE_ANOMALY_ENERGY) { 270 selection.anomalyEnergy.push(it.rowId!) 271 } else if (it.rowType == TraceRow.ROW_TYPE_SYSTEM_ENERGY) { 272 info("load anomaly Energy traceRow id is : ", it.rowId) 273 } else if (it.rowType == TraceRow.ROW_TYPE_SMAPS) { 274 selection.smapsType.push(it.rowId!) 275 } 276 }) 277 selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0; 278 selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0; 279 this.selectStructNull(); 280 this.timerShaftEL?.removeTriangle("inverted") 281 this.traceSheetEL?.rangeSelect(selection); 282 } 283 // @ts-ignore 284 new ResizeObserver((entries) => { 285 let width = entries[0].contentRect.width - 1 - SpSystemTrace.scrollViewWidth; 286 requestAnimationFrame(() => { 287 this.timerShaftEL?.updateWidth(width) 288 this.shadowRoot!.querySelectorAll<TraceRow<any>>("trace-row").forEach(it => it.updateWidth(width)) 289 }) 290 }).observe(this); 291 292 new ResizeObserver((entries) => { 293 this.getVisibleRows().forEach(it => { 294 it.draw(true); 295 }); 296 if (this.traceSheetEL!.getAttribute("mode") == "hidden") { 297 this.timerShaftEL?.removeTriangle("triangle") 298 } 299 }).observe(this.rowsEL!); 300 window.addEventListener("keydown", ev => { 301 if (ev.key.toLocaleLowerCase() === "escape") { 302 this.selectStructNull(); 303 this.timerShaftEL?.setSlicesMark(); 304 this.traceSheetEL?.setAttribute("mode", 'hidden'); 305 TraceRow.rangeSelectObject = undefined; 306 } 307 }); 308 this.chartManager = new SpChartManager(this); 309 } 310 311 getScrollWidth() { 312 let totalScrollDiv, scrollDiv, overflowDiv = document.createElement('div'); 313 overflowDiv.style.cssText = 'position:absolute; top:-2000px;width:200px; height:200px; overflow:hidden;'; 314 totalScrollDiv = document.body.appendChild(overflowDiv).clientWidth; 315 overflowDiv.style.overflowY = 'scroll'; 316 scrollDiv = overflowDiv.clientWidth; 317 document.body.removeChild(overflowDiv); 318 return totalScrollDiv - scrollDiv; 319 } 320 321 getVisibleRows(): Array<TraceRow<any>> { 322 let scrollTop = this.rowsEL?.scrollTop || 0; 323 let scrollHeight = this.rowsEL?.clientHeight || 0; 324 let res = [...this.rowsEL!.querySelectorAll<TraceRow<any>>("trace-row")].filter((it) => { 325 let tr = (it as TraceRow<any>); 326 let top = it.offsetTop - (this.rowsEL?.offsetTop || 0); 327 if ((top + it.clientHeight > scrollTop && top + it.clientHeight < scrollTop + scrollHeight + it.clientHeight) || it.collect) { 328 it.sleeping = false; 329 return true 330 } else { 331 if (!it.hasAttribute("collect-type")) { 332 it.sleeping = true; 333 } 334 return false; 335 } 336 }) 337 this.visibleRows = res; 338 info("Visible TraceRow size is :", this.visibleRows!.length) 339 return res; 340 } 341 342 timerShaftELFlagClickHandler = (flag: Flag | undefined | null) => { 343 if (flag) { 344 setTimeout(() => { 345 this.traceSheetEL?.displayFlagData(flag); 346 }, 100) 347 } 348 } 349 350 timerShaftELFlagChange = (hoverFlag: Flag | undefined | null, selectFlag: Flag | undefined | null) => { 351 this.hoverFlag = hoverFlag; 352 this.selectFlag = selectFlag; 353 this.visibleRows.forEach(it => it.draw(true)); 354 } 355 356 timerShaftELRangeChange = (e: any) => { 357 TraceRow.range = e; 358 if (TraceRow.rangeSelectObject) { 359 TraceRow.rangeSelectObject!.startX = Math.floor(ns2x(TraceRow.rangeSelectObject!.startNS!, TraceRow.range?.startNS!, TraceRow.range?.endNS!, TraceRow.range?.totalNS!, this.timerShaftEL!.sportRuler!.frame)); 360 TraceRow.rangeSelectObject!.endX = Math.floor(ns2x(TraceRow.rangeSelectObject!.endNS!, TraceRow.range?.startNS!, TraceRow.range?.endNS!, TraceRow.range?.totalNS!, this.timerShaftEL!.sportRuler!.frame)); 361 } 362 //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知 363 for (let i = 0; i < this.visibleRows.length; i++) { 364 this.visibleRows[i].draw(); 365 } 366 } 367 368 rowsElOnScroll = (e: any) => { 369 this.hoverStructNull(); 370 if (TraceRow.range) { 371 TraceRow.range.refresh = true; 372 } 373 this.visibleRows = this.getVisibleRows(); 374 for (let index = 0; index < this.visibleRows.length; index++) { 375 if (index == 0 || index == this.visibleRows.length - 1) { 376 this.visibleRows[index].isHover = false; 377 } 378 } 379 } 380 381 documentOnMouseDown = (ev: MouseEvent) => { 382 if (!this.loadTraceCompleted) return; 383 TraceRow.isUserInteraction = true; 384 if (this.isMouseInSheet(ev)) return; 385 this.observerScrollHeightEnable = false; 386 if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft) { 387 let x = ev.offsetX - this.timerShaftEL!.canvas!.offsetLeft; 388 let y = ev.offsetY; 389 this.timerShaftEL?.documentOnMouseDown(ev); 390 if (this.timerShaftEL!.sportRuler!.frame.contains(x, y) && x > (TraceRow.rangeSelectObject?.startX || 0) && x < (TraceRow.rangeSelectObject?.endX || 0)) { 391 let time = Math.round((x * (TraceRow.range?.endNS! - TraceRow.range?.startNS!) / this.timerShaftEL!.canvas!.offsetWidth) + TraceRow.range?.startNS!); 392 this.timerShaftEL!.sportRuler!.drawTriangle(time, "triangle") 393 } else { 394 this.rangeSelect.mouseDown(ev) 395 } 396 this.visibleRows.forEach(it => it.draw()); 397 } 398 } 399 400 documentOnMouseUp = (ev: MouseEvent) => { 401 if (!this.loadTraceCompleted) return; 402 TraceRow.isUserInteraction = false; 403 this.rangeSelect.isMouseDown = false; 404 if (this.isMouseInSheet(ev)) return; 405 let x = ev.offsetX - this.timerShaftEL!.canvas!.offsetLeft; 406 let y = ev.offsetY; 407 if (this.timerShaftEL!.sportRuler!.frame.contains(x, y) && x > (TraceRow.rangeSelectObject?.startX || 0) && x < (TraceRow.rangeSelectObject?.endX || 0)) { 408 } else { 409 this.rangeSelect.mouseUp(ev); 410 this.timerShaftEL?.documentOnMouseUp(ev) 411 } 412 } 413 414 documentOnMouseOut = (ev: MouseEvent) => { 415 if (!this.loadTraceCompleted) return; 416 if (this.isMouseInSheet(ev)) return; 417 if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft) { 418 this.timerShaftEL?.documentOnMouseOut(ev) 419 } 420 } 421 422 documentOnKeyPress = (ev: KeyboardEvent) => { 423 if (!this.loadTraceCompleted) return; 424 TraceRow.isUserInteraction = true; 425 if (ev.key.toLocaleLowerCase() == "m") { 426 if (CpuStruct.selectCpuStruct) { 427 this.timerShaftEL?.setSlicesMark((CpuStruct.selectCpuStruct.startTime || 0), (CpuStruct.selectCpuStruct.startTime || 0) + (CpuStruct.selectCpuStruct.dur || 0)); 428 } else if (ThreadStruct.selectThreadStruct) { 429 this.timerShaftEL?.setSlicesMark((ThreadStruct.selectThreadStruct.startTime || 0), (ThreadStruct.selectThreadStruct.startTime || 0) + (ThreadStruct.selectThreadStruct.dur || 0)); 430 } else if (FuncStruct.selectFuncStruct) { 431 this.timerShaftEL?.setSlicesMark((FuncStruct.selectFuncStruct.startTs || 0), (FuncStruct.selectFuncStruct.startTs || 0) + (FuncStruct.selectFuncStruct.dur || 0)); 432 } else if (TraceRow.rangeSelectObject) { 433 this.timerShaftEL?.setSlicesMark((TraceRow.rangeSelectObject.startNS || 0), (TraceRow.rangeSelectObject.endNS || 0)); 434 } else { 435 this.timerShaftEL?.setSlicesMark(); 436 } 437 } 438 if (this.isMousePointInSheet) { 439 return; 440 } 441 this.observerScrollHeightEnable = false; 442 this.keyboardEnable && this.timerShaftEL!.documentOnKeyPress(ev); 443 } 444 445 documentOnKeyUp = (ev: KeyboardEvent) => { 446 if (!this.loadTraceCompleted) return; 447 TraceRow.isUserInteraction = false; 448 this.observerScrollHeightEnable = false; 449 this.keyboardEnable && this.timerShaftEL!.documentOnKeyUp(ev); 450 if (ev.code == "Enter") { 451 if (ev.shiftKey) { 452 this.dispatchEvent(new CustomEvent("previous-data", { 453 detail: {}, 454 composed: false 455 })); 456 } else { 457 this.dispatchEvent(new CustomEvent("next-data", { 458 detail: {}, 459 composed: false 460 })); 461 } 462 } 463 } 464 465 isMouseInSheet = (ev: MouseEvent) => { 466 this.isMousePointInSheet = this.traceSheetEL?.getAttribute("mode") != "hidden" && ev.offsetX > this.traceSheetEL!.offsetLeft && ev.offsetY > this.traceSheetEL!.offsetTop; 467 return this.isMousePointInSheet; 468 } 469 470 favoriteChangeHandler = (row: TraceRow<any>) => { 471 info("favoriteChangeHandler", row.frame, row.offsetTop, row.offsetHeight); 472 this.getVisibleRows(); 473 } 474 475 selectChangeHandler = (rows: Array<TraceRow<any>>) => { 476 this.rangeSelect.rangeTraceRow = rows; 477 this.rangeSelect.selectHandler?.(this.rangeSelect.rangeTraceRow, false); 478 } 479 480 documentOnMouseMove = (ev: MouseEvent) => { 481 if ((window as any).isSheetMove) return; 482 if (!this.loadTraceCompleted || (window as any).flagInputFocus) return; 483 if (this.isMouseInSheet(ev)) { 484 this.hoverStructNull(); 485 return; 486 } 487 let rows = this.visibleRows; 488 if (this.timerShaftEL?.isScaling()) { 489 return; 490 } 491 this.timerShaftEL?.documentOnMouseMove(ev) 492 this.rangeSelect.mouseMove(rows, ev); 493 if (this.rangeSelect.isMouseDown) { 494 for (let i = 0; i < rows.length; i++) { 495 rows[i].tipEL!.style.display = "none"; 496 rows[i].draw(true); 497 } 498 } else { 499 for (let i = 0; i < rows.length; i++) { 500 let tr = rows[i]; 501 let rowsELScrollTop = this.rowsEL?.scrollTop || 0; 502 let x = ev.offsetX - (tr.canvasContainer?.offsetLeft || 0); 503 let y = ev.offsetY - (tr.canvasContainer?.offsetTop || 0) + rowsELScrollTop; 504 if ((!tr.collect && x > tr.frame.x && x < tr.frame.x + tr.frame.width && ev.offsetY + rowsELScrollTop > tr.offsetTop && ev.offsetY + rowsELScrollTop < tr.offsetTop + tr.frame.height) || 505 (tr.collect && x > tr.frame.x && x < tr.frame.x + tr.frame.width && ev.offsetY > tr.offsetTop - 48 && ev.offsetY < tr.offsetTop - 48 + tr.frame.height)) { 506 tr.isHover = true; 507 tr.hoverX = x; 508 tr.hoverY = tr.collect ? (ev.offsetY + 48 - tr.offsetTop) : y; 509 if (tr.rowType === TraceRow.ROW_TYPE_CPU) { 510 this.currentRowType = TraceRow.ROW_TYPE_CPU; 511 CpuFreqStruct.hoverCpuFreqStruct = undefined; 512 SpFreqChart.hoverStateStruct = undefined; 513 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined 514 if (CpuStruct.hoverCpuStruct) { 515 tr.tip = `<span>P:${CpuStruct.hoverCpuStruct.processName || "Process"} [${CpuStruct.hoverCpuStruct.processId}]</span><span>T:${CpuStruct.hoverCpuStruct.name} [${CpuStruct.hoverCpuStruct.tid}] [Prio:${CpuStruct.hoverCpuStruct.priority||0}]</span>`; 516 } 517 tr.setTipLeft(x, CpuStruct.hoverCpuStruct) 518 } else if (tr.rowType === TraceRow.ROW_TYPE_CPU_STATE) { 519 this.currentRowType = TraceRow.ROW_TYPE_CPU_STATE; 520 CpuFreqStruct.hoverCpuFreqStruct = undefined; 521 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined 522 523 if (SpFreqChart.hoverStateStruct) { 524 tr.tip = `<span>State: ${SpFreqChart.hoverStateStruct.value}</span>` 525 } 526 tr.setTipLeft(x, SpFreqChart.hoverStateStruct) 527 } else if (tr.rowType === TraceRow.ROW_TYPE_CPU_FREQ_LIMIT){ 528 CpuFreqStruct.hoverCpuFreqStruct = undefined; 529 SpFreqChart.hoverStateStruct = undefined; 530 if (CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct) { 531 tr.tip = `<span>Max Freq: ${ColorUtils.formatNumberComma(CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct.max!)} kHz</span><span>Min Freq: ${ColorUtils.formatNumberComma(CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct.min!)} kHz</span>` 532 } 533 tr.setTipLeft(x, CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct) 534 }else if (tr.rowType === TraceRow.ROW_TYPE_CPU_FREQ) { 535 this.currentRowType = TraceRow.ROW_TYPE_CPU_FREQ; 536 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined 537 SpFreqChart.hoverStateStruct = undefined; 538 if (CpuFreqStruct.hoverCpuFreqStruct) { 539 CpuStruct.hoverCpuStruct = undefined; 540 tr.tip = `<span>${ColorUtils.formatNumberComma(CpuFreqStruct.hoverCpuFreqStruct.value!)} kHz</span>` 541 } 542 tr.setTipLeft(x, CpuFreqStruct.hoverCpuFreqStruct) 543 } else if (tr.rowType === TraceRow.ROW_TYPE_FPS) { 544 this.currentRowType = TraceRow.ROW_TYPE_FPS; 545 if (FpsStruct.hoverFpsStruct) { 546 tr.tip = `<span>${FpsStruct.hoverFpsStruct.fps}</span>` 547 } 548 tr.setTipLeft(x, FpsStruct.hoverFpsStruct) 549 } else if (tr.rowType === TraceRow.ROW_TYPE_THREAD) { 550 FuncStruct.hoverFuncStruct = undefined; 551 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined 552 this.currentRowType = TraceRow.ROW_TYPE_THREAD; 553 } else if (tr.rowType === TraceRow.ROW_TYPE_FUNC) { 554 ThreadStruct.hoverThreadStruct = undefined; 555 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined 556 this.currentRowType = TraceRow.ROW_TYPE_FUNC; 557 } else if (tr.rowType === TraceRow.ROW_TYPE_HEAP) { 558 this.currentRowType = TraceRow.ROW_TYPE_HEAP; 559 if (HeapStruct.hoverHeapStruct) { 560 if (tr.drawType === 1) { 561 tr.tip = `<span>${HeapStruct.hoverHeapStruct.heapsize}</span>` 562 } else { 563 tr.tip = `<span>${Utils.getByteWithUnit(HeapStruct.hoverHeapStruct.heapsize!)}</span>` 564 } 565 } 566 tr.setTipLeft(x, HeapStruct.hoverHeapStruct) 567 } else if (tr.rowType === TraceRow.ROW_TYPE_CPU_ABILITY) { 568 this.currentRowType = TraceRow.ROW_TYPE_CPU_ABILITY; 569 if (!SpSystemTrace.isCanvasOffScreen) CpuAbilityMonitorStruct.hoverCpuAbilityStruct = tr.onMouseHover(x, y); 570 if (CpuAbilityMonitorStruct.hoverCpuAbilityStruct) { 571 let monitorCpuTip = (CpuAbilityMonitorStruct.hoverCpuAbilityStruct.value!).toFixed(2) + "%" 572 tr.tip = `<span>${monitorCpuTip}</span>` 573 } 574 tr.setTipLeft(x, CpuAbilityMonitorStruct.hoverCpuAbilityStruct) 575 } else if (tr.rowType === TraceRow.ROW_TYPE_MEMORY_ABILITY) { 576 this.currentRowType = TraceRow.ROW_TYPE_MEMORY_ABILITY; 577 if (!SpSystemTrace.isCanvasOffScreen) MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = tr.onMouseHover(x, y); 578 if (MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct) { 579 tr.tip = `<span>${Utils.getBinaryByteWithUnit(MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct.value!)}</span>` 580 } 581 tr.setTipLeft(x, MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct) 582 } else if (tr.rowType === TraceRow.ROW_TYPE_DISK_ABILITY) { 583 this.currentRowType = TraceRow.ROW_TYPE_DISK_ABILITY; 584 if (!SpSystemTrace.isCanvasOffScreen) DiskAbilityMonitorStruct.hoverDiskAbilityStruct = tr.onMouseHover(x, y); 585 if (DiskAbilityMonitorStruct.hoverDiskAbilityStruct) { 586 tr.tip = `<span>${DiskAbilityMonitorStruct.hoverDiskAbilityStruct.value!} KB/S</span>` 587 } 588 tr.setTipLeft(x, DiskAbilityMonitorStruct.hoverDiskAbilityStruct) 589 } else if (tr.rowType === TraceRow.ROW_TYPE_NETWORK_ABILITY) { 590 this.currentRowType = TraceRow.ROW_TYPE_NETWORK_ABILITY; 591 if (!SpSystemTrace.isCanvasOffScreen) NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = tr.onMouseHover(x, y); 592 if (NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct) { 593 tr.tip = `<span>${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct.value!)}</span>` 594 } 595 tr.setTipLeft(x, NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct) 596 } else if (tr.rowType === TraceRow.ROW_TYPE_HIPERF_CPU) { 597 this.currentRowType = TraceRow.ROW_TYPE_HIPERF_CPU; 598 if (SpHiPerf.hoverCpuStruct) { 599 let num = Math.trunc((SpHiPerf.hoverCpuStruct.height || 0) / 40 * 100); 600 if (num > 0) { 601 if (tr.rowId == "HiPerf-cpu-merge") { 602 tr.tip = `<span>${num * (this.chartManager!.perf!.maxCpuId + 1)}% (10.00ms)</span>` 603 } else { 604 tr.tip = `<span>${num}% (10.00ms)</span>` 605 } 606 } else { 607 let perfCall = perfDataQuery.callChainMap.get(SpHiPerf.hoverCpuStruct.callchain_id || 0); 608 tr.tip = `<span>${perfCall ? perfCall.name : ''} (${perfCall ? perfCall.depth : '0'} other frames)</span>` 609 } 610 } 611 tr.setTipLeft(x, SpHiPerf.hoverCpuStruct) 612 } else if (tr.rowType === TraceRow.ROW_TYPE_HIPERF_EVENT) { 613 this.currentRowType = TraceRow.ROW_TYPE_HIPERF_EVENT; 614 if (SpHiPerf.hoverEventuctStruct) { 615 let num = Math.trunc((SpHiPerf.hoverEventuctStruct.sum || 0) / (SpHiPerf.hoverEventuctStruct.max || 0) * 100); 616 if (num > 0) { 617 tr.tip = `<span>${num}% (10.00ms)</span>` 618 } else { 619 let perfCall = perfDataQuery.callChainMap.get(SpHiPerf.hoverEventuctStruct.callchain_id || 0); 620 tr.tip = `<span>${perfCall ? perfCall.name : ''} (${perfCall ? perfCall.depth : '0'} other frames)</span>` 621 } 622 } 623 tr.setTipLeft(x, SpHiPerf.hoverEventuctStruct) 624 } else if (tr.rowType === TraceRow.ROW_TYPE_HIPERF_PROCESS) { 625 this.currentRowType = TraceRow.ROW_TYPE_HIPERF_PROCESS; 626 if (SpHiPerf.hoverProcessStruct) { 627 let num = Math.trunc((SpHiPerf.hoverProcessStruct.height || 0) / 40 * 100); 628 if (num > 0) { 629 tr.tip = `<span>${num}% (10.00ms)</span>` 630 } else { 631 let perfCall = perfDataQuery.callChainMap.get(SpHiPerf.hoverProcessStruct.callchain_id || 0); 632 tr.tip = `<span>${perfCall ? perfCall.name : ''} (${perfCall ? perfCall.depth : '0'} other frames)</span>` 633 } 634 } 635 tr.setTipLeft(x, SpHiPerf.hoverProcessStruct) 636 } else if (tr.rowType === TraceRow.ROW_TYPE_HIPERF_THREAD) { 637 this.currentRowType = TraceRow.ROW_TYPE_HIPERF_THREAD; 638 if (SpHiPerf.hoverThreadStruct) { 639 let num = Math.trunc((SpHiPerf.hoverThreadStruct.height || 0) / 40 * 100); 640 if (num > 0) { 641 tr.tip = `<span>${num}% (10.00ms)</span>` 642 } else { 643 let perfCall = perfDataQuery.callChainMap.get(SpHiPerf.hoverThreadStruct.callchain_id || -1); 644 tr.tip = `<span>${perfCall ? perfCall.name : ''} (${perfCall ? perfCall.depth : '0'} other frames)</span>` 645 } 646 } 647 tr.setTipLeft(x, SpHiPerf.hoverThreadStruct) 648 } else if (tr.rowType === TraceRow.ROW_TYPE_FILE_SYSTEM) { 649 this.currentRowType = TraceRow.ROW_TYPE_FILE_SYSTEM; 650 let num = 0; 651 if (SpFileSystemChart.hoverFileSysStruct) { 652 num = SpFileSystemChart.hoverFileSysStruct.size ?? 0; 653 let group10Ms = SpFileSystemChart.hoverFileSysStruct.group10Ms ?? false; 654 if (tr.rowId!.startsWith("FileSystemDiskIOLatency")) { 655 if (num > 0) { 656 let tipStr = Utils.getProbablyTime(num); 657 tr.tip = `<span>${tipStr} (10.00ms)</span>` 658 } 659 } else { 660 if (num > 0) { 661 if (group10Ms) { 662 tr.tip = `<span>${num} (10.00ms)</span>` 663 } else { 664 tr.tip = `<span>${num}</span>` 665 } 666 } 667 } 668 } 669 tr.setTipLeft(x, num > 0 ? SpFileSystemChart.hoverFileSysStruct : null) 670 } else if (tr.rowType == TraceRow.ROW_TYPE_MEM) { 671 if (ProcessMemStruct.hoverProcessMemStruct) { 672 CpuStruct.hoverCpuStruct = undefined; 673 tr.tip = `<span>${ProcessMemStruct.hoverProcessMemStruct.value}</span>` 674 } 675 tr.setTipLeft(x, ProcessMemStruct.hoverProcessMemStruct) 676 } else if (tr.rowType === TraceRow.ROW_TYPE_SDK_COUNTER) { 677 this.currentRowType = TraceRow.ROW_TYPE_SDK_COUNTER; 678 if (!SpSystemTrace.isCanvasOffScreen) CounterStruct.hoverCounterStruct = tr.onMouseHover(x, y); 679 if (CounterStruct.hoverCounterStruct) { 680 let gpuTip = (CounterStruct.hoverCounterStruct.value!).toFixed(2) 681 tr.tip = `<span>${gpuTip}</span>` 682 } 683 tr.setTipLeft(x, CounterStruct.hoverCounterStruct) 684 } else if (tr.rowType === TraceRow.ROW_TYPE_SDK_SLICE) { 685 this.currentRowType = TraceRow.ROW_TYPE_SDK_SLICE; 686 if (!SpSystemTrace.isCanvasOffScreen) SdkSliceStruct.hoverSdkSliceStruct = tr.onMouseHover(x, y); 687 if (SdkSliceStruct.hoverSdkSliceStruct) { 688 tr.tip = `<span>${SdkSliceStruct.hoverSdkSliceStruct?.value}</span>`; 689 } 690 tr.setTipLeft(x, SdkSliceStruct.hoverSdkSliceStruct) 691 } else if (tr.rowType == TraceRow.ROW_TYPE_VIRTUAL_MEMORY) { 692 if (VirtualMemoryStruct.hoverStruct) { 693 CpuStruct.hoverCpuStruct = undefined; 694 tr.tip = `<span>value:${VirtualMemoryStruct.hoverStruct.value}</span>` 695 } 696 tr.setTipLeft(x, VirtualMemoryStruct.hoverStruct) 697 } else if (tr.rowType == TraceRow.ROW_TYPE_POWER_ENERGY) { 698 this.currentRowType = TraceRow.ROW_TYPE_POWER_ENERGY; 699 if (!SpSystemTrace.isCanvasOffScreen) EnergyPowerStruct.hoverEnergyPowerStruct = tr.onMouseHover(x, y); 700 if (EnergyPowerStruct.hoverEnergyPowerStruct) { 701 tr.tip = `<div style="width: 120px"> 702 <div style="display: flex"><div style="width: 80%;text-align: left">CPU: </div><div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct.cpu!}</div></div> 703 <div style="display: flex"><div style="width: 80%;text-align: left">location: </div><div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct.location!}</div></div> 704 <div style="display: flex"><div style="width: 80%;text-align: left">GPU: </div><div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct.gpu!}</div></div> 705 <div style="display: flex"><div style="width: 80%;text-align: left">display: </div><div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct.display!}</div></div> 706 <div style="display: flex"><div style="width: 80%;text-align: left">camera: </div><div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct.camera!}</div></div> 707 <div style="display: flex"><div style="width: 80%;text-align: left">bluetooth: </div><div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct.bluetooth!}</div></div> 708 <div style="display: flex"><div style="width: 80%;text-align: left">flashlight: </div><div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct.flashlight!}</div></div> 709 <div style="display: flex"><div style="width: 80%;text-align: left">audio: </div><div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct.audio!}</div></div> 710 <div style="display: flex"><div style="width: 80%;text-align: left">wifiScan: </div><div style="width: 20%;text-align: left">${EnergyPowerStruct.hoverEnergyPowerStruct.wifiscan!}</div></div> 711 </div>` 712 } 713 tr.setTipLeft(x, EnergyPowerStruct.hoverEnergyPowerStruct) 714 } else if (tr.rowType == TraceRow.ROW_TYPE_SYSTEM_ENERGY) { 715 this.currentRowType = TraceRow.ROW_TYPE_SYSTEM_ENERGY; 716 if (!SpSystemTrace.isCanvasOffScreen) EnergySystemStruct.hoverEnergySystemStruct = tr.onMouseHover(x, y); 717 if (EnergySystemStruct.hoverEnergySystemStruct) { 718 tr.tip = `<div style="width: 250px"> 719 <div style="display: flex"><div style="width: 75%;text-align: left">WORKSCHEDULER: </div><div style="width: 20%;text-align: left">${EnergySystemStruct.hoverEnergySystemStruct.workScheduler!}</div></div> 720 <div style="display: flex"><div style="width: 75%;text-align: left">POWER_RUNNINGLOCK: </div><div style="width: 20%;text-align: left">${EnergySystemStruct.hoverEnergySystemStruct.power!}</div></div> 721 <div style="display: flex"><div style="width: 75%;text-align: left">LOCATION: </div><div style="width: 20%;text-align: left">${EnergySystemStruct.hoverEnergySystemStruct.location!}</div></div> 722 </div>` 723 } 724 tr.setTipLeft(x, EnergySystemStruct.hoverEnergySystemStruct) 725 } else if (tr.rowType == TraceRow.ROW_TYPE_ANOMALY_ENERGY) { 726 this.currentRowType = TraceRow.ROW_TYPE_ANOMALY_ENERGY; 727 if (!SpSystemTrace.isCanvasOffScreen) EnergyAnomalyStruct.hoverEnergyAnomalyStruct = tr.onMouseHover(x, y); 728 if (EnergyAnomalyStruct.hoverEnergyAnomalyStruct) { 729 tr.tip = `<span>AnomalyName:${EnergyAnomalyStruct.hoverEnergyAnomalyStruct.eventName}</span>` 730 } 731 tr.setTipLeft(x, EnergyAnomalyStruct.hoverEnergyAnomalyStruct) 732 } else if (tr.rowType == TraceRow.ROW_TYPE_STATE_ENERGY) { 733 this.currentRowType = TraceRow.ROW_TYPE_STATE_ENERGY; 734 if (!SpSystemTrace.isCanvasOffScreen) EnergyStateStruct.hoverEnergyStateStruct = tr.onMouseHover(x, y); 735 if (EnergyStateStruct.hoverEnergyStateStruct) { 736 if (EnergyStateStruct.hoverEnergyStateStruct.type!.toLocaleLowerCase().includes("state")) { 737 tr.tip = `<span>Switch Status: ${EnergyStateStruct.hoverEnergyStateStruct.value == 1 ? 'disable' : 'enable'}</span>` 738 } else { 739 tr.tip = `<span>value: ${EnergyStateStruct.hoverEnergyStateStruct.value}</span>` 740 } 741 } 742 tr.setTipLeft(x, EnergyStateStruct.hoverEnergyStateStruct) 743 } else if (tr.rowType == TraceRow.ROW_TYPE_SMAPS) { 744 this.currentRowType = TraceRow.ROW_TYPE_SMAPS; 745 if (!SpSystemTrace.isCanvasOffScreen) SmapsShowStruct.hoverStruct = tr.onMouseHover(x, y); 746 if (SmapsShowStruct.hoverStruct) { 747 let value = 0; 748 if (SmapsShowStruct.hoverStruct.value != undefined) { 749 value = SmapsShowStruct.hoverStruct.value 750 } 751 tr.tip = `<span>${Utils.getBinaryByteWithUnit( value * 1024)}</span>` 752 } 753 tr.setTipLeft(x, SmapsShowStruct.hoverStruct) 754 } else { 755 this.hoverStructNull(); 756 } 757 if (tr.isComplete) { 758 tr.draw(true); 759 } 760 } else { 761 tr.onMouseLeave(x, y); 762 tr.isHover = false; 763 tr.hoverX = x; 764 tr.hoverY = y; 765 } 766 767 } 768 if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft! 769 && ev.offsetX < this.timerShaftEL!.canvas!.offsetLeft! + this.timerShaftEL!.canvas!.offsetWidth! 770 && ev.offsetY > this.rowsEL!.offsetTop 771 && ev.offsetY < this.rowsEL!.offsetTop + this.rowsEL!.offsetHeight 772 ) { 773 } else { 774 this.hoverStructNull(); 775 for (let i = 0, len = rows.length; i < len; i++) { 776 if (!(rows[i].rowType === TraceRow.ROW_TYPE_PROCESS) && this.currentRowType === rows[i].rowType) { // 777 if (rows[i].isComplete) { 778 rows[i].draw(true); 779 } 780 } 781 } 782 } 783 } 784 } 785 786 hoverStructNull() { 787 CpuStruct.hoverCpuStruct = undefined; 788 CpuFreqStruct.hoverCpuFreqStruct = undefined; 789 ThreadStruct.hoverThreadStruct = undefined; 790 FuncStruct.hoverFuncStruct = undefined; 791 SpHiPerf.hoverCpuStruct = undefined; 792 SpFreqChart.hoverStateStruct = undefined; 793 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined 794 } 795 796 selectStructNull() { 797 CpuStruct.selectCpuStruct = undefined; 798 CpuStruct.wakeupBean = null; 799 CpuFreqStruct.selectCpuFreqStruct = undefined; 800 ThreadStruct.selectThreadStruct = undefined; 801 FuncStruct.selectFuncStruct = undefined; 802 SpHiPerf.selectCpuStruct = undefined; 803 SpFreqChart.selectStateStruct = undefined; 804 CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = undefined 805 } 806 807 documentOnClick = (ev: MouseEvent) => { 808 if (!this.loadTraceCompleted) return; 809 if (this.isMouseInSheet(ev)) return; 810 if ((window as any).isPackUpTable) { 811 (window as any).isPackUpTable = false; 812 return; 813 } 814 if (this.rangeSelect.isDrag()) { 815 return; 816 } 817 let x = ev.offsetX - this.timerShaftEL!.canvas!.offsetLeft; 818 let y = ev.offsetY; 819 if (this.timerShaftEL!.sportRuler!.frame.contains(x, y) && x > (TraceRow.rangeSelectObject?.startX || 0) && x < (TraceRow.rangeSelectObject?.endX || 0)) { 820 } else { 821 this.onClickHandler(); 822 this.documentOnMouseMove(ev) 823 } 824 } 825 826 onClickHandler() { 827 if (!this.loadTraceCompleted) return; 828 this.rowsEL?.querySelectorAll<TraceRow<any>>("trace-row").forEach(it => it.rangeSelect = false) 829 this.selectStructNull(); 830 let threadClickHandler: any; 831 let cpuClickHandler: any; 832 threadClickHandler = (d: ThreadStruct) => { 833 this.observerScrollHeightEnable = false; 834 this.scrollToProcess(`${d.cpu}`, "", "cpu-data", true); 835 let cpuRow = this.rowsEL?.querySelectorAll<TraceRow<CpuStruct>>(`trace-row[row-id='${d.cpu}'][row-type='cpu-data']`)[0]; 836 let findEntry = cpuRow!.dataList!.find((dat: any) => dat.startTime === d.startTime); 837 if (findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || findEntry!.startTime! > TraceRow.range!.endNS) { 838 this.timerShaftEL?.setRangeNS(findEntry!.startTime! - findEntry!.dur! * 2, findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2); 839 } 840 this.hoverStructNull(); 841 this.selectStructNull(); 842 CpuStruct.hoverCpuStruct = findEntry; 843 CpuStruct.selectCpuStruct = findEntry; 844 this.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, "inverted"); 845 cpuRow!.draw(); 846 this.traceSheetEL?.displayCpuData(CpuStruct.selectCpuStruct!, (wakeUpBean) => { 847 CpuStruct.wakeupBean = wakeUpBean; 848 this.visibleRows.forEach(it => it.draw()); 849 }, cpuClickHandler); 850 } 851 852 cpuClickHandler = (d: CpuStruct) => { 853 this.observerScrollHeightEnable = true; 854 let threadRow = this.rowsEL?.querySelectorAll<TraceRow<ThreadStruct>>(`trace-row[row-id='${d.tid}'][row-type='thread']`)[0]; 855 let task = () => { 856 if(threadRow){ 857 if (threadRow!.isComplete) { 858 let findEntry = threadRow!.dataList!.find((dat) => dat.startTime === d.startTime); 859 if (findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || findEntry!.startTime! > TraceRow.range!.endNS) { 860 this.timerShaftEL?.setRangeNS(findEntry!.startTime! - findEntry!.dur! * 2, findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2); 861 } 862 this.hoverStructNull(); 863 this.selectStructNull(); 864 ThreadStruct.hoverThreadStruct = findEntry; 865 ThreadStruct.selectThreadStruct = findEntry; 866 this.closeAllExpandRows(d.processId + "") 867 this.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, "inverted"); 868 threadRow!.draw(); 869 this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct!, threadClickHandler, cpuClickHandler); 870 this.scrollToProcess(`${d.tid}`, `${d.processId}`, "thread", true) 871 } else { 872 threadRow!.onComplete = () => { 873 let findEntry = threadRow!.dataList!.find((dat) => dat.startTime === d.startTime); 874 if (findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || findEntry!.startTime! > TraceRow.range!.endNS) { 875 this.timerShaftEL?.setRangeNS(findEntry!.startTime! - findEntry!.dur! * 2, findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2); 876 } 877 this.hoverStructNull(); 878 this.selectStructNull(); 879 ThreadStruct.hoverThreadStruct = findEntry; 880 ThreadStruct.selectThreadStruct = findEntry; 881 this.closeAllExpandRows(d.processId + "") 882 this.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, "inverted"); 883 threadRow!.draw(); 884 this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct!, threadClickHandler, cpuClickHandler); 885 this.scrollToProcess(`${d.tid}`, `${d.processId}`, "thread", false); 886 } 887 } 888 } 889 } 890 this.observerScrollHeightCallback = () => task(); 891 if(threadRow){ 892 this.scrollToProcess(`${d.tid}`, `${d.processId}`, "thread", true); 893 } 894 task(); 895 } 896 897 if (CpuStruct.hoverCpuStruct) { 898 CpuStruct.selectCpuStruct = CpuStruct.hoverCpuStruct 899 this.timerShaftEL?.drawTriangle(CpuStruct.selectCpuStruct!.startTime || 0, "inverted"); 900 this.traceSheetEL?.displayCpuData(CpuStruct.selectCpuStruct, (wakeUpBean) => { 901 CpuStruct.wakeupBean = wakeUpBean; 902 this.visibleRows.forEach(it => it.draw()); 903 }, cpuClickHandler); 904 this.timerShaftEL?.modifyFlagList(undefined); 905 } else if (ThreadStruct.hoverThreadStruct) { 906 ThreadStruct.selectThreadStruct = ThreadStruct.hoverThreadStruct; 907 this.timerShaftEL?.drawTriangle(ThreadStruct.selectThreadStruct!.startTime || 0, "inverted"); 908 this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct, threadClickHandler, cpuClickHandler); 909 this.timerShaftEL?.modifyFlagList(undefined); 910 } else if (FuncStruct.hoverFuncStruct) { 911 FuncStruct.selectFuncStruct = FuncStruct.hoverFuncStruct; 912 this.timerShaftEL?.drawTriangle(FuncStruct.selectFuncStruct!.startTs || 0, "inverted"); 913 this.traceSheetEL?.displayFuncData(FuncStruct.hoverFuncStruct, (funcStract: any) => { 914 this.observerScrollHeightEnable = true; 915 this.moveRangeToCenter(funcStract.startTime!, funcStract.dur!) 916 this.scrollToActFunc(funcStract, false) 917 }) 918 this.timerShaftEL?.modifyFlagList(undefined); 919 } else if (CpuFreqStruct.hoverCpuFreqStruct) { 920 CpuFreqStruct.selectCpuFreqStruct = CpuFreqStruct.hoverCpuFreqStruct 921 this.traceSheetEL?.displayFreqData() 922 this.timerShaftEL?.modifyFlagList(undefined); 923 }else if (SpFreqChart.hoverStateStruct) { 924 SpFreqChart.selectStateStruct = SpFreqChart.hoverStateStruct; 925 this.traceSheetEL?.displayCpuStateData() 926 this.timerShaftEL?.modifyFlagList(undefined); 927 } else if (CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct) { 928 CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct 929 this.traceSheetEL?.displayFreqLimitData() 930 this.timerShaftEL?.modifyFlagList(undefined); 931 } else { 932 this.observerScrollHeightEnable = false; 933 this.selectFlag = null; 934 this.timerShaftEL?.removeTriangle("inverted"); 935 if (!SportRuler.isMouseInSportRuler) { 936 this.traceSheetEL?.setAttribute("mode", 'hidden'); 937 this.getVisibleRows().forEach(it => it.draw(true)); 938 } 939 } 940 } 941 942 connectedCallback() { 943 /** 944 * 监听时间轴区间变化 945 */ 946 this.timerShaftEL!.rangeChangeHandler = this.timerShaftELRangeChange; 947 this.timerShaftEL!.flagChangeHandler = this.timerShaftELFlagChange; 948 this.timerShaftEL!.flagClickHandler = this.timerShaftELFlagClickHandler; 949 /** 950 * 监听rowsEL的滚动时间,刷新可见区域的trace-row组件的时间区间(将触发trace-row组件重绘) 951 */ 952 this.rowsEL?.addEventListener('scroll', this.rowsElOnScroll) 953 /** 954 * 监听document的mousemove事件 坐标通过换算后找到当前鼠标所在的trace-row组件,将坐标传入 955 */ 956 this.addEventListener('mousemove', this.documentOnMouseMove) 957 this.addEventListener('click', this.documentOnClick) 958 this.addEventListener('mousedown', this.documentOnMouseDown) 959 this.addEventListener('mouseup', this.documentOnMouseUp) 960 this.addEventListener('mouseout', this.documentOnMouseOut) 961 document.addEventListener('keypress', this.documentOnKeyPress) 962 document.addEventListener('keyup', this.documentOnKeyUp) 963 SpApplication.skinChange2 = (val: boolean) => { 964 this.timerShaftEL?.render() 965 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row:not([sleeping])`).forEach(it => { 966 this.hoverStructNull(); 967 it.draw(); 968 }) 969 } 970 } 971 972 scrollToProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) { 973 let row = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`); 974 if (row) { 975 row.expansion = true 976 } 977 let rootRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); 978 this.rowsEL!.scroll({ 979 top: (rootRow?.offsetTop || 0) - this.rowsEL!.offsetTop - this.rowsEL!.offsetHeight + (rootRow?.offsetHeight || 0), 980 left: 0, 981 behavior: smooth ? "smooth" : undefined 982 }) 983 } 984 985 scrollToDepth(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true, depth: number) { 986 let row = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`); 987 if (row) { 988 row.expansion = true 989 } 990 let rootRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); 991 this.rowsEL!.scroll({ 992 top: (rootRow?.offsetTop || 0) - this.rowsEL!.offsetTop - this.rowsEL!.offsetHeight + ((++depth) * 20 || 0), 993 left: 0, 994 behavior: smooth ? "smooth" : undefined 995 }) 996 } 997 998 scrollToFunction(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true, afterScroll: any) { 999 let row = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowParentId}'][folder]`); 1000 if (row) { 1001 row.expansion = true 1002 } 1003 let funcRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); 1004 if (funcRow == null) { 1005 let threadRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='thread']`); 1006 this.rowsEL!.scroll({ 1007 top: threadRow!.offsetTop - this.rowsEL!.offsetTop - this.rowsEL!.offsetHeight + threadRow!.offsetHeight + threadRow!.offsetHeight, 1008 left: 0, 1009 behavior: smooth ? "smooth" : undefined 1010 }) 1011 if (threadRow != null) { 1012 if (threadRow.isComplete) { 1013 afterScroll() 1014 } else { 1015 threadRow.onComplete = () => { 1016 funcRow = this.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); 1017 afterScroll() 1018 } 1019 } 1020 } 1021 } else { 1022 afterScroll() 1023 } 1024 } 1025 1026 rowScrollTo(offset: number, callback: Function) { 1027 const fixedOffset = offset; 1028 const onScroll = () => { 1029 if (this.rowsEL!.scrollTop === fixedOffset) { 1030 this.rowsEL!.removeEventListener('scroll', onScroll) 1031 callback() 1032 } 1033 } 1034 1035 this.rowsEL!.addEventListener('scroll', onScroll) 1036 onScroll() 1037 this.rowsEL!.scrollTo({ 1038 top: offset, 1039 behavior: 'smooth' 1040 }) 1041 } 1042 1043 disconnectedCallback() { 1044 this.timerShaftEL?.removeEventListener('range-change', this.timerShaftELRangeChange); 1045 this.rowsEL?.removeEventListener('scroll', this.rowsElOnScroll); 1046 this.removeEventListener('mousemove', this.documentOnMouseMove); 1047 this.removeEventListener('click', this.documentOnClick); 1048 this.removeEventListener('mousedown', this.documentOnMouseDown) 1049 this.removeEventListener('mouseup', this.documentOnMouseUp) 1050 this.removeEventListener('mouseout', this.documentOnMouseOut) 1051 document.removeEventListener('keypress', this.documentOnKeyPress) 1052 document.removeEventListener('keyup', this.documentOnKeyUp) 1053 } 1054 1055 loadDatabaseUrl(url: string, progress: Function, complete?: ((res: { status: boolean, msg: string }) => void) | undefined) { 1056 this.observerScrollHeightEnable = false; 1057 this.init({url: url}, "", progress).then((res) => { 1058 if (complete) { 1059 complete(res); 1060 } 1061 }) 1062 } 1063 1064 loadDatabaseArrayBuffer(buf: ArrayBuffer, thirdPartyWasmConfigUrl: string, progress: ((name: string, percent: number) => void), complete?: ((res: { status: boolean, msg: string }) => void) | undefined) { 1065 this.observerScrollHeightEnable = false; 1066 this.init({buf}, thirdPartyWasmConfigUrl, progress).then((res) => { 1067 let scrollTop = this.rowsEL?.scrollTop || 0 1068 let scrollHeight = this.rowsEL?.clientHeight || 0 1069 this.rowsEL?.querySelectorAll("trace-row").forEach((it: any) => { 1070 this.observer.observe(it); 1071 }) 1072 if (complete) { 1073 complete(res); 1074 } 1075 }) 1076 } 1077 1078 search(query: string) { 1079 this.shadowRoot?.querySelectorAll<TraceRow<any>>('trace-row').forEach(item => { 1080 if (query == null || query == undefined || query == '') { 1081 if (item.rowType == TraceRow.ROW_TYPE_CPU || 1082 item.rowType == TraceRow.ROW_TYPE_CPU_FREQ || 1083 item.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY || 1084 item.rowType == TraceRow.ROW_TYPE_FPS || 1085 item.rowType == TraceRow.ROW_TYPE_PROCESS || 1086 item.rowType == TraceRow.ROW_TYPE_CPU_ABILITY || 1087 item.rowType == TraceRow.ROW_TYPE_MEMORY_ABILITY || 1088 item.rowType == TraceRow.ROW_TYPE_DISK_ABILITY || 1089 item.rowType == TraceRow.ROW_TYPE_NETWORK_ABILITY) { 1090 item.expansion = false; 1091 item.rowHidden = false; 1092 } else { 1093 item.rowHidden = true; 1094 } 1095 } else { 1096 if (item.name.toLowerCase().indexOf(query.toLowerCase()) >= 0) { 1097 item.rowHidden = false; 1098 } else { 1099 item.rowHidden = true; 1100 } 1101 } 1102 }) 1103 this.getVisibleRows().forEach(it => it.rowHidden = false && it.draw(true)) 1104 } 1105 1106 searchCPU(query: string): Array<CpuStruct> { 1107 let searchResults: Array<CpuStruct> = [] 1108 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach(item => { 1109 let res = item!.dataList!.filter(it => (it.name && it.name.search(query) >= 0) || it.tid == query 1110 || it.processId == query 1111 || (it.processName && it.processName.search(query) >= 0) 1112 ) 1113 searchResults.push(...res); 1114 }) 1115 searchResults.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); 1116 return searchResults; 1117 } 1118 1119 async searchFunction(cpuList: Array<any>, query: string): Promise<Array<any>> { 1120 let list = await querySearchFunc(query) 1121 cpuList = cpuList.concat(list) 1122 cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); 1123 return cpuList 1124 } 1125 1126 searchThreadsAndProcesses(query: string): Array<any> { 1127 let searchResults: Array<any> = [] 1128 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='thread'][row-type='process']`).forEach(item => { 1129 if (item!.name.search(query) >= 0) { 1130 let searchBean = new SearchThreadProcessBean() 1131 searchBean.name = item.name 1132 searchBean.rowId = item.rowId 1133 searchBean.type = "thread||process" 1134 searchBean.rowType = item.rowType 1135 searchBean.rowParentId = item.rowParentId 1136 searchResults.push(searchBean) 1137 } 1138 }) 1139 return searchResults 1140 } 1141 1142 showStruct(previous: boolean, currentIndex: number, structs: Array<any>) { 1143 if (structs.length == 0) { 1144 return 0; 1145 } 1146 let findIndex = -1; 1147 if (previous) { 1148 for (let i = structs.length - 1; i >= 0; i--) { 1149 let it = structs[i]; 1150 if (i < currentIndex && (it.startTime!) >= (TraceRow.range!.startNS) && (it.startTime!) + (it.dur!) <= (TraceRow.range!.endNS)) { 1151 findIndex = i; 1152 break; 1153 } 1154 } 1155 } else { 1156 findIndex = structs.findIndex((it, idx) => { 1157 return idx > currentIndex && (it.startTime!) >= (TraceRow.range!.startNS) && (it.startTime!) + (it.dur!) <= (TraceRow.range!.endNS) 1158 }) 1159 } 1160 let findEntry: any 1161 if (findIndex >= 0) { 1162 findEntry = structs[findIndex]; 1163 } else { 1164 if (previous) { 1165 for (let i = structs.length - 1; i >= 0; i--) { 1166 let it = structs[i]; 1167 if ((it.startTime! + it.dur!) < (TraceRow.range!.startNS)) { 1168 findIndex = i; 1169 break; 1170 } 1171 } 1172 if (findIndex == -1) { 1173 findIndex = structs.length - 1; 1174 } 1175 } else { 1176 findIndex = structs.findIndex((it) => (it.startTime!) > (TraceRow.range!.endNS)) 1177 if (findIndex == -1) { 1178 findIndex = 0; 1179 } 1180 } 1181 findEntry = structs[findIndex]; 1182 this.moveRangeToCenter(findEntry.startTime!, findEntry.dur!) 1183 } 1184 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row`).forEach(item => { 1185 item.highlight = false; 1186 if (!item.sleeping) { 1187 item.draw(true) 1188 } 1189 }) 1190 if (findEntry.type == 'thread') { 1191 CpuStruct.selectCpuStruct = findEntry; 1192 CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; 1193 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach(item => { 1194 item.highlight = item.rowId == `${findEntry.cpu}`; 1195 item.draw(true) 1196 }) 1197 this.scrollToProcess(`${findEntry.cpu}`, "", "cpu-data", true) 1198 this.onClickHandler(); 1199 } else if (findEntry.type == "func") { 1200 this.observerScrollHeightEnable = true; 1201 this.scrollToActFunc(findEntry, true) 1202 } else if (findEntry.type == "thread||process") { 1203 let threadProcessRow = this.rowsEL?.querySelectorAll<TraceRow<ThreadStruct>>(`trace-row[row-id='${findEntry.rowId}'][row-type='${findEntry.rowType}']`)[0]; 1204 threadProcessRow!.highlight = true 1205 this.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); 1206 let completeEntry = () => { 1207 let searchEntry = threadProcessRow!.dataList!.find((dat) => dat.startTime === findEntry.startTime); 1208 this.hoverStructNull(); 1209 this.selectStructNull(); 1210 ThreadStruct.hoverThreadStruct = searchEntry; 1211 ThreadStruct.selectThreadStruct = searchEntry; 1212 this.closeAllExpandRows(findEntry.rowParentId) 1213 threadProcessRow!.draw(); 1214 } 1215 let scrollTimer: any; 1216 this.observerScrollHeightCallback = () => { 1217 if (threadProcessRow!.isComplete) { 1218 completeEntry() 1219 this.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true) 1220 } else { 1221 threadProcessRow!.onComplete = () => { 1222 completeEntry() 1223 clearTimeout(scrollTimer); 1224 scrollTimer = setTimeout(() => this.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, false), 100) 1225 } 1226 } 1227 } 1228 } 1229 this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, "inverted"); 1230 return findIndex; 1231 } 1232 1233 scrollToActFunc(funcStract: any, highlight: boolean) { 1234 this.scrollToFunction(`${funcStract.tid}`, `${funcStract.pid}`, funcStract.type, false, () => { 1235 let funcRow = this.rowsEL?.querySelector<TraceRow<FuncStruct>>(`trace-row[row-id='${funcStract.tid}'][row-type='func']`); 1236 if (funcRow == null) return 1237 this.scrollToDepth(`${funcStract.tid}`, `${funcStract.pid}`, "func", true, funcStract.depth || 0) 1238 funcRow!.highlight = highlight 1239 let completeEntry = () => { 1240 if (funcRow == null) return 1241 let searchEntry = funcRow!.dataList!.find((dat) => dat.startTs === funcStract.startTime); 1242 this.hoverStructNull(); 1243 this.selectStructNull(); 1244 FuncStruct.hoverFuncStruct = searchEntry; 1245 FuncStruct.selectFuncStruct = searchEntry; 1246 this.closeAllExpandRows(funcStract.pid) 1247 this.visibleRows.forEach(it => it.draw()); 1248 } 1249 let scrollTimer: any; 1250 this.observerScrollHeightCallback = () => { 1251 funcRow = this.rowsEL?.querySelector<TraceRow<FuncStruct>>(`trace-row[row-id='${funcStract.tid}'][row-type='func']`); 1252 if (funcRow == null) { 1253 return 1254 } 1255 if (funcRow!.isComplete) { 1256 completeEntry() 1257 this.onClickHandler(); 1258 this.scrollToDepth(`${funcStract.tid}`, `${funcStract.pid}`, "func", false, funcStract.depth || 0) 1259 } else { 1260 funcRow!.onComplete = () => { 1261 completeEntry() 1262 this.onClickHandler(); 1263 clearTimeout(scrollTimer); 1264 scrollTimer = setTimeout(() => this.scrollToDepth(`${funcStract.tid}`, `${funcStract.pid}`, "func", false, funcStract.depth || 0), 100) 1265 } 1266 } 1267 } 1268 if (funcRow?.isComplete) { 1269 completeEntry() 1270 this.onClickHandler(); 1271 this.scrollToProcess(`${funcStract.tid}`, `${funcStract.pid}`, "thread", false) 1272 this.scrollToDepth(`${funcStract.tid}`, `${funcStract.pid}`, "func", true, funcStract.depth || 0) 1273 } 1274 }); 1275 } 1276 1277 closeAllExpandRows(pid: string) { 1278 let expandRows = this.rowsEL?.querySelectorAll<TraceRow<ProcessStruct>>(`trace-row[row-type='process'][expansion]`); 1279 expandRows?.forEach((row) => { 1280 if (row.rowId != pid) { 1281 row.expansion = false 1282 } 1283 }) 1284 } 1285 1286 moveRangeToCenter(startTime: number, dur: number) { 1287 let startNS = this.timerShaftEL?.getRange()?.startNS || 0; 1288 let endNS = this.timerShaftEL?.getRange()?.endNS || 0; 1289 let harfDur = Math.trunc((endNS - startNS) / 2 - dur / 2); 1290 this.timerShaftEL?.setRangeNS(startTime - harfDur, startTime + dur + harfDur); 1291 } 1292 1293 showPreCpuStruct(currentIndex: number, cpuStructs: Array<CpuStruct>): number { 1294 if (cpuStructs.length == 0) { 1295 return 0; 1296 } 1297 let findIndex = -1; 1298 for (let i = cpuStructs.length - 1; i >= 0; i--) { 1299 let it = cpuStructs[i]; 1300 if (i < currentIndex && (it.startTime!) >= (TraceRow.range!.startNS) && (it.startTime!) + (it.dur!) <= (TraceRow.range!.endNS)) { 1301 findIndex = i; 1302 break; 1303 } 1304 } 1305 if (findIndex >= 0) { 1306 let findEntry = cpuStructs[findIndex]; 1307 CpuStruct.selectCpuStruct = findEntry; 1308 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach(item => { 1309 item.highlight = item.rowId == `${findEntry.cpu}`; 1310 item.draw(true); 1311 }) 1312 this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, "inverted"); 1313 } else { 1314 for (let i = cpuStructs.length - 1; i >= 0; i--) { 1315 let it = cpuStructs[i]; 1316 if ((it.startTime! + it.dur!) < (TraceRow.range!.startNS)) { 1317 findIndex = i; 1318 break; 1319 } 1320 } 1321 let findEntry: CpuStruct; 1322 if (findIndex == -1) { 1323 findIndex = cpuStructs.length - 1; 1324 } 1325 findEntry = cpuStructs[findIndex]; 1326 CpuStruct.selectCpuStruct = findEntry; 1327 let startNS = this.timerShaftEL?.getRange()?.startNS || 0; 1328 let endNS = this.timerShaftEL?.getRange()?.endNS || 0; 1329 let harfDur = Math.trunc((endNS - startNS) / 2 - findEntry.dur! / 2); 1330 this.timerShaftEL?.setRangeNS(findEntry.startTime! - harfDur, findEntry.startTime! + findEntry.dur! + harfDur); 1331 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach(item => { 1332 item.highlight = item.rowId == `${findEntry.cpu}`; 1333 item.draw(true) 1334 }) 1335 this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, "inverted"); 1336 } 1337 CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; 1338 this.onClickHandler(); 1339 return findIndex; 1340 } 1341 1342 showNextCpuStruct(currentIndex: number, cpuStructs: Array<CpuStruct>): number { 1343 if (cpuStructs.length == 0) { 1344 return 0; 1345 } 1346 let findIndex = cpuStructs.findIndex((it, idx) => { 1347 return idx > currentIndex && (it.startTime!) >= (TraceRow.range!.startNS) && (it.startTime!) + (it.dur!) <= (TraceRow.range!.endNS) 1348 }) 1349 if (findIndex >= 0) { 1350 let findEntry = cpuStructs[findIndex]; 1351 CpuStruct.selectCpuStruct = findEntry; 1352 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach(item => { 1353 item.highlight = item.rowId == `${findEntry.cpu}`; 1354 item.draw(true); 1355 }) 1356 this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, "inverted"); 1357 } else { 1358 findIndex = cpuStructs.findIndex((it) => (it.startTime!) > (TraceRow.range!.endNS)) 1359 let findEntry: CpuStruct; 1360 if (findIndex == -1) { 1361 findIndex = 0; 1362 } 1363 findEntry = cpuStructs[findIndex]; 1364 CpuStruct.selectCpuStruct = findEntry; 1365 let startNS = this.timerShaftEL?.getRange()?.startNS || 0; 1366 let endNS = this.timerShaftEL?.getRange()?.endNS || 0; 1367 let harfDur = Math.trunc((endNS - startNS) / 2 - findEntry.dur! / 2); 1368 this.timerShaftEL?.setRangeNS(findEntry.startTime! - harfDur, findEntry.startTime! + findEntry.dur! + harfDur); 1369 this.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[row-type='cpu-data']`).forEach(item => { 1370 item.highlight = item.rowId == `${findEntry.cpu}`; 1371 item.draw(true); 1372 }) 1373 this.timerShaftEL?.drawTriangle(findEntry.startTime || 0, "inverted"); 1374 } 1375 CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; 1376 this.onClickHandler(); 1377 return findIndex; 1378 } 1379 1380 reset(progress: Function | undefined | null) { 1381 this.loadTraceCompleted = false; 1382 if (this.rowsEL) this.rowsEL.innerHTML = '' 1383 this.spacerEL!.style.height = '0px'; 1384 this.rangeSelect.rangeTraceRow = []; 1385 CpuStruct.wakeupBean = undefined; 1386 this.selectStructNull(); 1387 this.hoverStructNull(); 1388 this.traceSheetEL?.setAttribute("mode", "hidden") 1389 progress && progress("rest timershaft", 8); 1390 this.timerShaftEL?.reset(); 1391 progress && progress("clear cache", 10); 1392 procedurePool.clearCache(); 1393 } 1394 1395 init = async (param: { buf?: ArrayBuffer, url?: string }, wasmConfigUri: string, progress: Function) => { 1396 progress("Load database", 6); 1397 this.reset(progress); 1398 if (param.buf) { 1399 let configJson = ""; 1400 try { 1401 configJson = await fetch(wasmConfigUri).then(res => res.text()); 1402 } catch (e) { 1403 error("getWasmConfigFailed", e) 1404 } 1405 let {status, msg, sdkConfigMap} = await threadPool.initSqlite(param.buf, configJson, progress); 1406 if (!status) { 1407 return {status: false, msg: msg} 1408 } 1409 SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap == undefined ? undefined : sdkConfigMap; 1410 } 1411 if (param.url) { 1412 let {status, msg} = await threadPool.initServer(param.url, progress); 1413 if (!status) { 1414 return {status: false, msg: msg} 1415 } 1416 } 1417 await this.chartManager?.init(progress); 1418 this.rowsEL?.querySelectorAll<TraceRow<any>>("trace-row").forEach((it: any) => { 1419 it.addEventListener('expansion-change', () => { 1420 this.getVisibleRows().forEach(it2 => it2.draw()); 1421 }) 1422 }) 1423 progress("completed", 100); 1424 info("All TraceRow Data initialized") 1425 this.loadTraceCompleted = true; 1426 this.getVisibleRows().forEach(it => { 1427 it.draw(); 1428 }); 1429 return {status: true, msg: "success"} 1430 } 1431 1432 initHtml(): string { 1433 return ` 1434 <style> 1435 :host{ 1436 display: block; 1437 width: 100%; 1438 height: 100%; 1439 } 1440 .timer-shaft{ 1441 width: 100%; 1442 z-index: 2; 1443 } 1444 .rows{ 1445 color: #fff; 1446 display: block; 1447 box-sizing: border-box; 1448 /*flex-direction: column;*/ 1449 /*overflow-y: auto;*/ 1450 overflow: overlay; 1451 overflow-anchor: none; 1452 max-height: calc(100vh - 147px - 48px); 1453 flex: 1; 1454 width: 100%; 1455 background: var(--dark-background4,#ffffff); 1456 /*scroll-behavior: smooth;*/ 1457 } 1458 .container{ 1459 width: 100%; 1460 box-sizing: border-box; 1461 height: 100%; 1462 display: grid; 1463 grid-template-columns: 1fr; 1464 grid-template-rows: min-content min-content 1fr min-content; 1465 } 1466 .trace-sheet{ 1467 cursor: default; 1468 } 1469 1470 </style> 1471 <div class="container"> 1472 <timer-shaft-element class="timer-shaft"> 1473 </timer-shaft-element> 1474 <div class="spacer"></div> 1475 <div class="rows"></div> 1476 <trace-sheet class="trace-sheet" mode="hidden"> 1477 </trace-sheet> 1478 </div> 1479 `; 1480 } 1481} 1482