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 {SpSystemTrace} from "../SpSystemTrace.js"; 17import {TraceRow} from "../trace/base/TraceRow.js"; 18import {procedurePool} from "../../database/Procedure.js"; 19import { 20 queryHiPerfCpuData, 21 queryHiPerfCpuMergeData, 22 queryHiPerfCpuMergeData2, 23 queryHiPerfEventData, 24 queryHiPerfEventList, 25 queryHiPerfEventListData, 26 queryHiPerfProcessData, 27 queryHiPerfThreadData, 28 queryPerfCmdline, 29 queryPerfThread 30} from "../../database/SqlLite.js"; 31import {Utils} from "../trace/base/Utils.js"; 32import {PerfThread} from "../../bean/PerfProfile.js"; 33import {HiPerfCpuStruct} from "../../database/ui-worker/ProcedureWorkerHiPerfCPU.js"; 34import {HiPerfThreadStruct} from "../../database/ui-worker/ProcedureWorkerHiPerfThread.js"; 35import {HiPerfProcessStruct} from "../../database/ui-worker/ProcedureWorkerHiPerfProcess.js"; 36import {info} from "../../../log/Log.js"; 37import {HiPerfEventStruct} from "../../database/ui-worker/ProcedureWorkerHiPerfEvent.js"; 38 39export interface ResultData { 40 existA: boolean | null | undefined, 41 existF: boolean | null | undefined, 42 fValue: number 43} 44 45export class SpHiPerf { 46 static hoverCpuStruct: HiPerfCpuStruct | undefined; 47 static hoverEventuctStruct: HiPerfEventStruct | undefined; 48 static selectCpuStruct: HiPerfCpuStruct | undefined; 49 static hoverProcessStruct: HiPerfProcessStruct | undefined; 50 static selectProcessStruct: HiPerfProcessStruct | undefined; 51 static hoverThreadStruct: HiPerfThreadStruct | undefined; 52 static selectThreadStruct: HiPerfThreadStruct | undefined; 53 static stringResult: ResultData | undefined; 54 55 private cpuData: Array<any> | undefined 56 public maxCpuId: number = 0 57 private rowFolder!: TraceRow<any>; 58 private perfThreads: Array<PerfThread> | undefined; 59 private trace: SpSystemTrace; 60 private group: any; 61 private eventTypeList: Array<{ id: number, report_value: string }> = []; 62 63 constructor(trace: SpSystemTrace) { 64 this.trace = trace; 65 } 66 67 async init() { 68 await this.initCmdLine() 69 this.perfThreads = await queryPerfThread(); 70 this.eventTypeList = await queryHiPerfEventList(); 71 info("PerfThread Data size is: ", this.perfThreads!.length) 72 this.group = Utils.groupBy(this.perfThreads || [], "pid"); 73 this.cpuData = await queryHiPerfCpuMergeData2(); 74 this.maxCpuId = this.cpuData.length > 0 ? this.cpuData.reduce((max, v) => max.cpu_id >= v.cpu_id ? max : v).cpu_id : -Infinity; 75 if (this.cpuData.length > 0) { 76 await this.initFolder(); 77 await this.initCpuMerge(); 78 await this.initCpu(); 79 await this.initProcess(); 80 } 81 info("HiPerf Data initialized") 82 } 83 84 getStringResult(s: string = "") { 85 let list = s.split(" ").filter((e) => e); 86 let sA = list.findIndex((item) => item == "-a"); 87 let sF = list.findIndex((item) => item == "-f"); 88 SpHiPerf.stringResult = { 89 existA: sA !== -1, 90 existF: sF !== -1, 91 fValue: Number((1000 / (sF !== -1 ? parseInt(list[sF + 1]) : 1000)).toFixed(1)), 92 } 93 } 94 95 async initCmdLine() { 96 let perfCmdLines = await queryPerfCmdline(); 97 if (perfCmdLines.length > 0) { 98 this.getStringResult(perfCmdLines[0].report_value) 99 } else { 100 SpHiPerf.stringResult = { 101 existA: true, 102 existF: false, 103 fValue: 1, 104 } 105 } 106 } 107 108 async initFolder() { 109 let row = new TraceRow({ 110 canvasNumber: 1, 111 alpha: false, 112 contextId: '2d', 113 isOffScreen: SpSystemTrace.isCanvasOffScreen 114 }); 115 row.setAttribute('disabled-check', '') 116 row.rowId = `HiPerf`; 117 row.index = 0; 118 row.rowType = TraceRow.ROW_TYPE_HIPERF 119 row.rowParentId = ''; 120 row.folder = true; 121 if (SpHiPerf.stringResult?.existA === true) { 122 row.name = `HiPerf (All)`; 123 } else { 124 let names = Reflect.ownKeys(this.group).map((pid: any) => { 125 let array = this.group[pid] as Array<PerfThread>; 126 let process = array.filter(th => th.pid === th.tid)[0]; 127 return process.processName; 128 }).join(','); 129 row.name = `HiPerf (${names})`; 130 } 131 row.supplier = () => new Promise<Array<any>>((resolve) => resolve([])); 132 row.onThreadHandler = (useCache) => { 133 procedurePool.submitWithName(`process${row.index}`, `HiPerf-Group`, { 134 list: row.must ? row.dataList : undefined, 135 offscreen: !row.isTransferCanvas ? row.offscreen[0] : undefined, 136 xs: TraceRow.range?.xs, 137 dpr: row.dpr, 138 isHover: row.isHover, 139 flagMoveInfo: this.trace.hoverFlag, 140 flagSelectedInfo: this.trace.selectFlag, 141 hoverX: row.hoverX, 142 hoverY: row.hoverY, 143 canvasWidth: row.canvasWidth, 144 canvasHeight: row.canvasHeight, 145 isRangeSelect: row.rangeSelect, 146 rangeSelectObject: TraceRow.rangeSelectObject, 147 useCache: useCache, 148 lineColor: row.getLineColor(), 149 startNS: TraceRow.range?.startNS || 0, 150 endNS: TraceRow.range?.endNS || 0, 151 totalNS: TraceRow.range?.totalNS || 0, 152 slicesTime: TraceRow.range?.slicesTime, 153 scale: TraceRow.range?.scale || 50, 154 intervalPerf: SpHiPerf.stringResult?.fValue || 1, 155 range:TraceRow.range, 156 frame: row.frame 157 }, !row.isTransferCanvas ? row.offscreen[0] : undefined, (res: any) => { 158 row.must = false; 159 }) 160 row.isTransferCanvas = true; 161 } 162 this.rowFolder = row; 163 this.trace.rowsEL?.appendChild(row) 164 } 165 166 async initCpuMerge() { 167 let row = new TraceRow({ 168 canvasNumber: 1, 169 alpha: false, 170 contextId: '2d', 171 isOffScreen: SpSystemTrace.isCanvasOffScreen 172 }); 173 row.rowId = `HiPerf-cpu-merge`; 174 row.index = 0; 175 row.rowType = TraceRow.ROW_TYPE_HIPERF_CPU 176 row.rowParentId = 'HiPerf'; 177 row.rowHidden = !this.rowFolder.expansion 178 row.folder = false; 179 row.name = `HiPerf`; 180 row.setAttribute('children', '') 181 row.favoriteChangeHandler = this.trace.favoriteChangeHandler; 182 row.selectChangeHandler = this.trace.selectChangeHandler; 183 let that = this; 184 row.supplier = () => queryHiPerfCpuMergeData(); 185 row.onThreadHandler = (useCache) => { 186 procedurePool.submitWithName(`freq${row.index}`, `HiPerf-Cpu-Merge`, { 187 list: row.must ? row.dataList : undefined, 188 offscreen: !row.isTransferCanvas ? row.offscreen[0] : undefined, 189 xs: TraceRow.range?.xs, 190 dpr: row.dpr, 191 isHover: row.isHover, 192 flagMoveInfo: this.trace.hoverFlag, 193 flagSelectedInfo: this.trace.selectFlag, 194 hoverX: row.hoverX, 195 hoverY: row.hoverY, 196 canvasWidth: row.canvasWidth, 197 canvasHeight: row.canvasHeight, 198 hoverStruct: SpHiPerf.hoverCpuStruct, 199 selectStruct: SpHiPerf.selectCpuStruct, 200 isRangeSelect: row.rangeSelect, 201 rangeSelectObject: TraceRow.rangeSelectObject, 202 useCache: useCache, 203 lineColor: row.getLineColor(), 204 startNS: TraceRow.range?.startNS || 0, 205 endNS: TraceRow.range?.endNS || 0, 206 totalNS: TraceRow.range?.totalNS || 0, 207 slicesTime: TraceRow.range?.slicesTime, 208 scale: TraceRow.range?.scale || 50, 209 intervalPerf: SpHiPerf.stringResult?.fValue || 1, 210 range:TraceRow.range, 211 frame: row.frame, 212 maxCpu: (this.maxCpuId + 1) 213 }, row.getTransferArray(), (res: any, hover: any) => { 214 row.must = false; 215 if (row.isHover) { 216 SpHiPerf.hoverCpuStruct = hover; 217 } 218 }) 219 row.isTransferCanvas = true; 220 } 221 this.trace.rowsEL?.appendChild(row) 222 } 223 224 async initCpu() { 225 for (let i = 0; i <= this.maxCpuId; i++) { 226 let row = new TraceRow({ 227 canvasNumber: 1, 228 alpha: false, 229 contextId: '2d', 230 isOffScreen: SpSystemTrace.isCanvasOffScreen 231 }); 232 row.rowId = `HiPerf-cpu-${i}`; 233 row.index = i; 234 row.rowType = TraceRow.ROW_TYPE_HIPERF_CPU 235 row.rowParentId = 'HiPerf'; 236 row.rowHidden = !this.rowFolder.expansion 237 row.folder = false; 238 row.name = `Cpu ${i}`; 239 row.setAttribute('children', '') 240 row.favoriteChangeHandler = this.trace.favoriteChangeHandler; 241 row.selectChangeHandler = this.trace.selectChangeHandler; 242 let that = this; 243 row.supplier = () => queryHiPerfCpuData(i); 244 row.onThreadHandler = (useCache) => { 245 procedurePool.submitWithName(`cpu${row.index}`, `HiPerf-Cpu-${i}`, { 246 list: row.must ? row.dataList : undefined, 247 offscreen: !row.isTransferCanvas ? row.offscreen[0] : undefined, 248 xs: TraceRow.range?.xs, 249 dpr: row.dpr, 250 isHover: row.isHover, 251 flagMoveInfo: this.trace.hoverFlag, 252 flagSelectedInfo: this.trace.selectFlag, 253 hoverX: row.hoverX, 254 hoverY: row.hoverY, 255 canvasWidth: row.canvasWidth, 256 canvasHeight: row.canvasHeight, 257 hoverStruct: SpHiPerf.hoverCpuStruct, 258 selectStruct: SpHiPerf.selectCpuStruct, 259 isRangeSelect: row.rangeSelect, 260 rangeSelectObject: TraceRow.rangeSelectObject, 261 useCache: useCache, 262 lineColor: row.getLineColor(), 263 startNS: TraceRow.range?.startNS || 0, 264 endNS: TraceRow.range?.endNS || 0, 265 totalNS: TraceRow.range?.totalNS || 0, 266 slicesTime: TraceRow.range?.slicesTime, 267 scale: TraceRow.range?.scale || 50, 268 intervalPerf: SpHiPerf.stringResult?.fValue || 1, 269 range:TraceRow.range, 270 frame: row.frame, 271 maxCpu: undefined 272 }, row.getTransferArray(), (res: any, hover: any) => { 273 row.must = false; 274 if (row.isHover) { 275 SpHiPerf.hoverCpuStruct = hover; 276 } 277 }) 278 row.isTransferCanvas = true; 279 } 280 this.trace.rowsEL?.appendChild(row) 281 } 282 } 283 284 async initReport() { 285 this.eventTypeList.forEach((it, index) => { 286 let fold = new TraceRow({ 287 canvasNumber: 1, 288 alpha: false, 289 contextId: '2d', 290 isOffScreen: SpSystemTrace.isCanvasOffScreen 291 }); 292 fold.rowId = `Perf-Report-${it.id}-${it.report_value}`; 293 fold.index = index; 294 fold.rowType = TraceRow.ROW_TYPE_HIPERF_REPORT 295 fold.rowParentId = 'HiPerf'; 296 fold.rowHidden = !this.rowFolder.expansion 297 fold.folder = true; 298 fold.name = `Event :${it.report_value}`; 299 fold.folderPaddingLeft = 30; 300 fold.favoriteChangeHandler = this.trace.favoriteChangeHandler; 301 fold.selectChangeHandler = this.trace.selectChangeHandler; 302 let that = this; 303 fold.supplier = () => queryHiPerfEventListData(it.id); 304 fold.onThreadHandler = (useCache) => { 305 procedurePool.submitWithName(`process${(fold.index) % procedurePool.processLen.length}`, `HiPerf-Report-Fold-${it.report_value}-${it.id}`, { 306 list: fold.must ? fold.dataList : undefined, 307 offscreen: !fold.isTransferCanvas ? fold.offscreen[0] : undefined, 308 xs: TraceRow.range?.xs, 309 dpr: fold.dpr, 310 isHover: fold.isHover, 311 flagMoveInfo: this.trace.hoverFlag, 312 flagSelectedInfo: this.trace.selectFlag, 313 hoverX: fold.hoverX, 314 hoverY: fold.hoverY, 315 canvasWidth: fold.canvasWidth, 316 canvasHeight: fold.canvasHeight, 317 isRangeSelect: fold.rangeSelect, 318 rangeSelectObject: TraceRow.rangeSelectObject, 319 useCache: useCache, 320 lineColor: fold.getLineColor(), 321 startNS: TraceRow.range?.startNS || 0, 322 endNS: TraceRow.range?.endNS || 0, 323 totalNS: TraceRow.range?.totalNS || 0, 324 slicesTime: TraceRow.range?.slicesTime, 325 scale: TraceRow.range?.scale || 50, 326 intervalPerf: SpHiPerf.stringResult?.fValue || 1, 327 range:TraceRow.range, 328 frame: fold.frame 329 }, fold.getTransferArray(), (res: any, hover: any) => { 330 fold.must = false; 331 if (fold.isHover) { 332 } 333 }) 334 fold.isTransferCanvas = true; 335 } 336 this.trace.rowsEL?.appendChild(fold) 337 338 for (let i = 0; i <= this.maxCpuId; i++) { 339 let row = new TraceRow({ 340 canvasNumber: 1, 341 alpha: false, 342 contextId: '2d', 343 isOffScreen: SpSystemTrace.isCanvasOffScreen 344 }); 345 row.rowId = `HiPerf-Report-Event-${it.report_value}-${i}`; 346 row.index = i; 347 row.rowType = TraceRow.ROW_TYPE_HIPERF_EVENT 348 row.rowParentId = fold.rowId; 349 row.rowHidden = !fold.expansion 350 row.folder = false; 351 row.name = `Cpu ${i}`; 352 row.setAttribute('children', '') 353 row.favoriteChangeHandler = this.trace.favoriteChangeHandler; 354 row.selectChangeHandler = this.trace.selectChangeHandler; 355 let that = this; 356 row.supplier = () => queryHiPerfEventData(it.id, row.index); 357 row.onThreadHandler = (useCache) => { 358 procedurePool.submitWithName(`process${row.index % procedurePool.processLen.length}`, `HiPerf-Report-Event-${it.report_value}-${i}`, { 359 list: row.must ? row.dataList : undefined, 360 offscreen: !row.isTransferCanvas ? row.offscreen[0] : undefined, 361 xs: TraceRow.range?.xs, 362 dpr: row.dpr, 363 isHover: row.isHover, 364 flagMoveInfo: this.trace.hoverFlag, 365 flagSelectedInfo: this.trace.selectFlag, 366 hoverX: row.hoverX, 367 hoverY: row.hoverY, 368 canvasWidth: row.canvasWidth, 369 canvasHeight: row.canvasHeight, 370 hoverStruct: SpHiPerf.hoverEventuctStruct, 371 selectStruct: SpHiPerf.selectCpuStruct, 372 isRangeSelect: row.rangeSelect, 373 rangeSelectObject: TraceRow.rangeSelectObject, 374 useCache: useCache, 375 lineColor: row.getLineColor(), 376 startNS: TraceRow.range?.startNS || 0, 377 endNS: TraceRow.range?.endNS || 0, 378 totalNS: TraceRow.range?.totalNS || 0, 379 slicesTime: TraceRow.range?.slicesTime, 380 scale: TraceRow.range?.scale || 50, 381 intervalPerf: SpHiPerf.stringResult?.fValue || 1, 382 range:TraceRow.range, 383 frame: row.frame, 384 maxCpu: undefined 385 }, row.getTransferArray(), (res: any, hover: any) => { 386 row.must = false; 387 if (row.isHover) { 388 SpHiPerf.hoverEventuctStruct = hover; 389 } 390 }) 391 row.isTransferCanvas = true; 392 } 393 this.trace.rowsEL?.appendChild(row) 394 } 395 }) 396 } 397 398 async initProcess() { 399 Reflect.ownKeys(this.group).forEach((key, index) => { 400 let array = this.group[key] as Array<PerfThread>; 401 let process = array.filter(th => th.pid === th.tid)[0]; 402 let row = new TraceRow({ 403 canvasNumber: 1, 404 alpha: false, 405 contextId: '2d', 406 isOffScreen: SpSystemTrace.isCanvasOffScreen 407 }); 408 row.rowId = `${process.pid}-Perf-Process`; 409 row.index = index; 410 row.rowType = TraceRow.ROW_TYPE_HIPERF_PROCESS 411 row.rowParentId = 'HiPerf'; 412 row.rowHidden = !this.rowFolder.expansion 413 row.folder = true; 414 row.name = `${process.processName||'Process'} [${process.pid}]`; 415 row.folderPaddingLeft = 30; 416 row.favoriteChangeHandler = this.trace.favoriteChangeHandler; 417 row.selectChangeHandler = this.trace.selectChangeHandler; 418 let that = this; 419 row.supplier = () => queryHiPerfProcessData(process.pid); 420 row.onThreadHandler = (useCache) => { 421 procedurePool.submitWithName(`process${(row.index) % procedurePool.processLen.length}`, `HiPerf-Process-${row.index}`, { 422 list: row.must ? row.dataList : undefined, 423 offscreen: !row.isTransferCanvas ? row.offscreen[0] : undefined, 424 xs: TraceRow.range?.xs, 425 dpr: row.dpr, 426 isHover: row.isHover, 427 flagMoveInfo: this.trace.hoverFlag, 428 flagSelectedInfo: this.trace.selectFlag, 429 hoverX: row.hoverX, 430 hoverY: row.hoverY, 431 canvasWidth: row.canvasWidth, 432 canvasHeight: row.canvasHeight, 433 hoverStruct: SpHiPerf.hoverProcessStruct, 434 selectStruct: SpHiPerf.selectProcessStruct, 435 isRangeSelect: row.rangeSelect, 436 rangeSelectObject: TraceRow.rangeSelectObject, 437 useCache: useCache, 438 lineColor: row.getLineColor(), 439 startNS: TraceRow.range?.startNS || 0, 440 endNS: TraceRow.range?.endNS || 0, 441 totalNS: TraceRow.range?.totalNS || 0, 442 slicesTime: TraceRow.range?.slicesTime, 443 scale: TraceRow.range?.scale || 50, 444 intervalPerf: SpHiPerf.stringResult?.fValue || 1, 445 range:TraceRow.range, 446 frame: row.frame 447 }, row.getTransferArray(), (res: any, hover: any) => { 448 row.must = false; 449 if (row.isHover) { 450 SpHiPerf.hoverProcessStruct = hover; 451 } 452 }) 453 row.isTransferCanvas = true; 454 } 455 this.trace.rowsEL?.appendChild(row) 456 457 array.forEach((thObj, thIdx) => { 458 let thread = new TraceRow({ 459 canvasNumber: 1, 460 alpha: false, 461 contextId: '2d', 462 isOffScreen: SpSystemTrace.isCanvasOffScreen 463 }); 464 thread.rowId = `${thObj.tid}-Perf-Thread`; 465 thread.index = thIdx; 466 thread.rowType = TraceRow.ROW_TYPE_HIPERF_THREAD 467 thread.rowParentId = row.rowId; 468 thread.rowHidden = !row.expansion 469 thread.folder = false; 470 thread.name = `${thObj.threadName||'Thread'} [${thObj.tid}]`; 471 thread.setAttribute('children', '') 472 thread.folderPaddingLeft = 30; 473 thread.favoriteChangeHandler = this.trace.favoriteChangeHandler; 474 thread.selectChangeHandler = this.trace.selectChangeHandler; 475 let that = this; 476 thread.supplier = () => queryHiPerfThreadData(thObj.tid); 477 thread.onThreadHandler = (useCache) => { 478 procedurePool.submitWithName(`process${(thread.index) % procedurePool.processLen.length}`, `HiPerf-Thread-${row.index}-${thread.index}`, { 479 list: thread.must ? thread.dataList : undefined, 480 offscreen: !thread.isTransferCanvas ? thread.offscreen[0] : undefined, 481 xs: TraceRow.range?.xs, 482 dpr: thread.dpr, 483 isHover: thread.isHover, 484 flagMoveInfo: this.trace.hoverFlag, 485 flagSelectedInfo: this.trace.selectFlag, 486 hoverX: thread.hoverX, 487 hoverY: thread.hoverY, 488 canvasWidth: thread.canvasWidth, 489 canvasHeight: thread.canvasHeight, 490 hoverStruct: SpHiPerf.hoverThreadStruct, 491 selectStruct: SpHiPerf.selectThreadStruct, 492 isRangeSelect: thread.rangeSelect, 493 rangeSelectObject: TraceRow.rangeSelectObject, 494 useCache: useCache, 495 lineColor: thread.getLineColor(), 496 startNS: TraceRow.range?.startNS || 0, 497 endNS: TraceRow.range?.endNS || 0, 498 totalNS: TraceRow.range?.totalNS || 0, 499 slicesTime: TraceRow.range?.slicesTime, 500 scale: TraceRow.range?.scale || 50, 501 intervalPerf: SpHiPerf.stringResult?.fValue || 1, 502 range:TraceRow.range, 503 frame: thread.frame 504 }, thread.getTransferArray(), (res: any, hover: any) => { 505 thread.must = false; 506 if (thread.isHover) { 507 SpHiPerf.hoverThreadStruct = hover; 508 } 509 }) 510 thread.isTransferCanvas = true; 511 } 512 this.trace.rowsEL?.appendChild(thread) 513 }); 514 }) 515 } 516} 517