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