• 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 */
15import { BaseStruct, Rect, Render, drawLoadingFrame, isFrameContainPoint, ns2x } from './ProcedureWorkerCommon';
16import { TraceRow } from '../../component/trace/base/TraceRow';
17import { Utils } from '../../component/trace/base/Utils';
18import { MemoryConfig } from '../../bean/MemoryConfig';
19import { SpSystemTrace } from '../../component/SpSystemTrace';
20
21export class SnapshotRender extends Render {
22  renderMainThread(
23    req: {
24      context: CanvasRenderingContext2D;
25      useCache: boolean;
26      type: string;
27    },
28    row: TraceRow<SnapshotStruct>
29  ): void {
30    let filter = row.dataListCache;
31    let maxValue = 0;
32    for (let item of filter) {
33      maxValue = Math.max(maxValue, item.value || 0);
34    }
35    snapshot(
36      filter,
37      maxValue,
38      TraceRow.range?.startNS ?? 0,
39      (TraceRow.range?.endNS ?? 0) - (TraceRow.range?.startNS! ?? 0),
40      row.frame
41    );
42    drawLoadingFrame(req.context, row.dataListCache, row);
43    req.context!.beginPath();
44    let find = false;
45    for (let re of filter) {
46      SnapshotStruct.draw(req.context, re);
47      if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) {
48        SnapshotStruct.hoverSnapshotStruct = re;
49        find = true;
50      }
51    }
52    if (!find && row.isHover) {
53      SnapshotStruct.hoverSnapshotStruct = undefined;
54    }
55    req.context!.closePath();
56  }
57}
58export function snapshot(
59  filter: Array<SnapshotStruct>,
60  maxValue: number,
61  startNs: number,
62  totalNs: number,
63  frame: Rect
64): void {
65  for (let file of filter) {
66    SnapshotStruct.setFrame(file, maxValue, startNs || 0, totalNs || 0, frame);
67  }
68}
69const padding = 2;
70export function SnapshotStructOnClick(clickRowType: string, sp: SpSystemTrace) {
71  return new Promise((resolve, reject) => {
72    if (SnapshotStruct.hoverSnapshotStruct) {
73      if (clickRowType === TraceRow.ROW_TYPE_SYS_MEMORY_GPU_TOTAL) {
74        displayGpuDumpTotalSheet(sp, reject);
75      } else if (clickRowType === TraceRow.ROW_TYPE_SYS_MEMORY_GPU_WINDOW) {
76        displayGpuDumpWindowSheet(sp, reject);
77      } else if (clickRowType === TraceRow.ROW_TYPE_VM_TRACKER_SMAPS) {
78        displaySmapsSheet(sp, reject);
79      }
80      if (clickRowType === TraceRow.ROW_TYPE_VMTRACKER_SHM) {
81        displayShmSheet(sp, reject);
82      }
83      if (clickRowType === TraceRow.ROW_TYPE_PURGEABLE_TOTAL_ABILITY) {
84        displayTotalAbilitySheet(sp, reject);
85      }
86      if (clickRowType === TraceRow.ROW_TYPE_PURGEABLE_PIN_ABILITY) {
87        displayPinAbilitySheet(sp, reject);
88      }
89      if (clickRowType === TraceRow.ROW_TYPE_PURGEABLE_TOTAL_VM) {
90        displayTotalVMSheet(sp, reject);
91      }
92      if (clickRowType === TraceRow.ROW_TYPE_PURGEABLE_PIN_VM) {
93        displayPinVMSheet(sp, reject);
94      }
95      if (clickRowType === TraceRow.ROW_TYPE_DMA_ABILITY) {
96        displayDmaAbilitySheet(sp, reject);
97      }
98      if (clickRowType === TraceRow.ROW_TYPE_DMA_VMTRACKER) {
99        displayDmaVmTrackerSheet(sp, reject);
100      }
101      if (clickRowType === TraceRow.ROW_TYPE_GPU_MEMORY_ABILITY) {
102        displayGpuMemoryAbilitySheet(sp, reject);
103      }
104      if (clickRowType === TraceRow.ROW_TYPE_GPU_MEMORY_VMTRACKER) {
105        displayGpuMemoryVmTrackerSheet(sp, reject);
106      }
107      if (clickRowType === TraceRow.ROW_TYPE_GPU_RESOURCE_VMTRACKER) {
108        displayGpuResourceSheet(sp);
109      } else {
110        resolve(null);
111      }
112    }
113  });
114}
115
116function displayGpuDumpTotalSheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
117  let gpuDumpTotalRow = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(
118    `trace-row[row-id='Skia Gpu Dump Total']`
119  );
120  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
121  sp.traceSheetEL?.displayGpuSelectedData(
122    'total',
123    SnapshotStruct.selectSnapshotStruct!.startNs,
124    gpuDumpTotalRow!.dataListCache
125  );
126  sp.timerShaftEL?.modifyFlagList(undefined);
127  reject();
128}
129
130function displayGpuDumpWindowSheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
131  let gpuDumpWindowRow = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(
132    `trace-row[row-id='Skia Gpu Dump Window']`
133  );
134  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
135  sp.traceSheetEL?.displayGpuSelectedData(
136    'window',
137    SnapshotStruct.selectSnapshotStruct!.startNs,
138    gpuDumpWindowRow!.dataListCache
139  );
140  sp.timerShaftEL?.modifyFlagList(undefined);
141  reject();
142}
143
144function displaySmapsSheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
145  let smapsRow = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(`trace-row[row-id='Dirty']`);
146  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
147  sp.traceSheetEL?.displaySmapsData(SnapshotStruct.selectSnapshotStruct!, smapsRow!.dataListCache);
148  reject();
149}
150
151function displayShmSheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
152  let shmRow = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(`trace-row[row-id='SHM']`);
153  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
154  sp.traceSheetEL?.displayShmData(SnapshotStruct.selectSnapshotStruct!, shmRow!.dataListCache);
155  reject();
156}
157
158function displayTotalAbilitySheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
159  let totalAbilityRow = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(
160    `trace-row[row-id='System Purgeable Total']`
161  );
162  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
163  sp.traceSheetEL?.displayPurgTotalAbilityData(SnapshotStruct.hoverSnapshotStruct!, totalAbilityRow!.dataListCache);
164  reject();
165}
166
167function displayPinAbilitySheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
168  let pinAbilityRow = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(
169    `trace-row[row-id='System Purgeable Pin']`
170  );
171  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
172  sp.traceSheetEL?.displayPurgPinAbilityData(SnapshotStruct.hoverSnapshotStruct!, pinAbilityRow!.dataListCache);
173  reject();
174}
175
176function displayTotalVMSheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
177  let totalVMRow = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(`trace-row[row-id='Purgeable Total']`);
178  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
179  sp.traceSheetEL?.displayPurgTotalVMData(SnapshotStruct.hoverSnapshotStruct!, totalVMRow!.dataListCache);
180  reject();
181}
182
183function displayPinVMSheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
184  let pinVMRow = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(`trace-row[row-id='Purgeable Pin']`);
185  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
186  sp.traceSheetEL?.displayPurgPinVMData(SnapshotStruct.hoverSnapshotStruct!, pinVMRow!.dataListCache);
187  reject();
188}
189
190function displayDmaAbilitySheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
191  let dmaAbilityRow = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(`trace-row[row-id='abilityMonitorDma']`);
192  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
193  sp.traceSheetEL?.displayDmaAbility(SnapshotStruct.selectSnapshotStruct!.startNs, dmaAbilityRow!.dataListCache);
194  reject();
195}
196
197function displayDmaVmTrackerSheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
198  let dmaVmTracker = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(`trace-row[row-type='dma-vmTracker']`);
199  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
200  sp.traceSheetEL?.displayDmaVmTracker(SnapshotStruct.selectSnapshotStruct!.startNs, dmaVmTracker!.dataListCache);
201  reject();
202}
203
204function displayGpuMemoryAbilitySheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
205  let gpuMemoryAbilityMonitor = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(
206    `trace-row[row-id='abilityMonitorGpuMemory']`
207  );
208  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
209  sp.traceSheetEL?.displayGpuMemoryAbility(
210    SnapshotStruct.selectSnapshotStruct!.startNs,
211    gpuMemoryAbilityMonitor!.dataListCache
212  );
213  reject();
214}
215
216function displayGpuMemoryVmTrackerSheet(sp: SpSystemTrace, reject: (reason?: any) => void) {
217  let gpuMemoryVmTracker = sp.shadowRoot?.querySelector<TraceRow<SnapshotStruct>>(
218    `trace-row[row-id='Skia Gpu Memory']`
219  );
220  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
221  sp.traceSheetEL?.displayGpuMemoryVmTracker(
222    SnapshotStruct.selectSnapshotStruct!.startNs,
223    gpuMemoryVmTracker!.dataListCache
224  );
225  reject();
226}
227
228function displayGpuResourceSheet(sp: SpSystemTrace) {
229  SnapshotStruct.selectSnapshotStruct = SnapshotStruct.hoverSnapshotStruct;
230  sp.traceSheetEL?.displayGpuResourceVmTracker(SnapshotStruct.selectSnapshotStruct!.startNs);
231}
232
233export class SnapshotStruct extends BaseStruct {
234  startNs: number = 0;
235  endNs: number = 0;
236  dur: number = 0;
237  name: string = '';
238  aSize: number = 0;
239  categoryNameId: number = 0;
240  textWidth: number = 0;
241  value: number = 0;
242  type: string = '';
243  static hoverSnapshotStruct: SnapshotStruct | undefined;
244  static selectSnapshotStruct: SnapshotStruct | undefined;
245  static setFrame(node: SnapshotStruct, maxValue: number, startNs: number, totalNs: number, frame: Rect): void {
246    node.frame = undefined;
247    frame.height = 40 - padding * 2;
248    // sample_interval单位是ms,startNs和endNs单位是纳秒,每一次采样的时间按采样间隔的五分之一算
249    node.dur = MemoryConfig.getInstance().snapshotDur;
250    node.endNs = node.startNs + node.dur;
251    if ((node.startNs - startNs || node.startNs - startNs === 0) && node.endNs - node.startNs) {
252      let rectangle: Rect = new Rect(
253        Math.floor(((node.startNs - startNs) / totalNs) * frame.width),
254        Math.floor(((maxValue - node.value) / maxValue) * frame.height),
255        Math.ceil(((node.endNs - node.startNs) / totalNs) * frame.width),
256        Math.ceil((node.value / maxValue) * frame.height)
257      );
258      node.frame = rectangle;
259    }
260    if (node.value === 0) {
261      let rectangle: Rect = new Rect(
262        Math.floor(((node.startNs - startNs) / totalNs) * frame.width),
263        30,
264        Math.ceil((node.dur / totalNs) * frame.width),
265        1
266      );
267      node.frame = rectangle;
268    }
269  }
270  static draw(ctx: CanvasRenderingContext2D, data: SnapshotStruct): void {
271    if (data.frame) {
272      ctx.fillStyle = 'rgb(86,192,197)';
273      ctx!.fillRect(data.frame!.x, data.frame!.y + padding, data.frame!.width, data.frame!.height);
274      if (data.frame!.width > 7) {
275        ctx.globalAlpha = 1.0;
276        ctx.lineWidth = 1;
277        ctx.fillStyle = '#fff';
278        ctx.textBaseline = 'middle';
279        if (data.frame!.height > 10 && data.frame!.height < 25) {
280          SnapshotStruct.drawString(ctx, data.name || '', 4, data.frame!, data, 4);
281        } else if (data.frame!.height >= 25) {
282          SnapshotStruct.drawString(ctx, data.name || '', 4, data.frame!, data, 4);
283          SnapshotStruct.drawString(ctx, Utils.getBinaryByteWithUnit(data.value || 0), 11, data.frame!, data, 2);
284        }
285      }
286      if (SnapshotStruct.selectSnapshotStruct && SnapshotStruct.equals(SnapshotStruct.selectSnapshotStruct, data)) {
287        ctx.strokeStyle = '#232c5d';
288        ctx.lineWidth = 2;
289        ctx.strokeRect(data.frame!.x, data.frame!.y + padding, data.frame!.width - 2, data.frame!.height);
290      }
291    }
292  }
293  /**
294   *
295   * @param ctx current context
296   * @param str text
297   * @param textPadding padding
298   * @param frame rectangle
299   * @param data PurgeableStruct
300   * @param location the position of the string, the bigger the numerical value, the higher the position on the canvas
301   */
302  static drawString(
303    ctx: CanvasRenderingContext2D,
304    str: string,
305    textPadding: number,
306    frame: Rect,
307    data: SnapshotStruct,
308    location: number
309  ): void {
310    if (data.textWidth === undefined) {
311      data.textWidth = ctx.measureText(str).width;
312    }
313    let textWidth = Math.round(data.textWidth / str.length);
314    let fillTextWidth = frame.width - textPadding * 2;
315    if (data.textWidth < fillTextWidth) {
316      let x = Math.floor(frame.width / 2 - data.textWidth / 2 + frame.x + textPadding);
317      ctx.fillText(str, x, Math.floor(frame.y + frame.height / location + textPadding), fillTextWidth);
318    } else {
319      if (fillTextWidth >= textWidth) {
320        let characterNum = fillTextWidth / textWidth;
321        let x = frame.x + textPadding;
322        if (characterNum < 2) {
323          ctx.fillText(
324            str.substring(0, 1),
325            x,
326            Math.floor(frame.y + frame.height / location + textPadding),
327            fillTextWidth
328          );
329        } else {
330          ctx.fillText(
331            `${str.substring(0, characterNum - 1)}...`,
332            x,
333            Math.floor(frame.y + frame.height / location + textPadding),
334            fillTextWidth
335          );
336        }
337      }
338    }
339  }
340  static equals(baseSnapshot: SnapshotStruct, targetSnapshot: SnapshotStruct): boolean {
341    return baseSnapshot === targetSnapshot;
342  }
343}
344