1fb726d48Sopenharmony_ci/*
2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb726d48Sopenharmony_ci * You may obtain a copy of the License at
6fb726d48Sopenharmony_ci *
7fb726d48Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb726d48Sopenharmony_ci *
9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and
13fb726d48Sopenharmony_ci * limitations under the License.
14fb726d48Sopenharmony_ci */
15fb726d48Sopenharmony_ci
16fb726d48Sopenharmony_ciimport { SpSystemTrace } from '../SpSystemTrace';
17fb726d48Sopenharmony_ciimport { info } from '../../../log/Log';
18fb726d48Sopenharmony_ciimport { TraceRow } from '../trace/base/TraceRow';
19fb726d48Sopenharmony_ciimport { procedurePool } from '../../database/Procedure';
20fb726d48Sopenharmony_ciimport { CpuRender, CpuStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCPU';
21fb726d48Sopenharmony_ciimport { renders } from '../../database/ui-worker/ProcedureWorker';
22fb726d48Sopenharmony_ciimport { Utils } from '../trace/base/Utils';
23fb726d48Sopenharmony_ciimport { cpuDataSender } from '../../database/data-trafic/CpuDataSender';
24fb726d48Sopenharmony_ciimport { queryCpuCount, queryCpuMax, queryCpuSchedSlice } from '../../database/sql/Cpu.sql';
25fb726d48Sopenharmony_ciimport { rowThreadHandler } from './SpChartManager';
26fb726d48Sopenharmony_ciimport { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil';
27fb726d48Sopenharmony_ci
28fb726d48Sopenharmony_ciexport class SpCpuChart {
29fb726d48Sopenharmony_ci  private trace: SpSystemTrace;
30fb726d48Sopenharmony_ci
31fb726d48Sopenharmony_ci  constructor(trace: SpSystemTrace) {
32fb726d48Sopenharmony_ci    this.trace = trace;
33fb726d48Sopenharmony_ci  }
34fb726d48Sopenharmony_ci
35fb726d48Sopenharmony_ci  private cpuSupplierFrame(traceRow: TraceRow<CpuStruct>, cpuId: number): void {
36fb726d48Sopenharmony_ci    traceRow.supplierFrame = async (): Promise<CpuStruct[]> => {
37fb726d48Sopenharmony_ci      const res = await cpuDataSender(cpuId, traceRow);
38fb726d48Sopenharmony_ci      const filterList = SpSystemTrace.keyPathList.filter((item) => {
39fb726d48Sopenharmony_ci        return item.cpu === cpuId;
40fb726d48Sopenharmony_ci      });
41fb726d48Sopenharmony_ci      res.push(...filterList);
42fb726d48Sopenharmony_ci      res.forEach((it, i, arr) => {
43fb726d48Sopenharmony_ci        let p = Utils.getInstance().getProcessMap().get(it.processId!);
44fb726d48Sopenharmony_ci        let t = Utils.getInstance().getThreadMap().get(it.tid!);
45fb726d48Sopenharmony_ci        let slice = Utils.getInstance().getSchedSliceMap().get(`${it.id}-${it.startTime}`);
46fb726d48Sopenharmony_ci        if (slice) {
47fb726d48Sopenharmony_ci          it.end_state = slice.endState;
48fb726d48Sopenharmony_ci          it.priority = slice.priority;
49fb726d48Sopenharmony_ci        }
50fb726d48Sopenharmony_ci        it.processName = p;
51fb726d48Sopenharmony_ci        it.processCmdLine = p;
52fb726d48Sopenharmony_ci        it.name = t;
53fb726d48Sopenharmony_ci        it.type = 'thread';
54fb726d48Sopenharmony_ci      });
55fb726d48Sopenharmony_ci      return res;
56fb726d48Sopenharmony_ci    };
57fb726d48Sopenharmony_ci  }
58fb726d48Sopenharmony_ci
59fb726d48Sopenharmony_ci  private cpuThreadHandler(traceRow: TraceRow<CpuStruct>, i1: number): void {
60fb726d48Sopenharmony_ci    traceRow.onThreadHandler = (useCache: boolean, buf: ArrayBuffer | undefined | null): void => {
61fb726d48Sopenharmony_ci      let context: CanvasRenderingContext2D;
62fb726d48Sopenharmony_ci      if (traceRow.currentContext) {
63fb726d48Sopenharmony_ci        context = traceRow.currentContext;
64fb726d48Sopenharmony_ci      } else {
65fb726d48Sopenharmony_ci        context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
66fb726d48Sopenharmony_ci      }
67fb726d48Sopenharmony_ci      traceRow.canvasSave(context);
68fb726d48Sopenharmony_ci      (renders['cpu-data'] as CpuRender).renderMainThread(
69fb726d48Sopenharmony_ci        {
70fb726d48Sopenharmony_ci          ctx: context,
71fb726d48Sopenharmony_ci          useCache: useCache,
72fb726d48Sopenharmony_ci          type: `cpu-data-${i1}`,
73fb726d48Sopenharmony_ci          translateY: traceRow.translateY,
74fb726d48Sopenharmony_ci        },
75fb726d48Sopenharmony_ci        traceRow
76fb726d48Sopenharmony_ci      );
77fb726d48Sopenharmony_ci      traceRow.canvasRestore(context, this.trace);
78fb726d48Sopenharmony_ci    };
79fb726d48Sopenharmony_ci  }
80fb726d48Sopenharmony_ci
81fb726d48Sopenharmony_ci  // @ts-ignore
82fb726d48Sopenharmony_ci  async init(cpuDataCount?: Map<number, number>, parentRow?: TraceRow<unknown>, traceId?: string): Promise<void> {
83fb726d48Sopenharmony_ci    let CpuStartTime = new Date().getTime();
84fb726d48Sopenharmony_ci    let array = await queryCpuMax(traceId);
85fb726d48Sopenharmony_ci    let cpuCountResult = await queryCpuCount(traceId);
86fb726d48Sopenharmony_ci    if (cpuCountResult && cpuCountResult.length > 0 && cpuCountResult[0]) {
87fb726d48Sopenharmony_ci      // @ts-ignore
88fb726d48Sopenharmony_ci      Utils.getInstance().setWinCpuCount(cpuCountResult[0].cpuCount, traceId);
89fb726d48Sopenharmony_ci    } else {
90fb726d48Sopenharmony_ci      Utils.getInstance().setWinCpuCount(0, traceId);
91fb726d48Sopenharmony_ci    }
92fb726d48Sopenharmony_ci    let cpuSchedSlice = await queryCpuSchedSlice(traceId);
93fb726d48Sopenharmony_ci    this.initSchedSliceData(cpuSchedSlice, traceId);
94fb726d48Sopenharmony_ci    info('Cpu trace row data size is: ', array.length);
95fb726d48Sopenharmony_ci    if (array && array.length > 0 && array[0]) {
96fb726d48Sopenharmony_ci      // 有cpu泳道,统计ftrace插件,cpu插件
97fb726d48Sopenharmony_ci      let requestBody = {
98fb726d48Sopenharmony_ci        eventData: {
99fb726d48Sopenharmony_ci          plugin: ['ftrace-plugin', 'cpu-plugin']
100fb726d48Sopenharmony_ci        }
101fb726d48Sopenharmony_ci      };
102fb726d48Sopenharmony_ci      SpStatisticsHttpUtil.recordPluginUsage(requestBody);
103fb726d48Sopenharmony_ci      //@ts-ignore
104fb726d48Sopenharmony_ci      let cpuMax = array[0].cpu + 1;
105fb726d48Sopenharmony_ci      Utils.getInstance().setCpuCount(cpuMax, traceId);
106fb726d48Sopenharmony_ci      for (let i1 = 0; i1 < cpuMax; i1++) {
107fb726d48Sopenharmony_ci        if (cpuDataCount && (cpuDataCount.get(i1) || 0) > 0) {
108fb726d48Sopenharmony_ci          let traceRow = this.createCpuRow(i1, traceId);
109fb726d48Sopenharmony_ci          if (parentRow) {
110fb726d48Sopenharmony_ci            parentRow.addChildTraceRow(traceRow);
111fb726d48Sopenharmony_ci          } else {
112fb726d48Sopenharmony_ci            this.trace.rowsEL?.appendChild(traceRow);
113fb726d48Sopenharmony_ci          }
114fb726d48Sopenharmony_ci        }
115fb726d48Sopenharmony_ci      }
116fb726d48Sopenharmony_ci    }
117fb726d48Sopenharmony_ci    let CpuDurTime = new Date().getTime() - CpuStartTime;
118fb726d48Sopenharmony_ci    info('The time to load the Cpu data is: ', CpuDurTime);
119fb726d48Sopenharmony_ci  }
120fb726d48Sopenharmony_ci
121fb726d48Sopenharmony_ci  createCpuRow(cpuId: number, traceId?: string): TraceRow<CpuStruct> {
122fb726d48Sopenharmony_ci    let traceRow = TraceRow.skeleton<CpuStruct>(traceId);
123fb726d48Sopenharmony_ci    traceRow.rowId = `${cpuId}`;
124fb726d48Sopenharmony_ci    traceRow.rowType = TraceRow.ROW_TYPE_CPU;
125fb726d48Sopenharmony_ci    traceRow.rowParentId = '';
126fb726d48Sopenharmony_ci    traceRow.style.height = '30px';
127fb726d48Sopenharmony_ci    traceRow.name = `Cpu ${cpuId}`;
128fb726d48Sopenharmony_ci    traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
129fb726d48Sopenharmony_ci    traceRow.selectChangeHandler = this.trace.selectChangeHandler;
130fb726d48Sopenharmony_ci    traceRow.supplierFrame = async (): Promise<CpuStruct[]> => {
131fb726d48Sopenharmony_ci      let res = await cpuDataSender(cpuId, traceRow, traceId);
132fb726d48Sopenharmony_ci      const filterList = SpSystemTrace.keyPathList.filter((item): boolean => {
133fb726d48Sopenharmony_ci        return item.cpu === cpuId;
134fb726d48Sopenharmony_ci      });
135fb726d48Sopenharmony_ci      res.push(...filterList);
136fb726d48Sopenharmony_ci      res.forEach((it, i, arr): void => {
137fb726d48Sopenharmony_ci        let p = Utils.getInstance().getProcessMap(traceId).get(it.processId!);
138fb726d48Sopenharmony_ci        let t = Utils.getInstance().getThreadMap(traceId).get(it.tid!);
139fb726d48Sopenharmony_ci        let slice = Utils.getInstance().getSchedSliceMap(traceId).get(`${it.id}-${it.startTime}`);
140fb726d48Sopenharmony_ci        if (slice) {
141fb726d48Sopenharmony_ci          it.end_state = slice.endState;
142fb726d48Sopenharmony_ci          it.priority = slice.priority;
143fb726d48Sopenharmony_ci        }
144fb726d48Sopenharmony_ci        it.processName = p;
145fb726d48Sopenharmony_ci        it.processCmdLine = p;
146fb726d48Sopenharmony_ci        it.name = t;
147fb726d48Sopenharmony_ci        it.type = 'thread';
148fb726d48Sopenharmony_ci      });
149fb726d48Sopenharmony_ci      return res;
150fb726d48Sopenharmony_ci    };
151fb726d48Sopenharmony_ci    traceRow.focusHandler = (): void => {
152fb726d48Sopenharmony_ci      this.trace?.displayTip(
153fb726d48Sopenharmony_ci        traceRow,
154fb726d48Sopenharmony_ci        CpuStruct.hoverCpuStruct,
155fb726d48Sopenharmony_ci        `<span>P:${CpuStruct.hoverCpuStruct?.processName || 'Process'} [${CpuStruct.hoverCpuStruct?.processId
156fb726d48Sopenharmony_ci        }]</span><span>T:${CpuStruct.hoverCpuStruct?.name} [${CpuStruct.hoverCpuStruct?.tid}] [Prio:${CpuStruct.hoverCpuStruct?.priority || 0
157fb726d48Sopenharmony_ci        }]</span>`
158fb726d48Sopenharmony_ci      );
159fb726d48Sopenharmony_ci    };
160fb726d48Sopenharmony_ci    traceRow.findHoverStruct = (): void => {
161fb726d48Sopenharmony_ci      CpuStruct.hoverCpuStruct = traceRow.getHoverStruct();
162fb726d48Sopenharmony_ci    };
163fb726d48Sopenharmony_ci    traceRow.onThreadHandler = rowThreadHandler<CpuRender>('cpu-data', 'ctx', {
164fb726d48Sopenharmony_ci      type: `cpu-data-${cpuId}`,
165fb726d48Sopenharmony_ci      translateY: traceRow.translateY,
166fb726d48Sopenharmony_ci    }, traceRow, this.trace);
167fb726d48Sopenharmony_ci    return traceRow;
168fb726d48Sopenharmony_ci  }
169fb726d48Sopenharmony_ci
170fb726d48Sopenharmony_ci  initProcessThreadStateData = async (progress: Function): Promise<void> => {
171fb726d48Sopenharmony_ci    let time = new Date().getTime();
172fb726d48Sopenharmony_ci    progress('StateProcessThread', 93);
173fb726d48Sopenharmony_ci    procedurePool.submitWithName('logic0', 'spt-init', {}, undefined, (res: unknown) => { });
174fb726d48Sopenharmony_ci    let durTime = new Date().getTime() - time;
175fb726d48Sopenharmony_ci    info('The time to load the first ProcessThreadState data is: ', durTime);
176fb726d48Sopenharmony_ci  };
177fb726d48Sopenharmony_ci
178fb726d48Sopenharmony_ci  initCpuIdle0Data = async (progress: Function): Promise<void> => {
179fb726d48Sopenharmony_ci    let time = new Date().getTime();
180fb726d48Sopenharmony_ci    progress('CPU Idle', 94);
181fb726d48Sopenharmony_ci    procedurePool.submitWithName(
182fb726d48Sopenharmony_ci      'logic0',
183fb726d48Sopenharmony_ci      'scheduling-getCpuIdle0',
184fb726d48Sopenharmony_ci      {
185fb726d48Sopenharmony_ci        // @ts-ignore
186fb726d48Sopenharmony_ci        endTs: (window as unknown).recordEndNS, // @ts-ignore
187fb726d48Sopenharmony_ci        total: (window as unknown).totalNS,
188fb726d48Sopenharmony_ci      },
189fb726d48Sopenharmony_ci      undefined,
190fb726d48Sopenharmony_ci      (res: unknown) => { }
191fb726d48Sopenharmony_ci    );
192fb726d48Sopenharmony_ci    let durTime = new Date().getTime() - time;
193fb726d48Sopenharmony_ci    info('The time to load the first CPU Idle0 data is: ', durTime);
194fb726d48Sopenharmony_ci  };
195fb726d48Sopenharmony_ci
196fb726d48Sopenharmony_ci  initSchedSliceData(arr: unknown[], traceId?: string): void {
197fb726d48Sopenharmony_ci    Utils.getInstance().getSchedSliceMap(traceId).clear();
198fb726d48Sopenharmony_ci    arr.forEach((value) => {
199fb726d48Sopenharmony_ci      Utils.getInstance().getSchedSliceMap(traceId). // @ts-ignore
200fb726d48Sopenharmony_ci        set(`${value.itid}-${value.ts}`, { endState: value.endState, priority: value.priority });
201fb726d48Sopenharmony_ci    });
202fb726d48Sopenharmony_ci  }
203fb726d48Sopenharmony_ci
204fb726d48Sopenharmony_ci  initSchedulingPTData = async (progress: Function): Promise<void> => {
205fb726d48Sopenharmony_ci    let time = new Date().getTime();
206fb726d48Sopenharmony_ci    progress('CPU Idle', 94);
207fb726d48Sopenharmony_ci    procedurePool.submitWithName('logic0', 'scheduling-getProcessAndThread', {}, undefined, (res: unknown) => { });
208fb726d48Sopenharmony_ci    let durTime = new Date().getTime() - time;
209fb726d48Sopenharmony_ci    info('The time to load the first CPU Idle0 data is: ', durTime);
210fb726d48Sopenharmony_ci  };
211fb726d48Sopenharmony_ci
212fb726d48Sopenharmony_ci  initSchedulingFreqData = async (progress: Function): Promise<void> => {
213fb726d48Sopenharmony_ci    let time = new Date().getTime();
214fb726d48Sopenharmony_ci    progress('CPU Scheduling Freq', 94);
215fb726d48Sopenharmony_ci    procedurePool.submitWithName('logic0', 'scheduling-initFreqData', {}, undefined, (res: unknown) => { });
216fb726d48Sopenharmony_ci    let durTime = new Date().getTime() - time;
217fb726d48Sopenharmony_ci    info('The time to load the first CPU Idle0 data is: ', durTime);
218fb726d48Sopenharmony_ci  };
219fb726d48Sopenharmony_ci}
220