• 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 { Counter, SelectionData, SelectionParam } from '../../../../bean/BoxSelection';
19import { resizeObserver } from '../SheetUtils';
20import { getTabCounters } from '../../../../database/sql/Cpu.sql';
21
22@element('tabpane-counter')
23export class TabPaneCounter extends BaseElement {
24  private counterTbl: LitTable | null | undefined;
25  private counterRange: HTMLLabelElement | null | undefined;
26  private counterSource: Array<SelectionData> = [];
27  private currentSelectionParam: SelectionParam | undefined;
28
29  set data(counterParam: SelectionParam | unknown) {
30    if (this.currentSelectionParam === counterParam) {
31      return;
32    }
33    // @ts-ignore
34    this.currentSelectionParam = counterParam;
35    //@ts-ignore
36    this.counterTbl?.shadowRoot?.querySelector('.table')?.style?.height = `${this.parentElement!.clientHeight - 45}px`;
37    this.counterRange!.textContent = `Selected range: ${parseFloat(
38      // @ts-ignore
39      ((counterParam.rightNs - counterParam.leftNs) / 1000000.0).toFixed(5)
40    )} ms`;
41    this.counterTbl!.loading = true;
42    // @ts-ignore
43    getTabCounters(counterParam.processTrackIds, counterParam.virtualTrackIds, counterParam.rightNs).then((result) => {
44      this.counterTbl!.loading = false;
45      //@ts-ignore
46      if (result !== null && result.length > 0) {
47        let dataSource: Array<SelectionData> = [];
48        //@ts-ignore
49        let collect = this.groupByTrackIdToMap(result);
50        let sumCount = 0;
51        for (let key of collect.keys()) {
52          let counters = collect.get(key);
53          let list: Array<Counter> = [];
54          // @ts-ignore
55          let index = counters!.findIndex((item) => item.startTime >= counterParam.leftNs);
56          if (index !== -1) {
57            list = counters!.splice(index > 0 ? index - 1 : index);
58          } else {
59            list.push(counters![counters!.length - 1]);
60          }
61          // @ts-ignore
62          let sd = this.createSelectCounterData(list, counterParam.leftNs, counterParam.rightNs);
63          sumCount += Number.parseInt(sd.count);
64          dataSource.push(sd);
65        }
66        let sumData = new SelectionData();
67        sumData.count = sumCount.toString();
68        sumData.process = ' ';
69        dataSource.splice(0, 0, sumData);
70        this.counterSource = dataSource;
71        this.counterTbl!.recycleDataSource = dataSource;
72      } else {
73        this.counterSource = [];
74        this.counterTbl!.recycleDataSource = this.counterSource;
75      }
76    });
77  }
78
79  initElements(): void {
80    this.counterTbl = this.shadowRoot?.querySelector<LitTable>('#tb-counter');
81    this.counterRange = this.shadowRoot?.querySelector('#time-range');
82    this.counterTbl!.addEventListener('column-click', (evt) => {
83      // @ts-ignore
84      this.sortByColumn(evt.detail);
85    });
86  }
87
88  connectedCallback(): void {
89    super.connectedCallback();
90    resizeObserver(this.parentElement!, this.counterTbl!);
91  }
92
93  initHtml(): string {
94    return `
95        <style>
96        .counter-label{
97            width: 100%;
98        }
99        :host{
100            flex-direction: column;
101            display: flex;
102            padding: 10px 10px;
103        }
104        </style>
105        <label id="time-range" class="counter-label"
106        style="height: 20px;text-align: end;font-size: 10pt;margin-bottom: 5px">Selected range:0.0 ms</label>
107        <lit-table id="tb-counter" style="height: auto">
108            <lit-table-column width="25%" title="Name" data-index="name" key="name"  align="flex-start" order>
109            </lit-table-column>
110            <lit-table-column width="1fr" title="Delta value" data-index="delta" key="delta"  align="flex-start" order >
111            </lit-table-column>
112            <lit-table-column width="1fr" title="Rate /s" data-index="rate" key="rate"  align="flex-start" order >
113            </lit-table-column>
114            <lit-table-column width="1fr" title="Weighted avg value" data-index="avgWeight" key="avgWeight"
115            align="flex-start" order >
116            </lit-table-column>
117            <lit-table-column width="1fr" title="Count" data-index="count" key="count"  align="flex-start" order >
118            </lit-table-column>
119            <lit-table-column width="1fr" title="First value" data-index="first" key="first"  align="flex-start" order >
120            </lit-table-column>
121            <lit-table-column width="1fr" title="Last value" data-index="last" key="last"  align="flex-start" order >
122            </lit-table-column>
123            <lit-table-column width="1fr" title="Min value" data-index="min" key="min"  align="flex-start" order >
124            </lit-table-column>
125            <lit-table-column width="1fr" title="Max value" data-index="max" key="max"  align="flex-start" order >
126            </lit-table-column>
127        </lit-table>
128        `;
129  }
130
131  groupByTrackIdToMap(arr: Array<Counter>): Map<number, Array<Counter>> {
132    let map = new Map<number, Array<Counter>>();
133    for (let counter of arr) {
134      counter.name = counter.name.replace('sys.virtual.mem.', '');
135      if (map.has(counter.trackId)) {
136        map.get(counter.trackId)!.push(counter);
137      } else {
138        let list: Array<Counter> = [];
139        list.push(counter);
140        map.set(counter.trackId, list);
141      }
142    }
143    return map;
144  }
145
146  createSelectCounterData(list: Array<Counter>, leftNs: number, rightNs: number): SelectionData {
147    let counterData = new SelectionData();
148    if (list.length > 0) {
149      let range = rightNs - leftNs;
150      let first = list[0];
151      counterData.trackId = first.trackId;
152      counterData.name = first.name;
153      counterData.first = `${first.value}`;
154      counterData.count = `${list.length}`;
155      counterData.last = `${list[list.length - 1].value}`;
156      counterData.delta = `${parseInt(counterData.last) - parseInt(counterData.first)}`;
157      counterData.rate = (parseInt(counterData.delta) / ((range * 1.0) / 1000000000)).toFixed(4);
158      counterData.min = `${first.value}`;
159      counterData.max = '0';
160      let weightAvg = 0.0;
161      for (let i = 0; i < list.length; i++) {
162        let counter = list[i];
163        if (counter.value < parseInt(counterData.min)) {
164          counterData.min = counter.value.toString();
165        }
166        if (counter.value > parseInt(counterData.max)) {
167          counterData.max = counter.value.toString();
168        }
169        let start = i === 0 ? leftNs : counter.startTime;
170        let end = i === list.length - 1 ? rightNs : list[i + 1].startTime;
171        weightAvg += counter.value * (((end - start) * 1.0) / range);
172      }
173      counterData.avgWeight = weightAvg.toFixed(2);
174    }
175    return counterData;
176  }
177
178  sortByColumn(detail: unknown): void {
179    // @ts-ignore
180    function compare(property, sort, type) {
181      return function (counterLeftData: SelectionData, counterRightData: SelectionData) {
182        if (counterLeftData.process === ' ' || counterRightData.process === ' ') {
183          return 0;
184        }
185        if (type === 'number') {
186          return sort === 2 // @ts-ignore
187            ? parseFloat(counterRightData[property]) - parseFloat(counterLeftData[property]) // @ts-ignore
188            : parseFloat(counterLeftData[property]) - parseFloat(counterRightData[property]);
189        } else {
190          // @ts-ignore
191          if (counterRightData[property] > counterLeftData[property]) {
192            return sort === 2 ? 1 : -1;
193          } else {
194            // @ts-ignore
195            if (counterRightData[property] === counterLeftData[property]) {
196              return 0;
197            } else {
198              return sort === 2 ? -1 : 1;
199            }
200          }
201        }
202      };
203    }
204
205    // @ts-ignore
206    if (detail.key === 'name') {
207      // @ts-ignore
208      this.counterSource.sort(compare(detail.key, detail.sort, 'string'));
209    } else {
210      // @ts-ignore
211      this.counterSource.sort(compare(detail.key, detail.sort, 'number'));
212    }
213    this.counterTbl!.recycleDataSource = this.counterSource;
214  }
215}
216