• 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  drawSelection,
23  drawWakeUp,
24  Rect,
25  Render,
26  RequestMessage,
27  isFrameContainPoint,
28  ns2x,
29} from './ProcedureWorkerCommon.js';
30import { TraceRow } from '../../component/trace/base/TraceRow.js';
31import { HeapStruct as BaseHeapStruct } from '../../bean/HeapStruct.js';
32export class NativeMemoryRender extends Render {
33  renderMainThread(req: any, row: TraceRow<any>) {}
34}
35export class HeapRender {
36  renderMainThread(
37    req: {
38      context: CanvasRenderingContext2D;
39      useCache: boolean;
40      type: string;
41    },
42    row: TraceRow<HeapStruct>
43  ) {
44    let heapList = row.dataList;
45    let heapFilter = row.dataListCache;
46    heap(
47      heapList,
48      heapFilter,
49      TraceRow.range?.startNS ?? 0,
50      TraceRow.range?.endNS ?? 0,
51      TraceRow.range?.totalNS ?? 0,
52      row.frame,
53      req.useCache || (TraceRow.range?.refresh ?? false)
54    );
55    req.context.beginPath();
56    let find = false;
57    for (let re of heapFilter) {
58      if (row.isHover && re.frame && !find && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) {
59        HeapStruct.hoverHeapStruct = re;
60        find = true;
61      }
62    }
63    for (let re of heapFilter) {
64      HeapStruct.drawHeap(req.context, re, row.drawType);
65    }
66    if (!find && row.isHover) HeapStruct.hoverHeapStruct = undefined;
67    req.context.closePath();
68  }
69
70  render(heapRequest: RequestMessage, list: Array<any>, filter: Array<any>) {
71    if (heapRequest.lazyRefresh) {
72      heap(
73        list,
74        filter,
75        heapRequest.startNS,
76        heapRequest.endNS,
77        heapRequest.totalNS,
78        heapRequest.frame,
79        heapRequest.useCache || !heapRequest.range.refresh
80      );
81    } else {
82      if (!heapRequest.useCache) {
83        heap(list, filter, heapRequest.startNS, heapRequest.endNS, heapRequest.totalNS, heapRequest.frame, false);
84      }
85    }
86    if (heapRequest.canvas) {
87      heapRequest.context.clearRect(0, 0, heapRequest.canvas.width, heapRequest.canvas.height);
88      let heapArr = filter;
89      if (heapArr.length > 0 && !heapRequest.range.refresh && !heapRequest.useCache && heapRequest.lazyRefresh) {
90        drawLoading(
91          heapRequest.context,
92          heapRequest.startNS,
93          heapRequest.endNS,
94          heapRequest.totalNS,
95          heapRequest.frame,
96          heapArr[0].startTime,
97          heapArr[heapArr.length - 1].startTime + heapArr[heapArr.length - 1].dur
98        );
99      }
100      heapRequest.context.beginPath();
101      drawLines(heapRequest.context, heapRequest.xs, heapRequest.frame.height, heapRequest.lineColor);
102      HeapStruct.hoverHeapStruct = undefined;
103      if (heapRequest.isHover) {
104        for (let re of filter) {
105          if (
106            re.frame &&
107            heapRequest.hoverX >= re.frame.x &&
108            heapRequest.hoverX <= re.frame.x + re.frame.width &&
109            heapRequest.hoverY >= re.frame.y &&
110            heapRequest.hoverY <= re.frame.y + re.frame.height
111          ) {
112            HeapStruct.hoverHeapStruct = re;
113            break;
114          }
115        }
116      } else {
117        HeapStruct.hoverHeapStruct = heapRequest.params.hoverHeapStruct;
118      }
119      for (let re of filter) {
120        HeapStruct.drawHeap(heapRequest.context, re, heapRequest.params.drawType);
121      }
122      drawSelection(heapRequest.context, heapRequest.params);
123      heapRequest.context.closePath();
124      drawFlagLine(
125        heapRequest.context,
126        heapRequest.flagMoveInfo,
127        heapRequest.flagSelectedInfo,
128        heapRequest.startNS,
129        heapRequest.endNS,
130        heapRequest.totalNS,
131        heapRequest.frame,
132        heapRequest.slicesTime
133      );
134    }
135    // @ts-ignore
136    self.postMessage({
137      id: heapRequest.id,
138      type: heapRequest.type,
139      results: heapRequest.canvas ? undefined : filter,
140      hover: HeapStruct.hoverHeapStruct,
141    });
142  }
143}
144export function heap(
145  heapList: Array<any>,
146  res: Array<any>,
147  startNS: number,
148  endNS: number,
149  totalNS: number,
150  frame: any,
151  use: boolean
152) {
153  if (use && res.length > 0) {
154    for (let i = 0; i < res.length; i++) {
155      let it = res[i];
156      if ((it.startTime || 0) + (it.dur || 0) > (startNS || 0) && (it.startTime || 0) < (endNS || 0)) {
157        HeapStruct.setFrame(res[i], 5, startNS || 0, endNS || 0, totalNS || 0, frame);
158      } else {
159        res[i].frame = null;
160      }
161    }
162    return;
163  }
164  res.length = 0;
165  for (let i = 0, len = heapList.length; i < len; i++) {
166    let it = heapList[i];
167    if ((it.startTime || 0) + (it.dur || 0) > (startNS || 0) && (it.startTime || 0) < (endNS || 0)) {
168      HeapStruct.setFrame(it, 5, startNS || 0, endNS || 0, totalNS || 0, frame);
169      if (i > 0) {
170        let last = heapList[i - 1];
171        if (last.frame?.x != it.frame.x || last.frame.width != it.frame.width) {
172          res.push(it);
173        }
174      } else {
175        res.push(it);
176      }
177    }
178  }
179}
180
181export class HeapStruct extends BaseHeapStruct {
182  static hoverHeapStruct: HeapStruct | undefined;
183  static selectHeapStruct: HeapStruct | undefined;
184  maxDensity: number = 0;
185  minDensity: number = 0;
186
187  static setFrame(node: HeapStruct, padding: number, startNS: number, endNS: number, totalNS: number, frame: Rect) {
188    let x1: number, x2: number;
189    if ((node.startTime || 0) < startNS) {
190      x1 = 0;
191    } else {
192      x1 = ns2x(node.startTime || 0, startNS, endNS, totalNS, frame);
193    }
194    if ((node.startTime || 0) + (node.dur || 0) > endNS) {
195      x2 = frame.width;
196    } else {
197      x2 = ns2x(
198        // @ts-ignore
199        node.startTime + node.dur,
200        startNS,
201        endNS,
202        totalNS,
203        frame
204      );
205    }
206    let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1;
207    let rectangle: Rect = new Rect(
208      Math.floor(x1),
209      Math.ceil(frame.y + padding),
210      Math.ceil(getV),
211      Math.floor(frame.height - padding * 2)
212    );
213    node.frame = rectangle;
214  }
215
216  static drawHeap(heapContext: CanvasRenderingContext2D, data: HeapStruct, drawType: number) {
217    if (data.frame) {
218      let width = data.frame.width || 0;
219      heapContext.fillStyle = '#2db3aa';
220      heapContext.strokeStyle = '#2db3aa';
221      let drawHeight: number = 0;
222      if (drawType == 0) {
223        if (data.minHeapSize < 0) {
224          drawHeight = Math.ceil(
225            (((data.heapsize || 0) - data.minHeapSize) * (data.frame.height || 0)) /
226              (data.maxHeapSize - data.minHeapSize)
227          );
228        } else {
229          drawHeight = Math.ceil(((data.heapsize || 0) * (data.frame.height || 0)) / data.maxHeapSize);
230        }
231      } else {
232        if (data.minDensity < 0) {
233          drawHeight = Math.ceil(
234            (((data.density || 0) - data.minDensity) * (data.frame.height || 0)) / (data.maxDensity - data.minDensity)
235          );
236        } else {
237          drawHeight = Math.ceil(((data.density || 0) * (data.frame.height || 0)) / data.maxDensity);
238        }
239      }
240      if (data == HeapStruct.hoverHeapStruct || data == HeapStruct.selectHeapStruct) {
241        heapContext.lineWidth = 1;
242        heapContext.globalAlpha = 0.6;
243        heapContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight);
244        heapContext.beginPath();
245        heapContext.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true);
246        heapContext.fill();
247        heapContext.globalAlpha = 1.0;
248        heapContext.stroke();
249        heapContext.beginPath();
250        heapContext.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight);
251        heapContext.lineWidth = 3;
252        heapContext.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight);
253        heapContext.stroke();
254      } else {
255        heapContext.globalAlpha = 0.6;
256        heapContext.lineWidth = 1;
257        heapContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight);
258      }
259    }
260    heapContext.globalAlpha = 1.0;
261    heapContext.lineWidth = 1;
262  }
263}
264