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