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