• 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 { SpSystemTrace } from '../SpSystemTrace.js';
17import {
18  queryBootTime,
19  queryHeapGroupByEvent,
20  queryNativeHookProcess,
21  queryNativeHookStatisticsCount,
22  queryNativeMemoryRealTime,
23} from '../../database/SqlLite.js';
24import { TraceRow } from '../trace/base/TraceRow.js';
25import { info } from '../../../log/Log.js';
26import { procedurePool } from '../../database/Procedure.js';
27import { NativeEventHeap } from '../../bean/NativeHook.js';
28import { HeapRender, HeapStruct } from '../../database/ui-worker/ProcedureWorkerHeap.js';
29import { Utils } from '../trace/base/Utils.js';
30import { renders } from '../../database/ui-worker/ProcedureWorker.js';
31import { EmptyRender } from '../../database/ui-worker/ProcedureWorkerCPU.js';
32
33export class SpNativeMemoryChart {
34  static EVENT_HEAP: Array<NativeEventHeap> = [];
35  static REAL_TIME_DIF: number = 0;
36  private trace: SpSystemTrace;
37
38  constructor(trace: SpSystemTrace) {
39    this.trace = trace;
40  }
41
42  initChart = async () => {
43    let time = new Date().getTime();
44    let nativeMemoryType = 'native_hook';
45    let nmsCount = await queryNativeHookStatisticsCount();
46    if (nmsCount && nmsCount[0] && (nmsCount[0] as any).num > 0) {
47      nativeMemoryType = 'native_hook_statistic';
48    }
49    let nativeProcess = await queryNativeHookProcess(nativeMemoryType);
50    info('NativeHook Process data size is: ', nativeProcess!.length);
51    if (nativeProcess.length == 0) {
52      return;
53    }
54    await this.initNativeMemory();
55    SpNativeMemoryChart.EVENT_HEAP = await queryHeapGroupByEvent(nativeMemoryType);
56    let nativeRow = TraceRow.skeleton();
57    let process = '';
58    if (nativeProcess.length > 0) {
59      process = ` ${nativeProcess[0].pid}`;
60    }
61    nativeRow.rowId = `native-memory`;
62    nativeRow.index = 0;
63    nativeRow.rowType = TraceRow.ROW_TYPE_NATIVE_MEMORY;
64    nativeRow.drawType = 0;
65    nativeRow.style.height = '40px';
66    nativeRow.rowParentId = '';
67    nativeRow.folder = true;
68    nativeRow.name = `Native Memory` + process;
69    nativeRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
70    nativeRow.selectChangeHandler = this.trace.selectChangeHandler;
71    nativeRow.rowSetting = 'enable';
72    nativeRow.rowSettingPopoverDirection = 'bottomLeft';
73    nativeRow.rowSettingList = [
74      {
75        key: '0',
76        title: 'Current Bytes',
77        checked: true,
78      },
79      {
80        key: '1',
81        title: 'Native Memory Density'
82      }
83    ]
84    nativeRow.onRowSettingChangeHandler = (value) => {
85      nativeRow.childrenList.forEach((row) => (row.drawType = parseInt(value[0])));
86      this.trace.favoriteRowsEL?.querySelectorAll<TraceRow<any>>(`trace-row[row-type='heap']`).forEach((it) => {
87        it.drawType = parseInt(value[0]);
88      });
89      this.trace.refreshCanvas(false);
90    }
91    nativeRow.supplier = () => new Promise<Array<any>>((resolve) => resolve([]));
92    nativeRow.onThreadHandler = (useCache) => {
93      nativeRow.canvasSave(this.trace.canvasPanelCtx!);
94      if (nativeRow.expansion) {
95        this.trace.canvasPanelCtx?.clearRect(0, 0, nativeRow.frame.width, nativeRow.frame.height);
96      } else {
97        (renders['empty'] as EmptyRender).renderMainThread(
98          {
99            context: this.trace.canvasPanelCtx,
100            useCache: useCache,
101            type: ``,
102          },
103          nativeRow
104        );
105      }
106      nativeRow.canvasRestore(this.trace.canvasPanelCtx!);
107    };
108    this.trace.rowsEL?.appendChild(nativeRow);
109    /**
110     * 添加heap信息
111     */
112    let native_memory = ['All Heap & Anonymous VM', 'All Heap', 'All Anonymous VM'];
113    for (let i = 0; i < native_memory.length; i++) {
114      let nm = native_memory[i];
115      let allHeapRow = TraceRow.skeleton<HeapStruct>();
116      allHeapRow.index = i;
117      allHeapRow.rowParentId = `native-memory`;
118      allHeapRow.rowHidden = !nativeRow.expansion;
119      allHeapRow.style.height = '40px';
120      allHeapRow.name = nm;
121      allHeapRow.rowId = nm;
122      allHeapRow.drawType = 0;
123      allHeapRow.isHover = true;
124      allHeapRow.folder = false;
125      allHeapRow.rowType = TraceRow.ROW_TYPE_HEAP;
126      allHeapRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
127      allHeapRow.selectChangeHandler = this.trace.selectChangeHandler;
128      allHeapRow.setAttribute('heap-type', nativeMemoryType);
129      allHeapRow.setAttribute('children', '');
130      allHeapRow.focusHandler = () => {
131        let tip = '';
132        if (HeapStruct.hoverHeapStruct) {
133          if (allHeapRow.drawType === 1) {
134            tip = `<span>${HeapStruct.hoverHeapStruct.density}</span>`;
135          } else {
136            tip = `<span>${Utils.getByteWithUnit(HeapStruct.hoverHeapStruct.heapsize!)}</span>`;
137          }
138        }
139        this.trace?.displayTip(allHeapRow, HeapStruct.hoverHeapStruct, tip);
140      };
141      allHeapRow.supplier = () => {
142        return nativeMemoryType === 'native_hook'
143          ? this.getNativeMemoryDataByChartType(i, allHeapRow.drawType)
144          : this.getNativeMemoryStatisticByChartType(i - 1);
145      };
146      allHeapRow.onThreadHandler = (useCache) => {
147        let context = allHeapRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
148        allHeapRow.canvasSave(context);
149        (renders['heap'] as HeapRender).renderMainThread(
150          {
151            context: context,
152            useCache: useCache,
153            type: `heap`,
154          },
155          allHeapRow
156        );
157        allHeapRow.canvasRestore(context);
158      };
159      nativeRow.addChildTraceRow(allHeapRow);
160    }
161    let durTime = new Date().getTime() - time;
162    info('The time to load the Native Memory data is: ', durTime);
163  };
164
165  getNativeMemoryStatisticByChartType = async (chartType: number): Promise<Array<HeapStruct>> => {
166    let nmStatisticArray: Array<HeapStruct> = [];
167    await new Promise<Array<HeapStruct>>((resolve, reject) => {
168      procedurePool.submitWithName(
169        'logic1',
170        'native-memory-queryNativeHookStatistic',
171        { type: chartType, totalNS: TraceRow.range?.totalNS! },
172        undefined,
173        (res: any) => {
174          nmStatisticArray = nmStatisticArray.concat(res.data);
175          res.data = null;
176          if (res.tag == 'end') {
177            resolve(nmStatisticArray);
178          }
179        }
180      );
181    });
182    return nmStatisticArray;
183  };
184
185  getNativeMemoryDataByChartType = async (nativeMemoryType: number, chartType: number): Promise<Array<HeapStruct>> => {
186    let args = new Map<string, any>();
187    args.set('nativeMemoryType', nativeMemoryType);
188    args.set('chartType', chartType);
189    args.set('totalNS', TraceRow.range?.totalNS!);
190    args.set('actionType', 'memory-chart');
191    let nmArray: Array<HeapStruct> = [];
192    await new Promise<Array<HeapStruct>>((resolve, reject) => {
193      procedurePool.submitWithName('logic1', 'native-memory-chart-action', args, undefined, (res: any) => {
194        nmArray = nmArray.concat(res.data);
195        res.data = null;
196        if (res.tag == 'end') {
197          resolve(nmArray);
198        }
199      });
200    });
201    return nmArray;
202  };
203
204  initNativeMemory = async () => {
205    let time = new Date().getTime();
206    let isRealtime = false;
207    let realTimeDif = 0;
208    SpNativeMemoryChart.REAL_TIME_DIF = 0;
209    let queryTime = await queryNativeMemoryRealTime();
210    let bootTime = await queryBootTime();
211    if (queryTime.length > 0) {
212      isRealtime = queryTime[0].clock_name == 'realtime';
213    }
214    if (bootTime.length > 0 && isRealtime) {
215      realTimeDif = queryTime[0].ts - bootTime[0].ts;
216      SpNativeMemoryChart.REAL_TIME_DIF = realTimeDif;
217    }
218    await new Promise<any>((resolve, reject) => {
219      procedurePool.submitWithName(
220        'logic1',
221        'native-memory-init',
222        { isRealtime, realTimeDif, dataDict: SpSystemTrace.DATA_DICT },
223        undefined,
224        (res: any) => {
225          resolve(res);
226        }
227      );
228    });
229    let durTime = new Date().getTime() - time;
230    info('The time to init the native memory data is: ', durTime);
231  };
232}
233