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