• 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 { procedurePool } from '../../database/Procedure';
19import { info } from '../../../log/Log';
20import '../../../base-ui/chart/pie/LitChartPie';
21import { LitChartPie } from '../../../base-ui/chart/pie/LitChartPie';
22import { LitSelect } from '../../../base-ui/select/LitSelect';
23import { LitSelectOption } from '../../../base-ui/select/LitSelectOption';
24import '../../../base-ui/progress-bar/LitProgressBar';
25import { LitProgressBar } from '../../../base-ui/progress-bar/LitProgressBar';
26import './TableNoData';
27import { TableNoData } from './TableNoData';
28import { getProbablyTime } from '../../database/logic-worker/ProcedureLogicWorkerCommon';
29import { queryThreads } from '../../database/sql/ProcessThread.sql';
30import { Top20FrequencyThreadHtml } from './Top20FrequencyThread.html';
31
32@element('top20-frequency-thread')
33export class Top20FrequencyThread extends BaseElement {
34  static threads: { id: number; tid: number; name: string }[] | undefined;
35  traceChange: boolean = false;
36  private frequencyThreadTbl: LitTable | null | undefined;
37  private threadSelect: LitSelect | null | undefined;
38  private frequencyThreadPie: LitChartPie | null | undefined;
39  private currentThread: HTMLDivElement | null | undefined;
40  private frequencyThreadProgress: LitProgressBar | null | undefined;
41  private nodata: TableNoData | null | undefined;
42  private currentTid: number = 0;
43  private frequencyThreadData: Array<unknown> = [];
44  private sortColumn: string = '';
45  private sortType: number = 0;
46
47  initElements(): void {
48    this.nodata = this.shadowRoot!.querySelector<TableNoData>('#nodata');
49    this.frequencyThreadProgress = this.shadowRoot!.querySelector<LitProgressBar>('#loading');
50    this.frequencyThreadTbl = this.shadowRoot!.querySelector<LitTable>('#tb-process-thread-count');
51    this.currentThread = this.shadowRoot!.querySelector<HTMLDivElement>('#current_thread');
52    this.threadSelect = this.shadowRoot!.querySelector<LitSelect>('#thread_select');
53    this.frequencyThreadPie = this.shadowRoot!.querySelector<LitChartPie>('#pie');
54
55    this.threadSelect!.onchange = (e): void => {
56      //@ts-ignore
57      this.currentThread!.textContent = (e as unknown).detail.text; //@ts-ignore
58      this.currentTid = parseInt((e as unknown).detail.value);
59      this.frequencyThreadProgress!.loading = true;
60      this.queryData();
61    };
62
63    this.frequencyThreadTbl!.addEventListener('row-click', (evt: unknown): void => {
64      //@ts-ignore
65      let data = evt.detail.data;
66      data.isSelected = true; //@ts-ignore
67      if ((evt.detail as unknown).callBack) {
68        //@ts-ignore
69        (evt.detail as unknown).callBack(true);
70      }
71    });
72
73    this.frequencyThreadTbl!.addEventListener('column-click', (evt: unknown): void => {
74      //@ts-ignore
75      this.sortColumn = evt.detail.key; //@ts-ignore
76      this.sortType = evt.detail.sort;
77      // @ts-ignore
78      this.sortByColumn(evt.detail);
79    });
80    this.frequencyThreadTbl!.addEventListener('row-hover', (evt: unknown): void => {
81      //@ts-ignore
82      if (evt.detail.data) {
83        //@ts-ignore
84        let data = evt.detail.data;
85        data.isHover = true; //@ts-ignore
86        if ((evt.detail as unknown).callBack) {
87          //@ts-ignore
88          (evt.detail as unknown).callBack(true);
89        }
90      }
91      this.frequencyThreadPie?.showHover();
92    }); // @ts-ignore
93    this.frequencyThreadTbl!.itemTextHandleMap.set('freq', (value) => (value === -1 ? 'unknown' : value));
94  }
95
96  sortByColumn(detail: unknown): void {
97    // @ts-ignore
98    function compare(frequencyThreadProperty, sort, type) {
99      return function (a: unknown, b: unknown) {
100        if (type === 'number') {
101          // @ts-ignore
102          return sort === 2
103            ? // @ts-ignore
104              parseFloat(b[frequencyThreadProperty]) - parseFloat(a[frequencyThreadProperty])
105            : //@ts-ignore
106              parseFloat(a[frequencyThreadProperty]) - parseFloat(b[frequencyThreadProperty]);
107        } else {
108          if (sort === 2) {
109            //@ts-ignore
110            return b[frequencyThreadProperty].toString().localeCompare(a[frequencyThreadProperty].toString());
111          } else {
112            //@ts-ignore
113            return a[frequencyThreadProperty].toString().localeCompare(b[frequencyThreadProperty].toString());
114          }
115        }
116      };
117    }
118
119    //@ts-ignore
120    if (detail.key === 'timeStr') {
121      //@ts-ignore
122      detail.key = 'time'; //@ts-ignore
123      this.frequencyThreadData.sort(compare(detail.key, detail.sort, 'number')); //@ts-ignore
124    } else if (detail.key === 'no' || detail.key === 'cpu' || detail.key === 'freq' || detail.key === 'ratio') {
125      //@ts-ignore
126      this.frequencyThreadData.sort(compare(detail.key, detail.sort, 'number'));
127    } else {
128      //@ts-ignore
129      this.frequencyThreadData.sort(compare(detail.key, detail.sort, 'string'));
130    }
131    this.frequencyThreadTbl!.recycleDataSource = this.frequencyThreadData;
132  }
133
134  async init(): Promise<void> {
135    if (!this.traceChange) {
136      if (this.frequencyThreadTbl!.recycleDataSource.length > 0) {
137        this.frequencyThreadTbl?.reMeauseHeight();
138      }
139      return;
140    }
141    this.traceChange = false;
142    this.frequencyThreadProgress!.loading = true;
143    if (Top20FrequencyThread.threads === undefined) {
144      //@ts-ignore
145      Top20FrequencyThread.threads = (await queryThreads()) || [];
146      this.nodata!.noData = Top20FrequencyThread.threads === undefined || Top20FrequencyThread.threads.length === 0;
147      this.threadSelect!.innerHTML = ''; //@ts-ignore
148      let threads = Top20FrequencyThread.threads.map((it) => {
149        let option = new LitSelectOption();
150        option.setAttribute('value', `${it.tid}`);
151        option.textContent = it.name;
152        return option;
153      });
154      this.threadSelect!.append(...threads);
155      this.threadSelect?.initOptions(); //@ts-ignore
156      this.threadSelect!.value = `${Top20FrequencyThread.threads[0].tid}`; //@ts-ignore
157      this.currentThread!.textContent = Top20FrequencyThread.threads[0].name; //@ts-ignore
158      this.currentTid = Top20FrequencyThread.threads[0].tid;
159      this.queryData();
160    }
161  }
162
163  queryData(): void {
164    this.queryLogicWorker('scheduling-Thread Freq', 'query Thread Top 20 Frequency Time:', (res): void => {
165      this.nodata!.noData =
166        Top20FrequencyThread.threads === undefined ||
167        Top20FrequencyThread.threads.length === 0 ||
168        res === undefined || //@ts-ignore
169        res.length === 0;
170      (res as unknown[]).map((it: unknown, index: number): void => {
171        //@ts-ignore
172        it.no = index + 1;
173      }); //@ts-ignore
174      this.frequencyThreadData = res;
175      if (this.sortColumn !== '') {
176        this.sortByColumn({
177          key: this.sortColumn,
178          sort: this.sortType,
179        });
180      } else {
181        //@ts-ignore
182        this.frequencyThreadTbl!.recycleDataSource = res;
183      }
184      this.frequencyThreadTbl!.reMeauseHeight();
185      this.setThreadPieConfig(res);
186      this.frequencyThreadProgress!.loading = false;
187      this.shadowRoot!.querySelector('#tb_vessel')!.scrollTop = 0;
188    });
189  }
190
191  private setThreadPieConfig(res: unknown): void {
192    this.frequencyThreadPie!.config = {
193      appendPadding: 10, //@ts-ignore
194      data: this.getPieChartData(res),
195      angleField: 'time',
196      colorField: 'freq',
197      colorFieldTransferHandler: (value) => (value === -1 ? 'unknown' : value),
198      radius: 0.8,
199      label: {
200        type: 'outer',
201      },
202      tip: (obj): string => {
203        return `<div>
204                             <div>freq:${
205                               // @ts-ignore
206                               obj.obj.freq === -1 ? 'unknown' : obj.obj.freq
207                             }</div>
208                             <div>cpu:${
209                               // @ts-ignore
210                               obj.obj.cpu
211                             }</div>
212                             <div>time:${
213                               // @ts-ignore
214                               obj.obj.timeStr
215                             }</div>
216                             <div>ratio:${
217                               // @ts-ignore
218                               obj.obj.ratio
219                             }%</div>
220                        </div>
221                `;
222      },
223      hoverHandler: (data): void => {
224        if (data) {
225          this.frequencyThreadTbl!.setCurrentHover(data);
226        } else {
227          this.frequencyThreadTbl!.mouseOut();
228        }
229      },
230      interactions: [
231        {
232          type: 'element-active',
233        },
234      ],
235    };
236  }
237
238  getPieChartData(res: unknown[]): unknown[] {
239    if (res.length > 20) {
240      let pieChartArr: unknown[] = [];
241      let other: unknown = {
242        cpu: '-',
243        freq: 'other',
244        time: 0,
245        ratio: '0',
246        totalDur: 0,
247      };
248      for (let i = 0; i < res.length; i++) {
249        if (i < 19) {
250          pieChartArr.push(res[i]);
251        } else {
252          //@ts-ignore
253          other.time += res[i].time; //@ts-ignore
254          other.timeStr = getProbablyTime(other.time); //@ts-ignore
255          other.totalDur = res[i].totalDur; //@ts-ignore
256          other.ratio = ((other.time / other.totalDur) * 100).toFixed(2);
257        }
258      }
259      pieChartArr.push(other);
260      return pieChartArr;
261    }
262    return res;
263  }
264
265  clearData(): void {
266    this.traceChange = true;
267    this.threadSelect!.innerHTML = '';
268    this.frequencyThreadPie!.dataSource = [];
269    this.frequencyThreadTbl!.recycleDataSource = [];
270  }
271
272  queryLogicWorker(option: string, log: string, handler: (res: unknown) => void): void {
273    let frequencyThreadTime = new Date().getTime();
274    procedurePool.submitWithName('logic0', option, { tid: this.currentTid }, undefined, handler);
275    let durTime = new Date().getTime() - frequencyThreadTime;
276    info(log, durTime);
277  }
278
279  initHtml(): string {
280    return Top20FrequencyThreadHtml;
281  }
282}
283