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