• 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 { SpApplication } from '../SpApplication.js';
17import { BaseStruct } from './BaseStruct.js';
18import { Rect } from '../component/trace/timer-shaft/Rect.js';
19import { info, warn } from '../../log/Log.js';
20import { drawString } from '../database/ui-worker/ProcedureWorkerCommon.js';
21
22const padding: number = 1;
23const lightBlue = {
24  r: 82,
25  g: 145,
26  b: 255,
27  a: 0.9,
28};
29
30export class ChartStruct extends BaseStruct {
31  static hoverFuncStruct: ChartStruct | undefined;
32  static selectFuncStruct: ChartStruct | undefined;
33  static lastSelectFuncStruct: ChartStruct | undefined;
34  needShow = false;
35  isDraw = false;
36  depth: number = 0;
37  symbol: string = '';
38  lib: string = '';
39  size: number = 0;
40  count: number = 0;
41  dur: number = 0;
42  drawSize: number = 0;
43  drawCount: number = 0;
44  drawDur: number = 0;
45  parent: ChartStruct | undefined;
46  children: Array<ChartStruct> = [];
47  percent: number = 0;
48  addr: string = '';
49  isSearch: boolean = false;
50  textMetricsWidth: number | undefined;
51}
52
53export enum ChartMode {
54  Byte, // Native Memory
55  Count, // Perf
56  Duration, // eBpf
57}
58
59export function setFuncFrame(node: ChartStruct, canvas_frame: Rect, total: number, mode: ChartMode) {
60  if (!node.frame) {
61    node.frame = new Rect(0, 0, 0, 0);
62  }
63  // filter depth is 0
64  if (node.parent) {
65    let idx = node.parent.children.indexOf(node);
66    if (idx == 0) {
67      node.frame!.x = node.parent.frame!.x;
68    } else {
69      // set x by left frame. left frame is parent.children[idx - 1]
70      node.frame.x = node.parent.children[idx - 1].frame!.x + node.parent.children[idx - 1].frame!.width;
71    }
72    switch (mode) {
73      case ChartMode.Byte:
74        node.frame!.width = Math.floor(((node.drawSize || node.size) / total) * canvas_frame.width);
75        break;
76      case ChartMode.Count:
77        node.frame!.width = Math.floor(((node.drawCount || node.count) / total) * canvas_frame.width);
78        break;
79      case ChartMode.Duration:
80        node.frame!.width = Math.floor(((node.drawDur || node.dur) / total) * canvas_frame.width);
81        break;
82      default:
83        warn('not match ChartMode');
84    }
85    node.frame!.y = node.parent.frame!.y + 20;
86    node.frame!.height = 20;
87  }
88}
89
90/**
91 * draw rect
92 * @param frameChartBeanCanvasCtx CanvasRenderingContext2D
93 * @param frameChartBeanData rect which is need draw
94 * @param percent function size or count / total size or count
95 */
96export function draw(frameChartBeanCanvasCtx: CanvasRenderingContext2D, frameChartBeanData: ChartStruct) {
97  let spApplication = <SpApplication>document.getElementsByTagName('sp-application')[0];
98  if (frameChartBeanData.frame) {
99    // draw rect
100    let frameChartMiniHeight = 20;
101    if (isSelected(frameChartBeanData)) {
102      frameChartBeanCanvasCtx.fillStyle = `rgba(${lightBlue.r}, ${lightBlue.g}, ${lightBlue.b}, ${lightBlue.a})`;
103    } else {
104      let color = getHeatColor(frameChartBeanData.percent);
105      frameChartBeanCanvasCtx.fillStyle = `rgba(${color.r}, ${color.g}, ${color.b}, 0.9)`;
106    }
107    frameChartBeanCanvasCtx.fillRect(frameChartBeanData.frame.x, frameChartBeanData.frame.y, frameChartBeanData.frame.width, frameChartMiniHeight - padding * 2);
108    //draw border
109    frameChartBeanCanvasCtx.lineWidth = 0.4;
110    if (isHover(frameChartBeanData)) {
111      if (spApplication.dark) {
112        frameChartBeanCanvasCtx.strokeStyle = '#fff';
113      } else {
114        frameChartBeanCanvasCtx.strokeStyle = '#000';
115      }
116    } else {
117      if (spApplication.dark) {
118        frameChartBeanCanvasCtx.strokeStyle = '#000';
119      } else {
120        frameChartBeanCanvasCtx.strokeStyle = '#fff';
121      }
122      if (frameChartBeanData.isSearch) {
123        frameChartBeanCanvasCtx.strokeStyle = `rgb(${lightBlue.r}, ${lightBlue.g}, ${lightBlue.b})`;
124        frameChartBeanCanvasCtx.lineWidth = 1;
125      }
126    }
127    frameChartBeanCanvasCtx.strokeRect(frameChartBeanData.frame.x, frameChartBeanData.frame.y, frameChartBeanData.frame.width, frameChartMiniHeight - padding * 2);
128
129    //draw symbol name
130    if (frameChartBeanData.frame.width > 10) {
131      if (frameChartBeanData.percent > 0.6 || isSelected(frameChartBeanData)) {
132        frameChartBeanCanvasCtx.fillStyle = '#fff';
133      } else {
134        frameChartBeanCanvasCtx.fillStyle = '#000';
135      }
136      drawString(frameChartBeanCanvasCtx, frameChartBeanData.symbol || '', 5, frameChartBeanData.frame, frameChartBeanData);
137    }
138    frameChartBeanData.isDraw = true;
139  }
140}
141
142/**
143 * get frame chart color by percent
144 * @param widthPercentage proportion of function
145 * @returns rbg
146 */
147function getHeatColor(widthPercentage: number) {
148  return {
149    r: Math.floor(245 + 10 * (1 - widthPercentage)),
150    g: Math.floor(110 + 105 * (1 - widthPercentage)),
151    b: 100,
152  };
153}
154
155function isHover(data: ChartStruct): boolean {
156  return ChartStruct.hoverFuncStruct == data;
157}
158
159function isSelected(data: ChartStruct): boolean {
160  return ChartStruct.lastSelectFuncStruct == data;
161}
162