• 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 { info } from '../../../log/Log';
18import { TraceRow } from '../trace/base/TraceRow';
19import { procedurePool } from '../../database/Procedure';
20import { CpuRender, CpuStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCPU';
21import { renders } from '../../database/ui-worker/ProcedureWorker';
22import { Utils } from '../trace/base/Utils';
23import { cpuDataSender } from '../../database/data-trafic/CpuDataSender';
24import { queryCpuCount, queryCpuMax, queryCpuSchedSlice } from '../../database/sql/Cpu.sql';
25
26export class SpCpuChart {
27  private trace: SpSystemTrace;
28
29  constructor(trace: SpSystemTrace) {
30    this.trace = trace;
31  }
32
33  private cpuSupplierFrame(traceRow: TraceRow<CpuStruct>, cpuId: number): void {
34    traceRow.supplierFrame = async (): Promise<CpuStruct[]> => {
35      const res = await cpuDataSender(cpuId, traceRow);
36      const filterList = SpSystemTrace.keyPathList.filter((item) => {
37        return item.cpu === cpuId;
38      });
39      res.push(...filterList);
40      res.forEach((it, i, arr) => {
41        let p = Utils.PROCESS_MAP.get(it.processId!);
42        let t = Utils.THREAD_MAP.get(it.tid!);
43        let slice = Utils.SCHED_SLICE_MAP.get(`${it.id}-${it.startTime}`);
44        if (slice) {
45          it.end_state = slice.endState;
46          it.priority = slice.priority;
47        }
48        it.processName = p;
49        it.processCmdLine = p;
50        it.name = t;
51        it.type = 'thread';
52      });
53      return res;
54    };
55  }
56
57  private cpuThreadHandler(traceRow: TraceRow<CpuStruct>, i1: number): void {
58    traceRow.onThreadHandler = (useCache: boolean, buf: ArrayBuffer | undefined | null): void => {
59      let context: CanvasRenderingContext2D;
60      if (traceRow.currentContext) {
61        context = traceRow.currentContext;
62      } else {
63        context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
64      }
65      traceRow.canvasSave(context);
66      (renders['cpu-data'] as CpuRender).renderMainThread(
67        {
68          ctx: context,
69          useCache: useCache,
70          type: `cpu-data-${i1}`,
71          translateY: traceRow.translateY,
72        },
73        traceRow
74      );
75      traceRow.canvasRestore(context, this.trace);
76    };
77  }
78
79  async init(cpuDataCount?: Map<number, number>): Promise<void> {
80    let CpuStartTime = new Date().getTime();
81    let array = await queryCpuMax();
82    let cpuCountResult = await queryCpuCount();
83    if (cpuCountResult && cpuCountResult.length > 0 && cpuCountResult[0]) {
84      // @ts-ignore
85      (window as unknown).cpuCount = cpuCountResult[0].cpuCount;
86    } else {
87      // @ts-ignore
88      (window as unknown).cpuCount = 0;
89    }
90    let cpuSchedSlice = await queryCpuSchedSlice();
91    this.initSchedSliceData(cpuSchedSlice);
92    info('Cpu trace row data size is: ', array.length);
93    if (array && array.length > 0 && array[0]) {
94      //@ts-ignore
95      let cpuMax = array[0].cpu;
96      CpuStruct.cpuCount = cpuMax + 1;
97      for (let i1 = 0; i1 < CpuStruct.cpuCount; i1++) {
98        if (cpuDataCount && (cpuDataCount.get(i1) || 0) > 0) {
99          const cpuId = i1;
100          let traceRow = TraceRow.skeleton<CpuStruct>();
101          traceRow.rowId = `${cpuId}`;
102          traceRow.rowType = TraceRow.ROW_TYPE_CPU;
103          traceRow.rowParentId = '';
104          traceRow.style.height = '30px';
105          traceRow.name = `Cpu ${cpuId}`;
106          traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
107          traceRow.selectChangeHandler = this.trace.selectChangeHandler;
108          this.cpuSupplierFrame(traceRow, cpuId);
109          traceRow.focusHandler = (): void => {
110            this.trace?.displayTip(
111              traceRow,
112              CpuStruct.hoverCpuStruct,
113              `<span>P:${CpuStruct.hoverCpuStruct?.processName || 'Process'} [${
114                CpuStruct.hoverCpuStruct?.processId
115              }]</span><span>T:${CpuStruct.hoverCpuStruct?.name} [${CpuStruct.hoverCpuStruct?.tid}] [Prio:${
116                CpuStruct.hoverCpuStruct?.priority || 0
117              }]</span>`
118            );
119          };
120          traceRow.findHoverStruct = (): void => {
121            CpuStruct.hoverCpuStruct = traceRow.getHoverStruct();
122          };
123          this.cpuThreadHandler(traceRow, i1);
124          this.trace.rowsEL?.appendChild(traceRow);
125        }
126      }
127    }
128    let CpuDurTime = new Date().getTime() - CpuStartTime;
129    info('The time to load the Cpu data is: ', CpuDurTime);
130  }
131
132  initProcessThreadStateData = async (progress: Function): Promise<void> => {
133    let time = new Date().getTime();
134    progress('StateProcessThread', 93);
135    procedurePool.submitWithName('logic0', 'spt-init', {}, undefined, (res: unknown) => {});
136    let durTime = new Date().getTime() - time;
137    info('The time to load the first ProcessThreadState data is: ', durTime);
138  };
139
140  initCpuIdle0Data = async (progress: Function): Promise<void> => {
141    let time = new Date().getTime();
142    progress('CPU Idle', 94);
143    procedurePool.submitWithName(
144      'logic0',
145      'scheduling-getCpuIdle0',
146      {
147        // @ts-ignore
148        endTs: (window as unknown).recordEndNS, // @ts-ignore
149        total: (window as unknown).totalNS,
150      },
151      undefined,
152      (res: unknown) => {}
153    );
154    let durTime = new Date().getTime() - time;
155    info('The time to load the first CPU Idle0 data is: ', durTime);
156  };
157
158  initSchedSliceData(arr: unknown[]): void {
159    Utils.SCHED_SLICE_MAP.clear();
160    arr.forEach((value) => {
161      // @ts-ignore
162      Utils.SCHED_SLICE_MAP.set(`${value.itid}-${value.ts}`, { endState: value.endState, priority: value.priority });
163    });
164  }
165
166  initSchedulingPTData = async (progress: Function): Promise<void> => {
167    let time = new Date().getTime();
168    progress('CPU Idle', 94);
169    procedurePool.submitWithName('logic0', 'scheduling-getProcessAndThread', {}, undefined, (res: unknown) => {});
170    let durTime = new Date().getTime() - time;
171    info('The time to load the first CPU Idle0 data is: ', durTime);
172  };
173
174  initSchedulingFreqData = async (progress: Function): Promise<void> => {
175    let time = new Date().getTime();
176    progress('CPU Scheduling Freq', 94);
177    procedurePool.submitWithName('logic0', 'scheduling-initFreqData', {}, undefined, (res: unknown) => {});
178    let durTime = new Date().getTime() - time;
179    info('The time to load the first CPU Idle0 data is: ', durTime);
180  };
181}
182