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