• 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  drawSelection,
22  isFrameContainPoint,
23  ns2x,
24  Render,
25  RequestMessage,
26} from './ProcedureWorkerCommon.js';
27import { TraceRow } from '../../component/trace/base/TraceRow.js';
28import { CpuAbilityMonitorStruct } from './ProcedureWorkerCpuAbility.js';
29
30export class SmapsRender extends Render {
31  renderMainThread(
32    req: {
33      context: CanvasRenderingContext2D;
34      useCache: boolean;
35      type: string;
36      rowName: string;
37      maxValue: number;
38    },
39    row: TraceRow<SmapsStruct>
40  ) {
41    let smapsList = row.dataList;
42    let smapsFilter = row.dataListCache;
43    dataFilterHandler(smapsList, smapsFilter, {
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: req.useCache || !(TraceRow.range?.refresh ?? false),
52    });
53    req.context.beginPath();
54    let drawColor = '#0A59F7';
55    if (req.rowName != undefined) {
56      switch (req.rowName) {
57        case 'dirty':
58          drawColor = '#0A59F7';
59          break;
60        case 'swapper':
61          drawColor = '#46B1E3';
62          break;
63        case 'resident_size':
64          drawColor = '#564AF7';
65          break;
66      }
67    }
68    let find = false;
69    for (let re of smapsFilter) {
70      SmapsStruct.draw(req.context, re, req.maxValue, drawColor, row.isHover);
71      if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) {
72        SmapsStruct.hoverSmapsStruct = re;
73        find = true;
74      }
75    }
76    if (!find && row.isHover) SmapsStruct.hoverSmapsStruct = undefined;
77
78    req.context.closePath();
79  }
80
81  render(smapsReq: RequestMessage, list: Array<any>, filter: Array<any>) {
82    if (smapsReq.lazyRefresh) {
83      smaps(
84        list,
85        filter,
86        smapsReq.startNS,
87        smapsReq.endNS,
88        smapsReq.totalNS,
89        smapsReq.frame,
90        smapsReq.useCache || !smapsReq.range.refresh
91      );
92    } else {
93      if (!smapsReq.useCache) {
94        smaps(list, filter, smapsReq.startNS, smapsReq.endNS, smapsReq.totalNS, smapsReq.frame, false);
95      }
96    }
97    if (smapsReq.canvas) {
98      smapsReq.context.clearRect(0, 0, smapsReq.frame.width, smapsReq.frame.height);
99      smapsReq.context.beginPath();
100      let maxValue = 0;
101      let maxValueName = '';
102      if (smapsReq.params.maxValue != undefined || smapsReq.params.maxValueName != undefined) {
103        maxValue = smapsReq.params.maxValue;
104        maxValueName = smapsReq.params.maxValueName;
105      }
106      drawLines(smapsReq.context, smapsReq.xs, smapsReq.frame.height, smapsReq.lineColor);
107      SmapsStruct.hoverSmapsStruct = undefined;
108      if (smapsReq.isHover) {
109        for (let re of filter) {
110          if (
111            re.frame &&
112            smapsReq.hoverX >= re.frame.x &&
113            smapsReq.hoverX <= re.frame.x + re.frame.width &&
114            smapsReq.hoverY >= re.frame.y &&
115            smapsReq.hoverY <= re.frame.y + re.frame.height
116          ) {
117            SmapsStruct.hoverSmapsStruct = re;
118            break;
119          }
120        }
121      }
122      let drawColor = '#0A59F7';
123      if (smapsReq.params.rowName != undefined) {
124        switch (smapsReq.params.rowName) {
125          case 'dirty':
126            drawColor = '#0A59F7';
127            break;
128          case 'swapper':
129            drawColor = '#46B1E3';
130            break;
131          case 'resident_size':
132            drawColor = '#564AF7';
133            break;
134        }
135      }
136      SmapsStruct.selectSmapsStruct = smapsReq.params.selectSmapsStruct;
137      for (let re of filter) {
138        SmapsStruct.draw(smapsReq.context, re, maxValue, drawColor, true);
139      }
140      drawSelection(smapsReq.context, smapsReq.params);
141      smapsReq.context.closePath();
142      drawFlagLine(
143        smapsReq.context,
144        smapsReq.flagMoveInfo,
145        smapsReq.flagSelectedInfo,
146        smapsReq.startNS,
147        smapsReq.endNS,
148        smapsReq.totalNS,
149        smapsReq.frame,
150        smapsReq.slicesTime
151      );
152    }
153    // @ts-ignore
154    self.postMessage({
155      id: smapsReq.id,
156      type: smapsReq.type,
157      results: smapsReq.canvas ? undefined : filter,
158      hover: SmapsStruct.hoverSmapsStruct,
159    });
160  }
161}
162
163export function smaps(
164  smapsList: Array<any>,
165  res: Array<any>,
166  startNS: number,
167  endNS: number,
168  totalNS: number,
169  frame: any,
170  use: boolean
171) {
172  if (use && res.length > 0) {
173    for (let i = 0; i < res.length; i++) {
174      let smapsItem = res[i];
175      if ((smapsItem.startNS || 0) + (smapsItem.dur || 0) > (startNS || 0) && (smapsItem.startNS || 0) < (endNS || 0)) {
176        SmapsStruct.setSmapsFrame(smapsItem, 5, startNS || 0, endNS || 0, totalNS || 0, frame);
177      } else {
178        smapsItem.frame = null;
179      }
180    }
181    return;
182  }
183  res.length = 0;
184  if (smapsList) {
185    for (let smapsIndex = 0; smapsIndex < smapsList.length; smapsIndex++) {
186      let item = smapsList[smapsIndex];
187      if (smapsIndex === smapsList.length - 1) {
188        item.dur = (endNS || 0) - (item.startNS || 0);
189      } else {
190        item.dur = (smapsList[smapsIndex + 1].startNS || 0) - (item.startNS || 0);
191      }
192      if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) {
193        SmapsStruct.setSmapsFrame(smapsList[smapsIndex], 5, startNS || 0, endNS || 0, totalNS || 0, frame);
194        if (
195          smapsIndex > 0 &&
196          (smapsList[smapsIndex - 1].frame?.x || 0) == (smapsList[smapsIndex].frame?.x || 0) &&
197          (smapsList[smapsIndex - 1].frame?.width || 0) == (smapsList[smapsIndex].frame?.width || 0)
198        ) {
199        } else {
200          res.push(item);
201        }
202      }
203    }
204  }
205}
206
207export class SmapsStruct extends BaseStruct {
208  static maxValue: number = 0;
209  static maxValueName: string = '0 KB/S';
210  static hoverSmapsStruct: SmapsStruct | undefined;
211  static selectSmapsStruct: SmapsStruct | undefined;
212  value: number | undefined;
213  startNS: number | undefined;
214  dur: number | undefined;
215
216  static draw(
217    smapsContext: CanvasRenderingContext2D,
218    data: SmapsStruct,
219    maxValue: number,
220    drawColor: string,
221    isHover: boolean
222  ) {
223    if (data.frame) {
224      let width = data.frame.width || 0;
225      smapsContext.fillStyle = drawColor;
226      smapsContext.strokeStyle = drawColor;
227      if (data.startNS === SmapsStruct.hoverSmapsStruct?.startNS && isHover) {
228        smapsContext.lineWidth = 1;
229        let smapsDrawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / maxValue);
230        smapsContext.fillRect(
231          data.frame.x,
232          data.frame.y + data.frame.height - smapsDrawHeight + 4,
233          width,
234          smapsDrawHeight
235        );
236        smapsContext.beginPath();
237        smapsContext.arc(data.frame.x, data.frame.y + data.frame.height - smapsDrawHeight + 4, 3, 0, 2 * Math.PI, true);
238        smapsContext.fill();
239        smapsContext.globalAlpha = 1.0;
240        smapsContext.stroke();
241        smapsContext.beginPath();
242        smapsContext.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - smapsDrawHeight + 4);
243        smapsContext.lineWidth = 3;
244        smapsContext.lineTo(data.frame.x + width, data.frame.y + data.frame.height - smapsDrawHeight + 4);
245        smapsContext.stroke();
246      } else {
247        smapsContext.lineWidth = 1;
248        let smapsDrawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxValue);
249        smapsContext.fillRect(
250          data.frame.x,
251          data.frame.y + data.frame.height - smapsDrawHeight + 4,
252          width,
253          smapsDrawHeight
254        );
255      }
256    }
257    smapsContext.globalAlpha = 1.0;
258    smapsContext.lineWidth = 1;
259  }
260
261  static setSmapsFrame(smapsNode: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) {
262    let smapsStartPointX: number, smapsEndPointX: number;
263
264    if ((smapsNode.startNS || 0) < startNS) {
265      smapsStartPointX = 0;
266    } else {
267      smapsStartPointX = ns2x(smapsNode.startNS || 0, startNS, endNS, totalNS, frame);
268    }
269    if ((smapsNode.startNS || 0) + (smapsNode.dur || 0) > endNS) {
270      smapsEndPointX = frame.width;
271    } else {
272      smapsEndPointX = ns2x((smapsNode.startNS || 0) + (smapsNode.dur || 0), startNS, endNS, totalNS, frame);
273    }
274    let frameWidth: number = smapsEndPointX - smapsStartPointX <= 1 ? 1 : smapsEndPointX - smapsStartPointX;
275    if (!smapsNode.frame) {
276      smapsNode.frame = {};
277    }
278    smapsNode.frame.x = Math.floor(smapsStartPointX);
279    smapsNode.frame.y = frame.y + padding;
280    smapsNode.frame.width = Math.ceil(frameWidth);
281    smapsNode.frame.height = Math.floor(frame.height - padding * 2);
282  }
283}
284