• 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 { BaseElement, element } from '../../../../../base-ui/BaseElement';
17import { LitTable } from '../../../../../base-ui/table/lit-table';
18import { SelectionParam } from '../../../../bean/BoxSelection';
19import { NativeHookMalloc, NativeHookStatisticsTableData } from '../../../../bean/NativeHook';
20import { Utils } from '../../base/Utils';
21import { SpSystemTrace } from '../../../SpSystemTrace';
22import '../TabProgressBar';
23import { SpNativeMemoryChart } from '../../../chart/SpNativeMemoryChart';
24import { resizeObserver } from '../SheetUtils';
25import { TabPaneNMSampleList } from './TabPaneNMSampleList';
26import {
27  queryNativeHookStatistics,
28  queryNativeHookStatisticsMalloc,
29  queryNativeHookStatisticsSubType,
30} from '../../../../database/sql/NativeHook.sql';
31
32@element('tabpane-native-statistics')
33export class TabPaneNMStatstics extends BaseElement {
34  private nativeStatisticsTbl: LitTable | null | undefined;
35  private nativeStatisticsSource: Array<NativeHookStatisticsTableData> = [];
36  private nativeType: Array<string> = ['All Heap & Anonymous VM', 'All Heap', 'All Anonymous VM'];
37  private allMax: number = 0;
38  private sortColumn: string = '';
39  private sortType: number = 0;
40  private currentSelection: SelectionParam | undefined;
41  private currentSelectIPid = 1;
42
43  set data(nativeStatisticsParam: SelectionParam) {
44    if (nativeStatisticsParam === this.currentSelection) {
45      return;
46    }
47    this.currentSelectIPid = nativeStatisticsParam.nativeMemoryCurrentIPid;
48    this.currentSelection = nativeStatisticsParam;
49    this.allMax = 0;
50    TabPaneNMSampleList.clearData();
51    SpNativeMemoryChart.EVENT_HEAP.map((heap) => {
52      this.allMax += heap.sumHeapSize;
53    });
54    if (nativeStatisticsParam.nativeMemory.length > 0) {
55      Utils.getInstance().setCurrentSelectIPid(this.currentSelectIPid);
56      Utils.getInstance().initResponseTypeList(nativeStatisticsParam);
57    }
58    if (this.nativeStatisticsTbl) {
59      // @ts-ignore
60      this.nativeStatisticsTbl.shadowRoot.querySelector('.table').style.height = `${
61        this.parentElement!.clientHeight - 25
62      }px`;
63      // @ts-ignore
64      this.nativeStatisticsTbl.recycleDataSource = [];
65    }
66    this.nativeStatisticsTbl!.loading = true;
67    this.queryData(nativeStatisticsParam);
68  }
69
70  queryData(nativeStatisticsParam: SelectionParam): void {
71    Promise.all([
72      queryNativeHookStatistics(nativeStatisticsParam.leftNs, nativeStatisticsParam.rightNs, this.currentSelectIPid),
73      queryNativeHookStatisticsSubType(
74        nativeStatisticsParam.leftNs,
75        nativeStatisticsParam.rightNs,
76        this.currentSelectIPid
77      ),
78      queryNativeHookStatisticsMalloc(
79        nativeStatisticsParam.leftNs,
80        nativeStatisticsParam.rightNs,
81        this.currentSelectIPid
82      ),
83    ]).then((values) => {
84      this.nativeStatisticsTbl!.loading = false;
85      let arr: Array<NativeHookStatisticsTableData> = [];
86      let index1 = nativeStatisticsParam.nativeMemory.indexOf(this.nativeType[0]);
87      let index2 = nativeStatisticsParam.nativeMemory.indexOf(this.nativeType[1]);
88      let index3 = nativeStatisticsParam.nativeMemory.indexOf(this.nativeType[2]);
89      this.setMemoryTypeData(nativeStatisticsParam, values[0], arr);
90      if (index1 !== -1 || index3 !== -1) {
91        this.setSubTypeTableData(values[1], arr);
92      }
93      let type = 0;
94      if (index1 !== -1 || (index2 !== -1 && index3 !== -1)) {
95        type = 0;
96      } else {
97        type = index2 !== -1 ? 1 : 2;
98      }
99      this.setMallocTableData(values[2], arr, type);
100      this.nativeStatisticsSource = arr;
101      this.sortByColumn(this.sortColumn, this.sortType);
102    });
103  }
104
105  setMallocTableData(result: Array<NativeHookMalloc>, arr: Array<NativeHookStatisticsTableData>, type: number): void {
106    result.map((malloc) => {
107      let data = new NativeHookStatisticsTableData();
108      if (malloc.eventType === 'AllocEvent') {
109        data.memoryTap = `Malloc ${Utils.getByteWithUnit(malloc.heapSize)}`;
110      } else {
111        data.memoryTap = `Mmap ${Utils.getByteWithUnit(malloc.heapSize)}`;
112      }
113      data.existing = malloc.allocByte - malloc.freeByte;
114      data.allocCount = malloc.allocCount - malloc.freeCount;
115      data.freeCount = malloc.freeCount;
116      data.freeByte = malloc.freeByte;
117      data.totalBytes = malloc.allocByte;
118      data.totalCount = malloc.allocCount;
119      data.max = malloc.heapSize;
120      data.existingString = Utils.getByteWithUnit(data.existing);
121      data.freeByteString = Utils.getByteWithUnit(malloc.freeByte);
122      data.totalBytesString = Utils.getByteWithUnit(data.totalBytes);
123      data.maxStr = Utils.getByteWithUnit(malloc.heapSize);
124      data.existingValue = [data.existing, data.totalBytes, this.allMax];
125      if (type === 0) {
126        arr.push(data);
127      } else if (type === 1 && malloc.eventType === 'AllocEvent') {
128        arr.push(data);
129      } else if (type === 2 && malloc.eventType === 'MmapEvent') {
130        arr.push(data);
131      } else {
132      }
133    });
134  }
135
136  setSubTypeTableData(result: Array<NativeHookMalloc>, arr: Array<NativeHookStatisticsTableData>): void {
137    result.map((sub) => {
138      let subType = SpSystemTrace.DATA_DICT.get(sub.subTypeId);
139      if (subType !== null && subType !== undefined) {
140        let data = new NativeHookStatisticsTableData();
141        data.memoryTap = subType;
142        data.existing = sub.allocByte - sub.freeByte;
143        data.allocCount = sub.allocCount - sub.freeCount;
144        data.freeCount = sub.freeCount;
145        data.freeByte = sub.freeByte;
146        data.totalBytes = sub.allocByte;
147        data.totalCount = sub.allocCount;
148        data.max = sub.max;
149        data.freeByteString = Utils.getByteWithUnit(sub.freeByte);
150        data.existingString = Utils.getByteWithUnit(data.existing);
151        data.totalBytesString = Utils.getByteWithUnit(data.totalBytes);
152        data.maxStr = Utils.getByteWithUnit(sub.max);
153        data.existingValue = [data.existing, data.totalBytes, this.allMax];
154        arr.push(data);
155      }
156    });
157  }
158
159  setMemoryTypeData(
160    val: SelectionParam,
161    result: Array<NativeHookMalloc>,
162    arr: Array<NativeHookStatisticsTableData>
163  ): void {
164    let all: NativeHookStatisticsTableData | null = null;
165    let heap: NativeHookStatisticsTableData | null = null;
166    let anonymous: NativeHookStatisticsTableData | null = null;
167    if (val.nativeMemory.indexOf(this.nativeType[0]) !== -1) {
168      all = new NativeHookStatisticsTableData();
169      all.memoryTap = this.nativeType[0];
170    }
171    if (val.nativeMemory.indexOf(this.nativeType[1]) !== -1) {
172      heap = new NativeHookStatisticsTableData();
173      heap.memoryTap = this.nativeType[1];
174    }
175    if (val.nativeMemory.indexOf(this.nativeType[2]) !== -1) {
176      anonymous = new NativeHookStatisticsTableData();
177      anonymous.memoryTap = this.nativeType[2];
178    }
179    for (let hook of result) {
180      if (all !== null) {
181        this.processHookData(hook, all);
182      }
183      if (heap !== null && hook.eventType === 'AllocEvent') {
184        this.processHookData(hook, heap);
185      }
186      if (anonymous !== null && hook.eventType === 'MmapEvent') {
187        this.processHookData(hook, anonymous);
188      }
189    }
190    if (all !== null) {
191      this.updateHookData(all, arr);
192    }
193    if (heap !== null) {
194      this.updateHookData(heap, arr);
195    }
196    if (anonymous !== null) {
197      this.updateHookData(anonymous, arr);
198    }
199  }
200
201  private processHookData(hook: unknown, data: NativeHookStatisticsTableData): void {
202    // @ts-ignore
203    data.totalBytes += hook.allocByte;
204    // @ts-ignore
205    data.totalCount += hook.allocCount;
206    // @ts-ignore
207    data.freeByte += hook.freeByte;
208    // @ts-ignore
209    data.freeCount += hook.freeCount; // @ts-ignore
210    if (hook.max > data.max) {
211      // @ts-ignore
212      data.max = hook.max;
213      data.maxStr = Utils.getByteWithUnit(data.max);
214    }
215  }
216
217  private updateHookData(data: NativeHookStatisticsTableData, arr: Array<NativeHookStatisticsTableData>): void {
218    data.existing = data.totalBytes - data.freeByte;
219    data.allocCount = data.totalCount - data.freeCount;
220    data.existingString = Utils.getByteWithUnit(data.existing);
221    data.totalBytesString = Utils.getByteWithUnit(data.totalBytes);
222    data.freeByteString = Utils.getByteWithUnit(data.freeByte);
223    data.existingValue = [data.existing, data.totalBytes, this.allMax];
224    arr.push(data);
225  }
226
227  initElements(): void {
228    this.nativeStatisticsTbl = this.shadowRoot?.querySelector<LitTable>('#tb-native-statstics');
229    this.nativeStatisticsTbl!.addEventListener('column-click', (evt) => {
230      // @ts-ignore
231      this.sortByColumn(evt.detail.key, evt.detail.sort);
232    });
233    this.nativeStatisticsTbl!.exportTextHandleMap.set('existingString', (value) => {
234      // @ts-ignore
235      return `${value.existing}`;
236    });
237    this.nativeStatisticsTbl!.exportTextHandleMap.set('freeByteString', (value) => {
238      // @ts-ignore
239      return `${value.totalBytes - value.existing}`;
240    });
241    this.nativeStatisticsTbl!.exportTextHandleMap.set('totalBytesString', (value) => {
242      // @ts-ignore
243      return `${value.totalBytes}`;
244    });
245    this.nativeStatisticsTbl!.exportTextHandleMap.set('maxStr', (value) => {
246      // @ts-ignore
247      return `${value.max}`;
248    });
249  }
250
251  connectedCallback(): void {
252    super.connectedCallback();
253    resizeObserver(this.parentElement!, this.nativeStatisticsTbl!, 25);
254  }
255
256  sortByColumn(nmStatColumn: string, nmStatSort: number): void {
257    this.sortColumn = nmStatColumn;
258    this.sortType = nmStatSort;
259    if (nmStatSort === 0) {
260      this.nativeStatisticsTbl!.recycleDataSource = this.nativeStatisticsSource;
261    } else {
262      let arr = [...this.nativeStatisticsSource];
263      let compareFunction = (
264        nativeStatisticsLeftData: unknown,
265        nativeStatisticsRightData: unknown,
266        column: string,
267        sortType: number
268      ): number => {
269        if (sortType === 1) {
270          // @ts-ignore
271          return nativeStatisticsLeftData[column] - nativeStatisticsRightData[column];
272        } else {
273          // @ts-ignore
274          return nativeStatisticsRightData[column] - nativeStatisticsLeftData[column];
275        }
276      };
277
278      let columnMap: { [key: string]: string } = {
279        existingString: 'existing',
280        allocCount: 'allocCount',
281        freeByteString: 'totalBytes',
282        freeCount: 'freeCount',
283        totalBytesString: 'totalBytes',
284        maxStr: 'max',
285        totalCount: 'totalCount',
286      };
287      let sortColumnKey = columnMap[nmStatColumn];
288      this.nativeStatisticsTbl!.recycleDataSource = arr.sort((leftData, rightData) =>
289        compareFunction(leftData, rightData, sortColumnKey, nmStatSort)
290      );
291    }
292  }
293
294  initHtml(): string {
295    return `
296<style>
297.nm-stat-tbl {
298    height: auto
299}
300:host{
301    display: flex;
302    flex-direction: column;
303    padding: 10px 10px;
304}
305</style>
306<lit-table id="tb-native-statstics" class="nm-stat-tbl">
307    <lit-table-column class="nm-stat-column" width="25%" title="Memory Type"
308    data-index="memoryTap" key="memoryTap"  align="flex-start"></lit-table-column>
309    <lit-table-column class="nm-stat-column" width="1fr" title="Existing"
310    data-index="existingString" key="existingString"  align="flex-start" order></lit-table-column>
311    <lit-table-column class="nm-stat-column" width="1fr" title="# Existing"
312    data-index="allocCount" key="allocCount"  align="flex-start" order></lit-table-column>
313    <lit-table-column class="nm-stat-column" width="1fr" title="Transient"
314    data-index="freeByteString" key="freeByteString"  align="flex-start" order></lit-table-column>
315    <lit-table-column class="nm-stat-column" width="1fr" title="# Transient"
316    data-index="freeCount" key="freeCount"  align="flex-start" order></lit-table-column>
317    <lit-table-column class="nm-stat-column" width="1fr" title="Total Bytes"
318    data-index="totalBytesString" key="totalBytesString"  align="flex-start" order></lit-table-column>
319    <lit-table-column class="nm-stat-column" width="1fr" title="# Total"
320    data-index="totalCount" key="totalCount"  align="flex-start" order></lit-table-column>
321    <lit-table-column class="nm-stat-column" width="1fr" title="Peak Value"
322    data-index="maxStr" key="maxStr"  align="flex-start" order></lit-table-column>
323    <lit-table-column class="nm-stat-column" width="160px" title="Existing / Total"
324    data-index="existingValue" key="existingValue"  align="flex-start" >
325    <template><tab-progress-bar data="{{existingValue}}"></tab-progress-bar></template>
326    </lit-table-column>
327</lit-table>
328        `;
329  }
330}
331