• 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  isFrameContainPoint,
20  ns2x,
21  Render,
22  drawLoadingFrame,
23  Rect,
24} from '../ProcedureWorkerCommon';
25import { ColorUtils } from '../../../component/trace/base/ColorUtils';
26import { TraceRow } from '../../../component/trace/base/TraceRow';
27import { SpSystemTrace } from '../../../component/SpSystemTrace';
28
29export class CpuFreqLimitRender extends Render {
30  renderMainThread(
31    cpuFreqLimitReq: {
32      useCache: boolean;
33      context: CanvasRenderingContext2D;
34      cpu: number;
35      type: string;
36      maxFreq: number;
37      maxFreqName: string;
38    },
39    row: TraceRow<CpuFreqLimitsStruct>
40  ): void {
41    let list = row.dataList;
42    let filter = row.dataListCache;
43    dataFilterHandler(list, filter, {
44      startKey: 'startNs',
45      durKey: 'dur',
46      startNS: TraceRow.range?.startNS ?? 0,
47      endNS: TraceRow.range?.endNS ?? 0,
48      totalNS: TraceRow.range?.totalNS ?? 0,
49      frame: row.frame,
50      paddingTop: 5,
51      useCache: cpuFreqLimitReq.useCache || !(TraceRow.range?.refresh ?? false),
52    });
53    drawLoadingFrame(cpuFreqLimitReq.context, filter, row);
54    cpuFreqLimitReq.context.beginPath();
55    let maxFreq = cpuFreqLimitReq.maxFreq;
56    let maxFreqName = cpuFreqLimitReq.maxFreqName;
57    if (row.isHover) {
58      for (let re of filter) {
59        if (re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) {
60          CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = re;
61          break;
62        }
63      }
64    }
65    for (let re of filter) {
66      CpuFreqLimitsStruct.draw(cpuFreqLimitReq.context, re, maxFreq);
67    }
68    cpuFreqLimitReq.context.closePath();
69    let s = maxFreqName;
70    let textMetrics = cpuFreqLimitReq.context.measureText(s);
71    cpuFreqLimitReq.context.globalAlpha = 0.8;
72    cpuFreqLimitReq.context.fillStyle = '#f0f0f0';
73    cpuFreqLimitReq.context.fillRect(0, 5, textMetrics.width + 8, 18);
74    cpuFreqLimitReq.context.globalAlpha = 1;
75    cpuFreqLimitReq.context.fillStyle = '#333';
76    cpuFreqLimitReq.context.textBaseline = 'middle';
77    cpuFreqLimitReq.context.fillText(s, 4, 5 + 9);
78  }
79}
80export function CpuFreqLimitsStructOnClick(clickRowType: string, sp: SpSystemTrace): Promise<unknown> {
81  return new Promise((resolve, reject) => {
82    if (clickRowType === TraceRow.ROW_TYPE_CPU_FREQ_LIMIT && CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct) {
83      CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct;
84      sp.traceSheetEL?.displayFreqLimitData();
85      sp.timerShaftEL?.modifyFlagList(undefined);
86      reject(new Error());
87    } else {
88      resolve(null);
89    }
90  });
91}
92export class CpuFreqLimitsStruct extends BaseStruct {
93  static hoverCpuFreqLimitsStruct: CpuFreqLimitsStruct | undefined;
94  static selectCpuFreqLimitsStruct: CpuFreqLimitsStruct | undefined;
95  static minAlpha = 0.4;
96  static maxAlpha = 0.8;
97  startNs: number | undefined;
98  dur: number = 0;
99  max: number | undefined;
100  min: number | undefined;
101  cpu: number = 0;
102
103  static draw(ctx: CanvasRenderingContext2D, data: CpuFreqLimitsStruct, maxFreq: number): void {
104    if (data.frame) {
105      let width = data.frame.width || 0;
106      let drawMaxHeight: number = Math.floor(((data.max || 0) * (data.frame.height || 0)) / maxFreq);
107      let drawMinHeight: number = Math.floor(((data.min || 0) * (data.frame.height || 0)) / maxFreq);
108      let index = data.cpu || 0;
109      index += 2;
110      ctx.fillStyle = ColorUtils.colorForTid(index);
111      ctx.strokeStyle = ColorUtils.colorForTid(index);
112      if (
113        data === CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct ||
114        data === CpuFreqLimitsStruct.selectCpuFreqLimitsStruct
115      ) {
116        ctx.lineWidth = 1;
117        ctx.globalAlpha = this.minAlpha;
118        this.drawArcLine(ctx, data, drawMaxHeight, drawMaxHeight - drawMinHeight);
119        ctx.globalAlpha = this.maxAlpha;
120        this.drawArcLine(ctx, data, drawMinHeight, drawMinHeight);
121      } else {
122        ctx.globalAlpha = this.minAlpha;
123        ctx.lineWidth = 1;
124        ctx.fillRect(
125          data.frame.x,
126          data.frame.y + data.frame.height - drawMaxHeight,
127          width,
128          drawMaxHeight - drawMinHeight
129        );
130        ctx.globalAlpha = this.maxAlpha;
131        ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawMinHeight, width, drawMinHeight);
132      }
133    }
134    ctx.globalAlpha = 1.0;
135    ctx.lineWidth = 1;
136  }
137
138  static drawArcLine(
139    ctx: CanvasRenderingContext2D,
140    data: CpuFreqLimitsStruct,
141    yStartHeight: number,
142    drawHeight: number
143  ): void {
144    if (data.frame) {
145      let width = data.frame.width || 0;
146      ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - yStartHeight, width, drawHeight);
147      ctx.globalAlpha = this.maxAlpha;
148      ctx.beginPath();
149      ctx.arc(data.frame.x, data.frame.y + data.frame.height - yStartHeight, 3, 0, 2 * Math.PI, true);
150      ctx.fill();
151      ctx.stroke();
152      ctx.beginPath();
153      ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - yStartHeight);
154      ctx.lineWidth = 3;
155      ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - yStartHeight);
156      ctx.stroke();
157    }
158  }
159
160  static setFreqLimitFrame(
161    freqLimitNode: CpuFreqLimitsStruct,
162    padding: number,
163    startNS: number,
164    endNS: number,
165    totalNS: number,
166    frame: Rect
167  ): void {
168    let x1: number;
169    let x2: number;
170    if ((freqLimitNode.startNs || 0) < startNS) {
171      x1 = 0;
172    } else {
173      x1 = ns2x(freqLimitNode.startNs || 0, startNS, endNS, totalNS, frame);
174    }
175    if ((freqLimitNode.startNs || 0) + (freqLimitNode.dur || 0) > endNS) {
176      x2 = frame.width;
177    } else {
178      x2 = ns2x((freqLimitNode.startNs || 0) + (freqLimitNode.dur || 0), startNS, endNS, totalNS, frame);
179    }
180    let cpuFreqLimitsGetV: number = x2 - x1 <= 1 ? 1 : x2 - x1;
181    if (!freqLimitNode.frame) {
182      freqLimitNode.frame = new Rect(0, 0, 0, 0);
183    }
184    freqLimitNode.frame.x = Math.floor(x1);
185    freqLimitNode.frame.y = frame.y + padding;
186    freqLimitNode.frame.width = Math.ceil(cpuFreqLimitsGetV);
187    freqLimitNode.frame.height = Math.floor(frame.height - padding * 2);
188  }
189}
190