• 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 { Rect, Render, isFrameContainPoint, ns2x, drawLoadingFrame } from './ProcedureWorkerCommon';
17import { TraceRow } from '../../component/trace/base/TraceRow';
18import { HeapStruct as BaseHeapStruct } from '../../bean/HeapStruct';
19import { SpSystemTrace } from '../../component/SpSystemTrace';
20export class NativeMemoryRender {
21  renderMainThread(req: HeapStruct, row: TraceRow<HeapStruct>): void {}
22}
23export class HeapRender {
24  renderMainThread(
25    req: {
26      context: CanvasRenderingContext2D;
27      useCache: boolean;
28      type: string;
29    },
30    row: TraceRow<HeapStruct>
31  ): void {
32    let heapList = row.dataList;
33    let heapFilter = row.dataListCache;
34    heap(
35      heapList,
36      heapFilter,
37      TraceRow.range?.startNS ?? 0,
38      TraceRow.range?.endNS ?? 0,
39      TraceRow.range?.totalNS ?? 0,
40      row.frame,
41      req.useCache || (TraceRow.range?.refresh ?? false)
42    );
43    drawLoadingFrame(req.context, heapFilter, row);
44    setRenderHeapFrame(heapFilter, row);
45    drawHeap(req, heapFilter, row);
46  }
47}
48
49function setRenderHeapFrame(heapFilter: HeapStruct[], row: TraceRow<HeapStruct>): void {
50  // 多条数据,最后一条数据在结束点也需要绘制
51  if (heapFilter.length >= 2 && heapFilter[heapFilter.length - 1].dur === 0) {
52    if (heapFilter[heapFilter.length - 2].frame && heapFilter[heapFilter.length - 1].frame) {
53      heapFilter[heapFilter.length - 2].frame!.width = heapFilter[heapFilter.length - 2].frame!.width - 1;
54      heapFilter[heapFilter.length - 1].frame!.width = 1;
55      heapFilter[heapFilter.length - 1].frame!.x -= 1;
56    }
57  }
58  // 只有一条数据并且数据在结束点
59  // @ts-ignore
60  if (heapFilter.length === 1 && row.frame.width === heapFilter[0].frame?.x) {
61    heapFilter[0].frame!.x -= 1;
62  }
63}
64
65function drawHeap(
66  req: {
67    context: CanvasRenderingContext2D;
68    useCache: boolean;
69    type: string;
70  },
71  heapFilter: HeapStruct[],
72  row: TraceRow<HeapStruct>
73): void {
74  req.context.beginPath();
75  let find = false;
76  for (let re of heapFilter) {
77    if (row.isHover && re.frame && !find && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) {
78      HeapStruct.hoverHeapStruct = re;
79      find = true;
80    }
81  }
82  for (let re of heapFilter) {
83    HeapStruct.drawHeap(req.context, re, row.drawType);
84  }
85  if (!find && row.isHover) {
86    HeapStruct.hoverHeapStruct = undefined;
87  }
88  req.context.closePath();
89}
90
91export function heap(
92  heapList: Array<HeapStruct>,
93  res: Array<HeapStruct>,
94  startNS: number,
95  endNS: number,
96  totalNS: number,
97  frame: Rect,
98  use: boolean
99): void {
100  if (use && res.length > 0) {
101    setHeapFrameIfUse(res, startNS, endNS, totalNS, frame);
102    return;
103  }
104  res.length = 0;
105  for (let i = 0, len = heapList.length; i < len; i++) {
106    let it = heapList[i];
107    if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) <= endNS) {
108      HeapStruct.setFrame(it, 5, startNS, endNS, totalNS, frame);
109      if (i > 0) {
110        let last = heapList[i - 1];
111        if (last.frame?.x !== it.frame!.x || last.frame.width !== it.frame!.width) {
112          res.push(it);
113        }
114      } else {
115        res.push(it);
116      }
117    }
118  }
119}
120
121function setHeapFrameIfUse(res: Array<HeapStruct>, startNS: number, endNS: number, totalNS: number, frame: Rect): void {
122  for (let i = 0; i < res.length; i++) {
123    let it = res[i];
124    if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) <= endNS) {
125      HeapStruct.setFrame(res[i], 5, startNS, endNS, totalNS, frame);
126    } else {
127      res[i].frame = undefined;
128    }
129  }
130}
131
132export function HeapStructOnClick(
133  clickRowType: string,
134  sp: SpSystemTrace,
135  row: undefined | TraceRow<HeapStruct>
136): Promise<unknown> {
137  return new Promise((resolve, reject) => {
138    if (
139      clickRowType === TraceRow.ROW_TYPE_HEAP &&
140      row &&
141      row.getAttribute('heap-type') === 'native_hook_statistic' &&
142      HeapStruct.hoverHeapStruct
143    ) {
144      HeapStruct.selectHeapStruct = HeapStruct.hoverHeapStruct;
145      const key = row.rowParentId!.split(' ');
146      let ipid = 1;
147      if (key.length > 0) {
148        ipid = Number(key[key.length - 1]);
149      }
150      sp.traceSheetEL?.displayNativeHookData(HeapStruct.selectHeapStruct, row.rowId!, ipid);
151      sp.timerShaftEL?.modifyFlagList(undefined);
152      reject(new Error());
153    } else {
154      resolve(null);
155    }
156  });
157}
158export class HeapStruct extends BaseHeapStruct {
159  static hoverHeapStruct: HeapStruct | undefined;
160  static selectHeapStruct: HeapStruct | undefined;
161  maxDensity: number = 0;
162  minDensity: number = 0;
163
164  static setFrame(
165    node: HeapStruct,
166    padding: number,
167    startNS: number,
168    endNS: number,
169    totalNS: number,
170    frame: Rect
171  ): void {
172    let x1: number;
173    let x2: number;
174    if ((node.startTime || 0) < startNS) {
175      x1 = 0;
176    } else {
177      x1 = ns2x(node.startTime || 0, startNS, endNS, totalNS, frame);
178    }
179    if ((node.startTime || 0) + (node.dur || 0) > endNS) {
180      x2 = frame.width;
181    } else {
182      x2 = ns2x(
183        // @ts-ignore
184        node.startTime + node.dur,
185        startNS,
186        endNS,
187        totalNS,
188        frame
189      );
190    }
191    let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1;
192    let rectangle: Rect = new Rect(
193      Math.floor(x1),
194      Math.ceil(frame.y + padding),
195      Math.ceil(getV),
196      Math.floor(frame.height - padding * 2)
197    );
198    node.frame = rectangle;
199  }
200
201  static drawHeap(heapContext: CanvasRenderingContext2D, data: HeapStruct, drawType: number): void {
202    if (data.frame) {
203      let width = data.frame.width || 0;
204      heapContext.fillStyle = '#2db3aa';
205      heapContext.strokeStyle = '#2db3aa';
206      let drawHeight: number = 0;
207      if (drawType === 0) {
208        if (data.minHeapSize < 0) {
209          drawHeight = Math.ceil(
210            (((data.heapsize || 0) - data.minHeapSize) * (data.frame.height || 0)) /
211              (data.maxHeapSize - data.minHeapSize)
212          );
213        } else {
214          drawHeight = Math.ceil(((data.heapsize || 0) * (data.frame.height || 0)) / data.maxHeapSize);
215        }
216      } else {
217        if (data.minDensity < 0) {
218          drawHeight = Math.ceil(
219            (((data.density || 0) - data.minDensity) * (data.frame.height || 0)) / (data.maxDensity - data.minDensity)
220          );
221        } else {
222          drawHeight = Math.ceil(((data.density || 0) * (data.frame.height || 0)) / data.maxDensity);
223        }
224      }
225      if (data === HeapStruct.hoverHeapStruct || data === HeapStruct.selectHeapStruct) {
226        heapContext.lineWidth = 1;
227        heapContext.globalAlpha = 0.6;
228        heapContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight);
229        heapContext.beginPath();
230        heapContext.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true);
231        heapContext.fill();
232        heapContext.globalAlpha = 1.0;
233        heapContext.stroke();
234        heapContext.beginPath();
235        heapContext.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight);
236        heapContext.lineWidth = 3;
237        heapContext.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight);
238        heapContext.stroke();
239      } else {
240        heapContext.globalAlpha = 0.6;
241        heapContext.lineWidth = 1;
242        heapContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight);
243      }
244    }
245    heapContext.globalAlpha = 1.0;
246    heapContext.lineWidth = 1;
247  }
248}
249