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