• 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 {
17  BaseStruct,
18  dataFilterHandler,
19  drawFlagLine,
20  drawLines,
21  drawLoading,
22  drawLoadingFrame,
23  drawSelection,
24  drawWakeUp,
25  ns2x,
26  PerfRender,
27  Render,
28  RequestMessage,
29} from '../ProcedureWorkerCommon';
30import { TraceRow } from '../../../component/trace/base/TraceRow';
31import { ColorUtils } from '../../../component/trace/base/ColorUtils';
32import { convertJSON } from '../../logic-worker/ProcedureLogicWorkerCommon';
33import {SpSystemTrace} from "../../../component/SpSystemTrace";
34
35export class CpuStateRender extends PerfRender {
36  renderMainThread(
37    req: {
38      useCache: boolean;
39      cpuStateContext: CanvasRenderingContext2D;
40      type: string;
41      cpu: number;
42    },
43    cpuStateRow: TraceRow<CpuStateStruct>
44  ): void {
45    let list = cpuStateRow.dataList;
46    let filter = cpuStateRow.dataListCache;
47    dataFilterHandler(list, filter, {
48      startKey: 'startTs',
49      durKey: 'dur',
50      startNS: TraceRow.range?.startNS ?? 0,
51      endNS: TraceRow.range?.endNS ?? 0,
52      totalNS: TraceRow.range?.totalNS ?? 0,
53      frame: cpuStateRow.frame,
54      paddingTop: 5,
55      useCache: req.useCache || !(TraceRow.range?.refresh ?? false),
56    });
57    drawLoadingFrame(req.cpuStateContext, filter, cpuStateRow);
58    let path = new Path2D();
59    let find = false;
60    let offset = 3;
61    let heights = [4, 12, 21, 30];
62    for (let re of filter) {
63      re.height = heights[(re as any).value];
64      CpuStateStruct.draw(req.cpuStateContext, path, re);
65      if (cpuStateRow.isHover) {
66        if (
67          re.frame &&
68          cpuStateRow.hoverX >= re.frame.x - offset &&
69          cpuStateRow.hoverX <= re.frame.x + re.frame.width + offset
70        ) {
71          CpuStateStruct.hoverStateStruct = re;
72          find = true;
73        }
74      }
75    }
76    if (!find && cpuStateRow.isHover) {
77      CpuStateStruct.hoverStateStruct = undefined;
78    }
79    req.cpuStateContext.fill(path);
80  }
81
82  render(cpuStateReq: RequestMessage, list: Array<any>, filter: Array<any>, dataList2: Array<any>) {}
83
84  setFrameByArr(cpuStateRes: any[], startNS: number, endNS: number, totalNS: number, frame: any, arr2: any[]) {
85    let list: any[] = arr2;
86    cpuStateRes.length = 0;
87    let pns = (endNS - startNS) / frame.width;
88    let y = frame.y + 5;
89    let frameHeight = frame.height - 10;
90    let left = 0,
91      right = 0;
92    for (let i = 0, j = list.length - 1, ib = true, jb = true; i < list.length, j >= 0; i++, j--) {
93      if (list[j].startTs <= endNS && jb) {
94        right = j;
95        jb = false;
96      }
97      if (list[i].startTs + list[i].dur >= startNS && ib) {
98        left = i;
99        ib = false;
100      }
101      if (!ib && !jb) {
102        break;
103      }
104    }
105    let slice = list.slice(left, right + 1);
106    let sum = 0;
107    for (let i = 0; i < slice.length; i++) {
108      if (!slice[i].frame) {
109        slice[i].frame = {};
110        slice[i].frame.y = y;
111        slice[i].frame.height = frameHeight;
112      }
113      if (slice[i].dur >= pns) {
114        slice[i].v = true;
115        CpuStateStruct.setFrame(slice[i], 5, startNS, endNS, totalNS, frame);
116      } else {
117        if (i > 0) {
118          let c = slice[i].startTs - slice[i - 1].startTs - slice[i - 1].dur;
119          if (c < pns && sum < pns) {
120            sum += c + slice[i - 1].dur;
121            slice[i].v = false;
122          } else {
123            slice[i].v = true;
124            CpuStateStruct.setFrame(slice[i], 5, startNS, endNS, totalNS, frame);
125            sum = 0;
126          }
127        }
128      }
129    }
130    cpuStateRes.push(...slice.filter((it) => it.v));
131  }
132
133  setFrameByFilter(cpuStateRes: any[], startNS: number, endNS: number, totalNS: number, frame: any) {
134    for (let i = 0, len = cpuStateRes.length; i < len; i++) {
135      if (
136        (cpuStateRes[i].startTs || 0) + (cpuStateRes[i].dur || 0) >= startNS &&
137        (cpuStateRes[i].startTs || 0) <= endNS
138      ) {
139        CpuStateStruct.setFrame(cpuStateRes[i], 5, startNS, endNS, totalNS, frame);
140      } else {
141        cpuStateRes[i].frame = null;
142      }
143    }
144  }
145
146  cpuState(
147    arr: any[],
148    arr2: any[],
149    type: string,
150    cpuStateRes: any[],
151    cpu: number,
152    startNS: number,
153    endNS: number,
154    totalNS: number,
155    frame: any,
156    use: boolean
157  ) {
158    if (use && cpuStateRes.length > 0) {
159      this.setFrameByFilter(cpuStateRes, startNS, endNS, totalNS, frame);
160      return;
161    }
162    cpuStateRes.length = 0;
163    if (arr) {
164      this.setFrameByArr(cpuStateRes, startNS, endNS, totalNS, frame, arr2);
165    }
166  }
167}
168export function CpuStateStructOnClick(clickRowType: string, sp: SpSystemTrace) {
169  return new Promise((resolve, reject) => {
170    if (clickRowType === TraceRow.ROW_TYPE_CPU_STATE && CpuStateStruct.hoverStateStruct) {
171      CpuStateStruct.selectStateStruct = CpuStateStruct.hoverStateStruct;
172      sp.traceSheetEL?.displayCpuStateData();
173      sp.timerShaftEL?.modifyFlagList(undefined);
174      reject();
175    }else{
176      resolve(null);
177    }
178  });
179}
180export class CpuStateStruct extends BaseStruct {
181  static hoverStateStruct: CpuStateStruct | undefined;
182  static selectStateStruct: CpuStateStruct | undefined;
183  dur: number | undefined;
184  value: string | undefined;
185  startTs: number | undefined;
186  height: number | undefined;
187  cpu: number | undefined;
188
189  static draw(ctx: CanvasRenderingContext2D, path: Path2D, data: CpuStateStruct) {
190    if (data.frame) {
191      let chartColor = ColorUtils.colorForTid(data.cpu!);
192      ctx.font = '11px sans-serif';
193      ctx.fillStyle = chartColor;
194      ctx.strokeStyle = chartColor;
195      ctx.globalAlpha = 0.6;
196      if (data === CpuStateStruct.hoverStateStruct || data === CpuStateStruct.selectStateStruct) {
197        path.rect(data.frame.x, 35 - (data.height || 0), data.frame.width, data.height || 0);
198        ctx.lineWidth = 1;
199        ctx.globalAlpha = 1.0;
200        ctx.beginPath();
201        ctx.arc(data.frame.x, 35 - (data.height || 0), 3, 0, 2 * Math.PI, true);
202        ctx.stroke();
203        ctx.beginPath();
204        ctx.moveTo(data.frame.x + 3, 35 - (data.height || 0));
205        ctx.lineWidth = 3;
206        ctx.lineTo(data.frame.x + data.frame.width, 35 - (data.height || 0));
207        ctx.stroke();
208        ctx.lineWidth = 1;
209        ctx.globalAlpha = 0.6;
210        ctx.fillRect(data.frame.x, 35 - (data.height || 0), data.frame.width, data.height || 0);
211      } else {
212        ctx.globalAlpha = 0.6;
213        ctx.fillRect(data.frame.x, 35 - (data.height || 0), data.frame.width, data.height || 0);
214      }
215    }
216  }
217
218  static setCpuFrame(cpuStateNode: any, pns: number, startNS: number, endNS: number, frame: any) {
219    if ((cpuStateNode.startTime || 0) < startNS) {
220      cpuStateNode.frame.x = 0;
221    } else {
222      cpuStateNode.frame.x = Math.floor(((cpuStateNode.startTs || 0) - startNS) / pns);
223    }
224    if ((cpuStateNode.startTime || 0) + (cpuStateNode.dur || 0) > endNS) {
225      cpuStateNode.frame.width = frame.width - cpuStateNode.frame.x;
226    } else {
227      cpuStateNode.frame.width = Math.ceil(
228        ((cpuStateNode.startTs || 0) + (cpuStateNode.dur || 0) - startNS) / pns - cpuStateNode.frame.x
229      );
230    }
231    if (cpuStateNode.frame.width < 1) {
232      cpuStateNode.frame.width = 1;
233    }
234  }
235  static setFrame(cpuStateNode: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) {
236    let x1: number, x2: number;
237    if ((cpuStateNode.startTs || 0) < startNS) {
238      x1 = 0;
239    } else {
240      x1 = ns2x(cpuStateNode.startTs || 0, startNS, endNS, totalNS, frame);
241    }
242    if ((cpuStateNode.startTs || 0) + (cpuStateNode.dur || 0) > endNS) {
243      x2 = frame.width;
244    } else {
245      x2 = ns2x((cpuStateNode.startTs || 0) + (cpuStateNode.dur || 0), startNS, endNS, totalNS, frame);
246    }
247    let cpuStateGetV: number = x2 - x1 <= 1 ? 1 : x2 - x1;
248    if (!cpuStateNode.frame) {
249      cpuStateNode.frame = {};
250    }
251    cpuStateNode.frame.x = Math.ceil(x1);
252    cpuStateNode.frame.y = frame.y + padding;
253    cpuStateNode.frame.width = Math.floor(cpuStateGetV);
254    cpuStateNode.frame.height = cpuStateNode.height;
255  }
256}
257