• 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 { type LitTable } from '../../../../../base-ui/table/lit-table';
18import { type SelectionParam } from '../../../../bean/BoxSelection';
19import { MemoryConfig } from '../../../../bean/MemoryConfig';
20import { Utils } from '../../base/Utils';
21import { resizeObserver } from '../SheetUtils';
22import { querySysPurgeableTab } from '../../../../database/sql/Ability.sql';
23import { queryProcessPurgeableTab } from '../../../../database/sql/ProcessThread.sql';
24
25@element('tabpane-purg-total')
26export class TabPanePurgTotal extends BaseElement {
27  private purgeableTotalTable: LitTable | null | undefined;
28  private purgeableTotalSource: Array<PurgeableTabStruct> = [];
29  private tabTitle: HTMLDivElement | undefined | null;
30  private purgTotalTimeRange: HTMLLabelElement | undefined | null;
31  private sortKey = 'avgSize';
32  private sortType = 2;
33
34  set data(selection: SelectionParam) {
35    if (this.purgeableTotalTable) {
36      //@ts-ignore
37      this.purgeableTotalTable.shadowRoot?.querySelector('.table').style.height = `${
38        this.parentElement!.clientHeight - 45
39      }px`;
40    }
41    this.init();
42    this.purgTotalTimeRange!.textContent =
43      'Selected range: ' + ((selection.rightNs - selection.leftNs) / 1000000.0).toFixed(5) + ' ms';
44    this.purgeableTotalTable!.loading = true;
45    this.purgeableTotalTable!.recycleDataSource = [];
46    // 框选了 Purgeable Total
47    if (selection.purgeableTotalAbility.length > 0) {
48      this.purgeableTotalSource = [];
49      querySysPurgeableTab(
50        selection.leftNs,
51        selection.rightNs,
52        (MemoryConfig.getInstance().interval * 1000000) / 5
53      ).then((purgeTotalResults) => {
54        this.purgeableTotalTable!.loading = false;
55        this.getPurgeableTotalSource(purgeTotalResults);
56      });
57    } else if (selection.purgeableTotalVM.length > 0) {
58      this.purgeableTotalSource = [];
59      queryProcessPurgeableTab(
60        selection.leftNs,
61        selection.rightNs,
62        (MemoryConfig.getInstance().interval * 1000000) / 5,
63        MemoryConfig.getInstance().iPid
64      ).then((results) => {
65        this.purgeableTotalTable!.loading = false;
66        this.getPurgeableTotalSource(results);
67      });
68    }
69  }
70
71  getPurgeableTotalSource(results: unknown): void {
72    // @ts-ignore
73    if (results.length > 0) {
74      // @ts-ignore
75      for (let i = 0; i < results.length; i++) {
76        // @ts-ignore
77        this.purgeableTotalSource.push(
78          // @ts-ignore
79          this.toTabStruct(results[i].name, results[i].maxSize, results[i].minSize, results[i].avgSize)
80        );
81      }
82      this.sortByColumn({ key: this.sortKey, sort: this.sortType });
83      let total = this.totalData(this.purgeableTotalSource);
84      this.purgeableTotalSource.unshift(total);
85      this.purgeableTotalTable!.recycleDataSource = this.purgeableTotalSource;
86      this.purgeableTotalSource.shift();
87    } else {
88      this.purgeableTotalSource = [];
89      this.purgeableTotalTable!.recycleDataSource = [];
90    }
91  }
92
93  private init(): void {
94    const thTable = this.tabTitle!.querySelector('.th');
95    const purgeTotalTblNode = thTable!.querySelectorAll('div');
96    if (this.tabTitle!.hasAttribute('sort')) {
97      this.tabTitle!.removeAttribute('sort');
98      purgeTotalTblNode.forEach((item) => {
99        item.querySelectorAll('svg').forEach((svg) => {
100          svg.style.display = 'none';
101        });
102      });
103    }
104    this.sortKey = 'avgSize';
105    this.sortType = 2;
106  }
107
108  private toTabStruct(type: string, maxSize: number, minSize: number, avgSize: number): PurgeableTabStruct {
109    const tabStruct = new PurgeableTabStruct(
110      type,
111      maxSize,
112      minSize,
113      avgSize,
114      Utils.getBinaryByteWithUnit(avgSize),
115      Utils.getBinaryByteWithUnit(maxSize),
116      Utils.getBinaryByteWithUnit(minSize)
117    );
118    return tabStruct;
119  }
120
121  private totalData(source: Array<PurgeableTabStruct>): PurgeableTabStruct {
122    // 计算总的time作为表格的第一行显示
123    let totalAvg = 0;
124    let totalMax = 0;
125    let totalMin = 0;
126    for (let item of source) {
127      totalAvg += item.avgSize;
128      totalMax += item.maxSize;
129      totalMin += item.minSize;
130    }
131    let totalData = this.toTabStruct('Total', totalAvg, totalMax, totalMin);
132    return totalData;
133  }
134
135  private sortByColumn(detail: unknown): void {
136    // @ts-ignore
137    function compare(key, sort, type) {
138      return function (purgeTotalLeftData: unknown, purgeTotalRightData: unknown) {
139        // 不管哪一列的排序方式是0(默认排序),都按照avgSize列从大到小排序
140        if (sort === 0) {
141          sort = 2;
142          key = 'avgSize';
143          type = 'number';
144        }
145        if (type === 'number') {
146          // @ts-ignore
147          return sort === 2 // @ts-ignore
148            ? parseFloat(purgeTotalRightData[key]) - parseFloat(purgeTotalLeftData[key]) // @ts-ignore
149            : parseFloat(purgeTotalLeftData[key]) - parseFloat(purgeTotalRightData[key]);
150        } else {
151          if (sort === 2) {
152            // @ts-ignore
153            return purgeTotalRightData[key].toString().localeCompare(purgeTotalLeftData[key].toString());
154          } else {
155            // @ts-ignore
156            return purgeTotalLeftData[key].toString().localeCompare(purgeTotalRightData[key].toString());
157          }
158        }
159      };
160    }
161    // @ts-ignore
162    if (detail.key === 'type') {
163      // @ts-ignore
164      this.purgeableTotalSource.sort(compare(detail.key, detail.sort, 'string'));
165    } else {
166      // @ts-ignore
167      this.purgeableTotalSource.sort(compare(detail.key, detail.sort, 'number'));
168    }
169    let total = this.totalData(this.purgeableTotalSource);
170    this.purgeableTotalSource.unshift(total);
171    this.purgeableTotalTable!.recycleDataSource = this.purgeableTotalSource;
172    this.purgeableTotalSource.shift();
173  }
174
175  initElements(): void {
176    this.purgeableTotalTable = this.shadowRoot?.querySelector<LitTable>('#tb-purgeable-total');
177    this.tabTitle = this.purgeableTotalTable!.shadowRoot?.querySelector('.thead') as HTMLDivElement;
178    this.purgTotalTimeRange = this.shadowRoot?.querySelector('#purg-total-time-range') as HTMLLabelElement;
179    this.purgeableTotalTable!.addEventListener('column-click', (evt: unknown) => {
180      // @ts-ignore
181      this.sortKey = evt.detail.key; // @ts-ignore
182      this.sortType = evt.detail.sort;
183      // @ts-ignore
184      this.sortByColumn(evt.detail);
185    });
186  }
187
188  connectedCallback(): void {
189    super.connectedCallback();
190    resizeObserver(this.parentElement!, this.purgeableTotalTable!);
191  }
192
193  initHtml(): string {
194    return `
195        <style>
196        :host{
197            display: flex;
198            flex-direction: column;
199            padding: 10px 10px;
200        }
201        .purg-total-label{
202            display: flex;
203            height: 20px;
204            align-items: center;
205            flex-direction: row;
206            margin-bottom: 5px;
207        }
208        #purg-total-time-range{
209            width: auto;
210            text-align: end;
211            font-size: 10pt;
212        }
213        </style>
214        <div class="purg-total-label">
215            <div style="flex: 1"></div>
216            <label id="purg-total-time-range">Selected range:0.0 ms</label>
217        </div>
218        <lit-table id="tb-purgeable-total" style="height: auto">
219            <lit-table-column width="1fr" title="Type" data-index="type" key="type"  align="flex-start" order>
220            </lit-table-column>
221            <lit-table-column width="1fr" title="AvgSize" data-index="avgSizeStr" key="avgSize"  align="flex-start" order>
222            </lit-table-column>
223            <lit-table-column width="1fr" title="MaxSize" data-index="maxSizeStr" key="maxSize"  align="flex-start" order>
224            </lit-table-column>
225            <lit-table-column width="1fr" title="MinSize" data-index="minSizeStr" key="minSize"  align="flex-start" order>
226            </lit-table-column>
227        </lit-table>
228        `;
229  }
230}
231
232export class PurgeableTabStruct {
233  type: string;
234  avgSize: number;
235  maxSize: number;
236  minSize: number;
237  avgSizeStr: string;
238  maxSizeStr: string;
239  minSizeStr: string;
240
241  constructor(
242    type: string,
243    avgSize: number,
244    maxSize: number,
245    minSize: number,
246    avgSizeStr: string,
247    maxSizeStr: string,
248    minSizeStr: string
249  ) {
250    this.type = type;
251    this.avgSize = avgSize;
252    this.maxSize = maxSize;
253    this.minSize = minSize;
254    this.avgSizeStr = avgSizeStr;
255    this.maxSizeStr = maxSizeStr;
256    this.minSizeStr = minSizeStr;
257  }
258}
259