• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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