• 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 { 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