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'; 17import { SpHiPerf } from './SpHiPerf'; 18import { SpCpuChart } from './SpCpuChart'; 19import { SpFreqChart } from './SpFreqChart'; 20import { SpFpsChart } from './SpFpsChart'; 21import { info } from '../../../log/Log'; 22import { SpNativeMemoryChart } from './SpNativeMemoryChart'; 23import { SpAbilityMonitorChart } from './SpAbilityMonitorChart'; 24import { SpProcessChart } from './SpProcessChart'; 25import { perfDataQuery } from './PerfDataQuery'; 26import { SpVirtualMemChart } from './SpVirtualMemChart'; 27import { SpEBPFChart } from './SpEBPFChart'; 28import { SpSdkChart } from './SpSdkChart'; 29import { SpHiSysEnergyChart } from './SpHiSysEnergyChart'; 30import { VmTrackerChart } from './SpVmTrackerChart'; 31import { SpClockChart } from './SpClockChart'; 32import { SpXpowerChart } from './SpXpowerChart'; 33import { SpIrqChart } from './SpIrqChart'; 34import { renders } from '../../database/ui-worker/ProcedureWorker'; 35import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; 36import { TraceRow } from '../trace/base/TraceRow'; 37import { SpFrameTimeChart } from './SpFrameTimeChart'; 38import { Utils } from '../trace/base/Utils'; 39import { SpArkTsChart } from './SpArkTsChart'; 40import { MemoryConfig } from '../../bean/MemoryConfig'; 41import { FlagsConfig } from '../SpFlags'; 42import { SpLogChart } from './SpLogChart'; 43import { SpHiSysEventChart } from './SpHiSysEventChart'; 44import { SpAllAppStartupsChart } from './SpAllAppStartups'; 45import { procedurePool } from '../../database/Procedure'; 46import { SpSegmentationChart } from './SpSegmentationChart'; 47import { SpHangChart } from './SpHangChart'; 48import { SpPerfOutputDataChart } from './SpPerfOutputDataChart'; 49import { 50 queryAppStartupProcessIds, 51 queryDataDICT, 52 queryThreadAndProcessName, 53} from '../../database/sql/ProcessThread.sql'; 54import { queryTaskPoolCallStack, queryTotalTime } from '../../database/sql/SqlLite.sql'; 55import { queryMemoryConfig } from '../../database/sql/Memory.sql'; 56import { SpLtpoChart } from './SpLTPO'; 57import { SpBpftraceChart } from './SpBpftraceChart'; 58import { sliceSender } from '../../database/data-trafic/SliceSender'; 59import { BaseStruct } from '../../bean/BaseStruct'; 60import { SpGpuCounterChart } from './SpGpuCounterChart'; 61import { SpUserFileChart } from './SpUserPluginChart'; 62import { SpImportUserPluginsChart } from './SpImportUserPluginsChart'; 63import { queryDmaFenceIdAndCat } from '../../database/sql/dmaFence.sql'; 64import { queryAllFuncNames } from '../../database/sql/Func.sql'; 65import {SpSnapShotChart} from './spSnapShotChart'; 66import { SpRecordTrace } from '../SpRecordTrace'; 67 68export class SpChartManager { 69 static APP_STARTUP_PID_ARR: Array<number> = []; 70 71 private trace: SpSystemTrace; 72 public perf: SpHiPerf; 73 private cpu: SpCpuChart; 74 private freq: SpFreqChart; 75 private virtualMemChart: SpVirtualMemChart; 76 private fps: SpFpsChart; 77 private nativeMemory: SpNativeMemoryChart; 78 private abilityMonitor: SpAbilityMonitorChart; 79 private process: SpProcessChart; 80 private process2?: SpProcessChart; 81 private fileSystem: SpEBPFChart; 82 private sdkChart: SpSdkChart; 83 private hiSyseventChart: SpHiSysEnergyChart; 84 private smapsChart: VmTrackerChart; 85 private clockChart: SpClockChart; 86 private xpowerChart: SpXpowerChart; 87 private irqChart: SpIrqChart; 88 private spAllAppStartupsChart!: SpAllAppStartupsChart; 89 private SpLtpoChart!: SpLtpoChart; 90 frameTimeChart: SpFrameTimeChart; 91 public arkTsChart: SpArkTsChart; 92 private logChart: SpLogChart; 93 private spHiSysEvent: SpHiSysEventChart; 94 private spSegmentationChart: SpSegmentationChart; 95 private hangChart: SpHangChart; 96 private spBpftraceChart: SpBpftraceChart; 97 private spPerfOutputDataChart: SpPerfOutputDataChart; 98 private spGpuCounterChart: SpGpuCounterChart; 99 private spUserFileChart: SpUserFileChart; 100 private spImportUserPluginsChart: SpImportUserPluginsChart; 101 private spSnapShotChart: SpSnapShotChart; 102 103 constructor(trace: SpSystemTrace) { 104 this.trace = trace; 105 this.perf = new SpHiPerf(trace); 106 this.fileSystem = new SpEBPFChart(trace); 107 this.cpu = new SpCpuChart(trace); 108 this.freq = new SpFreqChart(trace); 109 this.virtualMemChart = new SpVirtualMemChart(trace); 110 this.fps = new SpFpsChart(trace); 111 this.nativeMemory = new SpNativeMemoryChart(trace); 112 this.abilityMonitor = new SpAbilityMonitorChart(trace); 113 this.process = new SpProcessChart(trace); 114 this.sdkChart = new SpSdkChart(trace); 115 this.hiSyseventChart = new SpHiSysEnergyChart(trace); 116 this.smapsChart = new VmTrackerChart(trace); 117 this.clockChart = new SpClockChart(trace); 118 this.irqChart = new SpIrqChart(trace); 119 this.frameTimeChart = new SpFrameTimeChart(trace); 120 this.arkTsChart = new SpArkTsChart(trace); 121 this.logChart = new SpLogChart(trace); 122 this.spHiSysEvent = new SpHiSysEventChart(trace); 123 this.spAllAppStartupsChart = new SpAllAppStartupsChart(trace); 124 this.SpLtpoChart = new SpLtpoChart(trace); 125 this.spSegmentationChart = new SpSegmentationChart(trace); 126 this.hangChart = new SpHangChart(trace); 127 this.spBpftraceChart = new SpBpftraceChart(trace); 128 this.spPerfOutputDataChart = new SpPerfOutputDataChart(trace); 129 this.spGpuCounterChart = new SpGpuCounterChart(trace); 130 this.spUserFileChart = new SpUserFileChart(trace); 131 this.spImportUserPluginsChart = new SpImportUserPluginsChart(trace); 132 this.xpowerChart = new SpXpowerChart(trace); 133 this.spSnapShotChart = new SpSnapShotChart(trace); 134 } 135 async initPreprocessData(progress: Function): Promise<void> { 136 progress('load data dict', 50); 137 this.process2 = undefined; 138 SpSystemTrace.DATA_DICT.clear(); 139 SpChartManager.APP_STARTUP_PID_ARR = []; 140 let dict = await queryDataDICT(); 141 if (FlagsConfig.getFlagsConfigEnableStatus('AppStartup')) { 142 let appStartUpPids = await queryAppStartupProcessIds(); 143 appStartUpPids.forEach((it) => SpChartManager.APP_STARTUP_PID_ARR.push(it.pid)); 144 } 145 await this.initTraceConfig(); //@ts-ignore 146 dict.map((d) => SpSystemTrace.DATA_DICT.set(d.id, d.data)); 147 await this.cacheDataDictToWorker(); 148 SpSystemTrace.DATA_TASK_POOL_CALLSTACK.clear(); 149 let taskPoolCallStack = await queryTaskPoolCallStack(); 150 taskPoolCallStack.map((d) => SpSystemTrace.DATA_TASK_POOL_CALLSTACK.set(d.id, d)); 151 progress('time range', 65); 152 await this.initTotalTime(); 153 let ptArr = await queryThreadAndProcessName(); //@ts-ignore 154 this.handleProcessThread(ptArr); 155 info('initData timerShaftEL Data initialized'); 156 let funArr = await queryAllFuncNames(); 157 this.handleFuncName(funArr); 158 } 159 160 async initCpu(progress: Function): Promise<void> { 161 progress('cpu', 70); 162 let result = await sliceSender(); 163 // @ts-ignore 164 SpProcessChart.threadStateList = result.threadMap; 165 // @ts-ignore 166 SpProcessChart.processRowSortMap = result.processRowSortMap; 167 //@ts-ignore 168 await this.cpu.init(result.count.cpu); 169 info('initData cpu Data initialized'); 170 if (FlagsConfig.getFlagsConfigEnableStatus('Bpftrace')) { 171 await this.spBpftraceChart.init(null); 172 } 173 if (FlagsConfig.getFlagsConfigEnableStatus('UserPluginsRow')) { 174 await this.spUserFileChart.init(null) 175 } 176 if (FlagsConfig.getFlagsConfigEnableStatus('GpuCounter')) { 177 await this.spGpuCounterChart.init([]); 178 } 179 if (FlagsConfig.getFlagsConfigEnableStatus('SchedulingAnalysis')) { 180 await this.cpu.initCpuIdle0Data(progress); 181 await this.cpu.initSchedulingPTData(progress); 182 await this.cpu.initSchedulingFreqData(progress); 183 } 184 info('initData ProcessThreadState Data initialized'); 185 progress('cpu rate', 75); 186 //@ts-ignore 187 await this.initCpuRate(result.cpuUtiliRateArray); 188 info('initData Cpu Rate Data initialized'); 189 progress('cpu freq', 80); 190 await this.freq.init(); 191 info('initData Cpu Freq Data initialized'); 192 } 193 194 async init(progress: Function): Promise<void> { 195 info('initData data parse end '); 196 await this.initPreprocessData(progress); 197 await this.initCpu(progress); 198 await this.logChart.init(); 199 await this.spHiSysEvent.init(); 200 if (SpRecordTrace.snapShotList.length > 0) { 201 await this.spSnapShotChart.init(); 202 } 203 let idAndNameArr = await queryDmaFenceIdAndCat(); 204 this.handleDmaFenceName(idAndNameArr as { id: number; cat: string; seqno: number; driver: string; context: string }[]); 205 if (FlagsConfig.getFlagsConfigEnableStatus('Hangs Detection')) { 206 progress('Hang init', 80); 207 await this.hangChart.init(); 208 } 209 progress('Clock init', 82); 210 await this.clockChart.init(); 211 progress('Xpower init', 83); 212 await this.xpowerChart.init(); 213 progress('Irq init', 84); 214 await this.irqChart.init(); 215 progress('SpSegmentationChart inin', 84.5); 216 await this.spSegmentationChart.init(); 217 await this.virtualMemChart.init(); 218 progress('fps', 85); 219 await this.fps.init(); 220 progress('native memory', 87); 221 await this.nativeMemory.initChart(); 222 progress('ability monitor', 88); 223 await this.abilityMonitor.init(); 224 progress('hiSysevent', 88.2); 225 await this.hiSyseventChart.init(); 226 progress('vm tracker', 88.4); 227 await this.smapsChart.init(); 228 progress('sdk', 88.6); 229 await this.sdkChart.init(); 230 progress('perf', 88.8); 231 await this.perf!.init(); 232 await perfDataQuery.initPerfCache(); 233 progress('file system', 89); 234 await this.fileSystem!.init(); 235 progress('ark ts', 90); 236 await this.arkTsChart.initFolder(); 237 await this.spAllAppStartupsChart.init(); 238 await this.SpLtpoChart.init(); 239 await this.frameTimeChart.init(); 240 await this.spPerfOutputDataChart.init(); 241 progress('process', 92); 242 this.process.clearCache(); 243 this.process2?.clearCache(); 244 this.process2 = undefined; 245 await this.process.initAsyncFuncData({ 246 startTs: Utils.getInstance().getRecordStartNS(), 247 endTs: Utils.getInstance().getRecordEndNS(), 248 }); 249 await this.process.initDeliverInputEvent(); 250 await this.process.initTouchEventDispatch(); 251 await this.process.init(false); 252 progress('display', 95); 253 } 254 255 async initDistributedChart(progress: Function, file1: string, file2: string): Promise<void> { 256 let funArr1 = await queryAllFuncNames('1'); 257 let funArr2 = await queryAllFuncNames('2'); 258 this.handleFuncName(funArr1, '1'); 259 this.handleFuncName(funArr2, '2'); 260 progress('load data dict', 50); 261 SpSystemTrace.DATA_DICT.clear(); 262 SpChartManager.APP_STARTUP_PID_ARR = []; 263 SpSystemTrace.DATA_TASK_POOL_CALLSTACK.clear(); 264 this.process.clearCache(); 265 this.process2?.clearCache(); 266 let trace1Folder = this.createFolderRow('trace-1', 'trace-1', file1); 267 let trace2Folder = this.createFolderRow('trace-2', 'trace-2', file2); 268 this.trace.rowsEL!.appendChild(trace1Folder); 269 this.trace.rowsEL!.appendChild(trace2Folder); 270 await this.initTotalTime(true); 271 await this.initDistributedTraceRow('1', trace1Folder, progress); 272 info(`trace 1 load completed`); 273 await this.initDistributedTraceRow('2', trace2Folder, progress); 274 info(`trace 2 load completed`); 275 } 276 277 // @ts-ignore 278 async initDistributedTraceRow(traceId: string, traceFolder: TraceRow<unknown>, progress: Function): Promise<void> { 279 let ptArr = await queryThreadAndProcessName(traceId); 280 // @ts-ignore 281 this.handleProcessThread(ptArr, traceId); 282 info(`initData trace ${traceId} timerShaftEL Data initialized`); 283 progress(`trace ${traceId} cpu`, 70); 284 let count = await sliceSender(traceId); 285 // @ts-ignore 286 await this.cpu.init(count.count.cpu, traceFolder, traceId); 287 info(`initData trace ${traceId} cpu Data initialized`); 288 progress(`trace ${traceId} cpu freq`, 75); 289 // @ts-ignore 290 await this.freq.init(traceFolder, traceId); 291 info(`initData trace ${traceId} cpu freq Data initialized`); 292 progress(`trace ${traceId} clock`, 80); 293 // @ts-ignore 294 await this.clockChart.init(traceFolder, traceId); 295 info(`initData trace ${traceId} clock Data initialized`); 296 progress(`trace ${traceId} Irq`, 85); 297 // @ts-ignore 298 await this.irqChart.init(traceFolder, traceId); 299 info(`initData trace ${traceId} irq Data initialized`); 300 progress(`trace ${traceId} process`, 92); 301 if (traceId === '2') { 302 if (!this.process2) { 303 this.process2 = new SpProcessChart(this.trace); 304 } 305 await this.process2.initAsyncFuncData( 306 { 307 startTs: Utils.getInstance().getRecordStartNS('2'), 308 endTs: Utils.getInstance().getRecordEndNS('2'), 309 }, 310 traceId 311 ); 312 await this.process2.init(true, traceFolder, traceId); 313 } else { 314 await this.process.initAsyncFuncData( 315 { 316 startTs: Utils.getInstance().getRecordStartNS('1'), 317 endTs: Utils.getInstance().getRecordEndNS('1'), 318 }, 319 traceId 320 ); 321 await this.process.init(true, traceFolder, traceId); 322 } 323 } 324 325 async initSample(ev: File) { 326 await this.initSampleTime(ev, 'bpftrace'); 327 await this.spBpftraceChart.init(ev); 328 } 329 330 async initGpuCounter(ev: File): Promise<void> { 331 const res = await this.initSampleTime(ev, 'gpucounter'); 332 //@ts-ignore 333 await this.spGpuCounterChart.init(res); 334 } 335 336 async importSoFileUpdate(): Promise<void> { 337 SpSystemTrace.DATA_DICT.clear(); 338 let dict = await queryDataDICT(); //@ts-ignore 339 dict.map((d) => SpSystemTrace.DATA_DICT.set(d.id, d.data)); 340 await this.cacheDataDictToWorker(); 341 await perfDataQuery.initPerfCache(); 342 await this.nativeMemory.initNativeMemory(); 343 await this.fileSystem.initFileCallchain(); 344 this.perf.resetAllChartData(); 345 } 346 347 handleProcessThread(arr: { id: number; name: string; type: string }[], traceId?: string): void { 348 Utils.getInstance().getProcessMap(traceId).clear(); 349 Utils.getInstance().getThreadMap(traceId).clear(); 350 for (let pt of arr) { 351 if (pt.type === 'p') { 352 Utils.getInstance().getProcessMap(traceId).set(pt.id, pt.name); 353 } else { 354 Utils.getInstance().getThreadMap(traceId).set(pt.id, pt.name); 355 } 356 } 357 } 358 359 // 将callstatck表信息转为map存入utils 360 handleFuncName(funcNameArray: Array<unknown>, traceId?: string): void { 361 if (traceId) { 362 funcNameArray.forEach((it) => { 363 //@ts-ignore 364 Utils.getInstance().getCallStatckMap().set(`${traceId}_${it.id!}`, it.name); 365 //@ts-ignore 366 Utils.getInstance().getCallStatckMap().set(it.name, it.colorIndex); 367 }); 368 } else { 369 funcNameArray.forEach((it) => { 370 //@ts-ignore 371 Utils.getInstance().getCallStatckMap().set(it.id, it.name); 372 //@ts-ignore 373 Utils.getInstance().getCallStatckMap().set(it.name, it.colorIndex); 374 }); 375 } 376 } 377 378 initTotalTime = async (isDistributed: boolean = false): Promise<void> => { 379 let res1 = await queryTotalTime('1'); 380 let total = res1[0].total; 381 Utils.getInstance().trace1RecordStartNS = res1[0].recordStartNS; 382 Utils.getInstance().trace1RecordEndNS = Math.max(res1[0].recordEndNS, res1[0].recordStartNS + 1); 383 if (isDistributed) { 384 let res2 = await queryTotalTime('2'); 385 total = Math.max(total, res2[0].total); 386 Utils.getInstance().trace2RecordStartNS = res2[0].recordStartNS; 387 Utils.getInstance().trace2RecordEndNS = Math.max(res2[0].recordEndNS, res2[0].recordStartNS + 1); 388 } 389 if (this.trace.timerShaftEL) { 390 if (total === 0) { 391 total = 1; 392 } 393 Utils.getInstance().totalNS = total; 394 this.trace.timerShaftEL.totalNS = total; 395 this.trace.timerShaftEL.getRangeRuler()!.drawMark = true; 396 this.trace.timerShaftEL.setRangeNS(0, total); 397 window.recordStartNS = Utils.getInstance().trace1RecordStartNS; 398 window.recordEndNS = Utils.getInstance().trace1RecordEndNS; 399 window.totalNS = total; 400 this.trace.timerShaftEL.loadComplete = true; 401 } 402 }; 403 404 initSampleTime = async (ev: File, type: string): Promise<unknown> => { 405 let res; 406 let endNS = 30_000_000_000; 407 if (type === 'gpucounter') { 408 res = await this.spGpuCounterChart.getCsvData(ev); 409 // @ts-ignore 410 const endTime = Number(res[res.length - 1].split(',')[0]); 411 // @ts-ignore 412 const minIndex = this.spGpuCounterChart.getMinData(res) + 1; 413 // @ts-ignore 414 const startTime = Number(res[minIndex].split(',')[0]); 415 endNS = Number((endTime - startTime).toString().slice(0, 11)); 416 } 417 if (this.trace.timerShaftEL) { 418 let total = endNS; 419 let startNS = 0; 420 this.trace.timerShaftEL.totalNS = total; 421 this.trace.timerShaftEL.getRangeRuler()!.drawMark = true; 422 this.trace.timerShaftEL.setRangeNS(0, total); // @ts-ignore 423 (window as unknown).recordStartNS = startNS; // @ts-ignore 424 (window as unknown).recordEndNS = endNS; // @ts-ignore 425 (window as unknown).totalNS = total; 426 this.trace.timerShaftEL.loadComplete = true; 427 } 428 return res; 429 }; 430 431 initCpuRate = async (rates: Array<{ cpu: number; ro: number; rate: number; }>): Promise<void> => { 432 if (this.trace.timerShaftEL) { 433 this.trace.timerShaftEL.cpuUsage = rates; 434 } 435 info('Cpu UtilizationRate data size is: ', rates.length); 436 }; 437 438 initTraceConfig = async (): Promise<void> => { 439 queryMemoryConfig().then((result) => { 440 if (result && result.length > 0) { 441 const config = result[0]; 442 MemoryConfig.getInstance().updateConfig(config.pid, config.iPid, config.processName, config.interval); 443 } 444 }); 445 }; 446 447 async cacheDataDictToWorker(): Promise<void> { 448 return new Promise((resolve) => { 449 procedurePool.submitWithName( 450 'logic0', 451 'cache-data-dict', 452 { dataDict: SpSystemTrace.DATA_DICT }, 453 undefined, 454 (res: unknown): void => { 455 resolve(); 456 } 457 ); 458 }); 459 } 460 461 // @ts-ignore 462 createFolderRow(rowId: string, rowType: string, rowName: string, traceId?: string): TraceRow<unknown> { 463 let row = TraceRow.skeleton<BaseStruct>(traceId); 464 row.setAttribute('disabled-check', ''); 465 row.rowId = rowId; 466 row.rowType = rowType; 467 row.rowParentId = ''; 468 row.folder = true; 469 row.style.height = '40px'; 470 row.name = rowName; 471 // @ts-ignore 472 row.supplier = folderSupplier(); 473 row.onThreadHandler = folderThreadHandler(row, this.trace); 474 row.addEventListener('expansion-change', (evt) => { 475 if (!row.expansion) { 476 this.trace.clickEmptyArea(); 477 } 478 }); 479 return row; 480 } 481 482 //存名字 483 handleDmaFenceName<T extends { id: number; cat: string; seqno: number; driver: string; context: string }>(arr: T[]): void { 484 Utils.DMAFENCECAT_MAP.clear(); 485 for (let item of arr) { 486 Utils.DMAFENCECAT_MAP.set(item.id, item); 487 } 488 } 489} 490 491export const folderSupplier = (): () => Promise<BaseStruct[]> => { 492 return () => new Promise<Array<BaseStruct>>((resolve) => resolve([])); 493}; 494 495export const folderThreadHandler = (row: TraceRow<BaseStruct>, trace: SpSystemTrace) => { 496 return (useCache: boolean): void => { 497 row.canvasSave(trace.canvasPanelCtx!); 498 if (row.expansion) { 499 // @ts-ignore 500 trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); 501 } else { 502 (renders.empty as EmptyRender).renderMainThread( 503 { 504 context: trace.canvasPanelCtx, 505 useCache: useCache, 506 type: '', 507 }, 508 row 509 ); 510 } 511 row.canvasRestore(trace.canvasPanelCtx!, trace); 512 }; 513}; 514 515export function rowThreadHandler<T>( 516 tag: string, 517 contextField: string, 518 arg: unknown, // @ts-ignore 519 row: TraceRow<unknown>, 520 trace: SpSystemTrace 521) { 522 return (useCache: boolean): void => { 523 let context: CanvasRenderingContext2D = getRowContext(row, trace); 524 row.canvasSave(context); // @ts-ignore 525 arg.useCache = useCache; 526 if (contextField) { 527 // @ts-ignore 528 arg[contextField] = context; 529 } // @ts-ignore 530 (renders[tag] as unknown).renderMainThread(arg, row); 531 row.canvasRestore(context, trace); 532 }; 533} 534// @ts-ignore 535export const getRowContext = (row: TraceRow<unknown>, trace: SpSystemTrace): CanvasRenderingContext2D => { 536 if (row.currentContext) { 537 return row.currentContext; 538 } else { 539 return row.collect ? trace.canvasFavoritePanelCtx! : trace.canvasPanelCtx!; 540 } 541}; 542