• 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 { SelectionData, SelectionParam } from '../../../../bean/BoxSelection';
19import { XpowerThreadInfoStruct } from '../../../../database/ui-worker/ProcedureWorkerXpowerThreadInfo';
20import { SortDetail, resizeObserver } from '../SheetUtils';
21
22@element('tabpane-xpower-thread-load')
23export class TabPaneXpowerThreadLoad extends BaseElement {
24  private XpowerThreadLoadTbl: LitTable | null | undefined;
25  private XpowerThreadLoadRange: HTMLLabelElement | null | undefined;
26  private XpowerThreadLoadSource: Array<SelectionData> = [];
27  private sumCount: number = 0;
28  private tabTitle: HTMLDivElement | undefined | null;
29
30  set data(XpowerThreadLoadValue: SelectionParam) {
31    this.init();
32    this.XpowerThreadLoadTbl!.shadowRoot!.querySelector<HTMLDivElement>('.table')!.style!.height = `${
33      this.parentElement!.clientHeight - 45
34    }px`;
35    this.XpowerThreadLoadRange!.textContent = `Selected range: ${parseFloat(
36      ((XpowerThreadLoadValue.rightNs - XpowerThreadLoadValue.leftNs) / 1000000.0).toFixed(5)
37    )} ms`;
38    this.getThreadLoadData(XpowerThreadLoadValue).then();
39  }
40
41  async getThreadLoadData(XpowerThreadLoadValue: SelectionParam): Promise<void> {
42    this.sumCount = 0;
43    let dataSource: SelectionData[] = [];
44    let collect = XpowerThreadLoadValue.xpowerThreadLoadMapData;
45    this.XpowerThreadLoadTbl!.loading = true;
46    for (let key of collect.keys()) {
47      let threadInfos = collect.get(key);
48      let res = (await threadInfos?.({
49        startNS: XpowerThreadLoadValue.leftNs,
50        endNS: XpowerThreadLoadValue.rightNs,
51        queryAll: true,
52      })) as XpowerThreadInfoStruct[];
53      let sd = this.createSelectThreadLoadData(res || []);
54      dataSource = dataSource.concat(sd);
55    }
56    this.XpowerThreadLoadTbl!.loading = false;
57    this.XpowerThreadLoadSource = dataSource;
58    this.XpowerThreadLoadTbl!.recycleDataSource = dataSource;
59  }
60
61  private init(): void {
62    const thTable = this.tabTitle!.querySelector('.th');
63    const list = thTable!.querySelectorAll('div');
64    if (this.tabTitle!.hasAttribute('sort')) {
65      this.tabTitle!.removeAttribute('sort');
66      list.forEach((item) => {
67        item.querySelectorAll('svg').forEach((svg) => {
68          svg.style.display = 'none';
69        });
70      });
71    }
72  }
73
74  initElements(): void {
75    this.XpowerThreadLoadTbl = this.shadowRoot?.querySelector<LitTable>('#tb-thread-info');
76    this.tabTitle = this.XpowerThreadLoadTbl!.shadowRoot?.querySelector('.thead') as HTMLDivElement;
77    this.XpowerThreadLoadRange = this.shadowRoot?.querySelector('#time-range');
78    this.XpowerThreadLoadTbl!.addEventListener('column-click', (evt): void => {
79      // @ts-ignore
80      this.sortByColumn(evt.detail);
81    });
82  }
83
84  connectedCallback(): void {
85    super.connectedCallback();
86    resizeObserver(this.parentElement!, this.XpowerThreadLoadTbl!);
87  }
88
89  initHtml(): string {
90    return `
91        <style>
92        .xpower-thread-info-label{
93            margin-bottom: 5px;
94        }
95        :host{
96            padding: 10px 10px;
97            display: flex;
98            flex-direction: column;
99        }
100        </style>
101        <label id="time-range" class="xpower-thread-info-label" style="width: 100%;height: 20px;text-align: end;font-size: 10pt;">Selected range:0.0 ms</label>
102        <lit-table id="tb-thread-info" style="height: auto">
103            <lit-table-column order title="ThreadName" data-index="name" key="name"  align="flex-start" width="25%">
104            </lit-table-column>
105            <lit-table-column data-index="count" title="Count" order key="count"  align="flex-start" width="1fr">
106            </lit-table-column>
107            <lit-table-column title="Avg Load(%)" data-index="avgNumber" order key="avgNumber"  align="flex-start" width="1fr">
108            </lit-table-column>
109            <lit-table-column title="Max Load(%)" align="flex-start" order data-index="maxNumber" key="maxNumber" width="1fr">
110            </lit-table-column>
111            <lit-table-column title="Min Load(%)" key="minNumber" data-index="minNumber" order align="flex-start" width="1fr">
112            </lit-table-column>
113        </lit-table>
114        `;
115  }
116
117  private createSelectThreadLoadData(list: Array<XpowerThreadInfoStruct>): SelectionData[] {
118    let SelectThreadLoadArray: SelectionData[] = [];
119    if (list.length > 0) {
120      let threadInfoMap = new Map();
121      list.forEach((item) => {
122        // 如果value为0,泳道不显示,tab也不显示该线程
123        if (item.value > 0) {
124          if (threadInfoMap.has(item.threadName)) {
125            const data = threadInfoMap.get(item.threadName)!;
126            data.push(item);
127          } else {
128            const data: XpowerThreadInfoStruct[] = [];
129            data.push(item);
130            threadInfoMap.set(item.threadName, data);
131          }
132        }
133      });
134      for (let itemArray of threadInfoMap.values()) {
135        let SelectThreadLoadData = new SelectionData();
136        let max = 0;
137        let min = 0;
138        let sum = 0;
139        SelectThreadLoadData.name = itemArray[0].threadName;
140        SelectThreadLoadData.count = itemArray.length;
141        if (itemArray.length > 1) {
142          max = itemArray.map((item: { value: number }) => item.value).reduce((a: number, b: number) => Math.max(a, b));
143          min = itemArray.map((item: { value: number }) => item.value).reduce((a: number, b: number) => Math.min(a, b));
144          sum = itemArray.reduce((acc: number, obj: { value: number }) => acc + obj.value, 0);
145          SelectThreadLoadData.avgNumber = parseFloat((sum / itemArray.length).toFixed(2));
146          SelectThreadLoadData.maxNumber = max;
147          SelectThreadLoadData.minNumber = min;
148        } else if (itemArray.length === 1) {
149          let value = itemArray[0].value;
150          SelectThreadLoadData.avgNumber = value;
151          SelectThreadLoadData.maxNumber = value;
152          SelectThreadLoadData.minNumber = value;
153        }
154        this.sumCount += itemArray.length;
155        SelectThreadLoadArray.push(SelectThreadLoadData);
156      }
157    }
158    return SelectThreadLoadArray;
159  }
160
161  private sortByColumn(detail: SortDetail): void {
162    function compare(property: string | number, sort: number, type: string) {
163      return function (xpowerThreadLoadLeftData: SelectionData, xpowerThreadLoadRightData: SelectionData): number {
164        if (xpowerThreadLoadLeftData.process === ' ' || xpowerThreadLoadRightData.process === ' ') {
165          return 0;
166        }
167        if (type === 'number') {
168          return sort === 2 // @ts-ignore
169            ? parseFloat(xpowerThreadLoadRightData[property]) - parseFloat(xpowerThreadLoadLeftData[property]) // @ts-ignore
170            : parseFloat(xpowerThreadLoadLeftData[property]) - parseFloat(xpowerThreadLoadRightData[property]);
171        } else {
172          // @ts-ignore
173          if (xpowerThreadLoadRightData[property] > xpowerThreadLoadLeftData[property]) {
174            return sort === 2 ? 1 : -1;
175          } else {
176            // @ts-ignore
177            if (xpowerThreadLoadRightData[property] === xpowerThreadLoadLeftData[property]) {
178              return 0;
179            } else {
180              return sort === 2 ? -1 : 1;
181            }
182          }
183        }
184      };
185    }
186    if (detail.key === 'name') {
187      this.XpowerThreadLoadSource.sort(compare(detail.key, detail.sort, 'string'));
188    } else {
189      this.XpowerThreadLoadSource.sort(compare(detail.key, detail.sort, 'number'));
190    }
191    this.XpowerThreadLoadTbl!.recycleDataSource = this.XpowerThreadLoadSource;
192  }
193}
194