• 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 { LitChartColumn } from '../../../base-ui/chart/column/LitChartColumn.js';
19import '../../../base-ui/chart/column/LitChartColumn.js';
20import './CheckCpuSetting.js';
21import '../../../base-ui/icon/LitIcon.js';
22import { CheckCpuSetting } from './CheckCpuSetting.js';
23import { procedurePool } from '../../database/Procedure.js';
24import { info } from '../../../log/Log.js';
25import '../../../base-ui/progress-bar/LitProgressBar.js';
26import { LitProgressBar } from '../../../base-ui/progress-bar/LitProgressBar.js';
27import './TableNoData.js';
28import { TableNoData } from './TableNoData.js';
29import { getProbablyTime } from '../../database/logic-worker/ProcedureLogicWorkerCommon.js';
30import { SpSchedulingAnalysis } from './SpSchedulingAnalysis.js';
31
32@element('top20-thread-cpu-usage')
33export class Top20ThreadCpuUsage extends BaseElement {
34  traceChange: boolean = false;
35  private table: LitTable | null | undefined;
36  private tableBig: LitTable | null | undefined;
37  private tableMid: LitTable | null | undefined;
38  private tableSmall: LitTable | null | undefined;
39  private chartTotal: LitChartColumn | null | undefined;
40  private chart2: LitChartColumn | null | undefined;
41  private chart3: LitChartColumn | null | undefined;
42  private chart4: LitChartColumn | null | undefined;
43  private cpuSetting: CheckCpuSetting | undefined | null;
44  private setting: HTMLDivElement | null | undefined;
45  private progress: LitProgressBar | null | undefined;
46  private nodata: TableNoData | null | undefined;
47  private map: Map<string, { chart: LitChartColumn; table: LitTable }> | undefined;
48  private data: Array<any> = [];
49  private dataBig: Array<any> = [];
50  private dataMid: Array<any> = [];
51  private dataSmall: Array<any> = [];
52  private sort: any = {
53    total: { key: '', sort: 0 },
54    small: { key: '', sort: 0 },
55    mid: { key: '', sort: 0 },
56    big: { key: '', sort: 0 },
57  };
58
59  private publicColumns = `
60                <lit-table-column width="50px" title=" " data-index="no" key="no" align="flex-start"></lit-table-column>
61                <lit-table-column width="50px" title="" data-index="visible" key="visible" align="flex-start">
62                    <template>
63                        <lit-icon name="{{ visible === 1 ? 'eye':'eye-close' }}" onclick="{
64                            let data = this.parentElement.parentElement.data;
65                            data.visible = data.visible === 1 ? 0 : 1
66                            this.name = data.visible === 1 ? 'eye':'eye-close'
67                            data.hideHandler()
68                        }" size="20"></lit-icon>
69                    </template>
70                </lit-table-column>
71                <lit-table-column width="100px" title="tid" data-index="tid" key="tid" align="flex-start" order></lit-table-column>
72                <lit-table-column width="200px" title="t_name" data-index="tName" key="tName" align="flex-start" order></lit-table-column>
73                <lit-table-column width="100px" title="pid" data-index="pid" key="pid" align="flex-start" order></lit-table-column>
74                <lit-table-column width="200px" title="p_name" data-index="pName" key="pName" align="flex-start" order></lit-table-column>
75        `;
76  private bigColumn = `
77                <lit-table-column width="100px" title="big core" data-index="bigTimeStr" key="bigTimeStr" align="flex-start" order></lit-table-column>
78                <lit-table-column width="100px" title="%" data-index="bigPercent" key="bigPercent" align="flex-start" order></lit-table-column>
79        `;
80  private midColumn = `
81                <lit-table-column width="100px" title="middle core" data-index="midTimeStr" key="midTimeStr" align="flex-start" order></lit-table-column>
82                <lit-table-column width="100px" title="%" data-index="midPercent" key="midPercent" align="flex-start" order></lit-table-column>
83        `;
84  private smallColumn = `
85                <lit-table-column width="100px" title="small core" data-index="smallTimeStr" key="smallTimeStr" align="flex-start" order></lit-table-column>
86                <lit-table-column width="100px" title="%" data-index="smallPercent" key="smallPercent" align="flex-start" order></lit-table-column>
87        `;
88
89  initElements(): void {
90    this.nodata = this.shadowRoot!.querySelector<TableNoData>('#nodata');
91    this.progress = this.shadowRoot!.querySelector<LitProgressBar>('#loading');
92    this.table = this.shadowRoot!.querySelector<LitTable>('#tb-thread-usage');
93    this.tableBig = this.shadowRoot!.querySelector<LitTable>('#tb-thread-big');
94    this.tableMid = this.shadowRoot!.querySelector<LitTable>('#tb-thread-mid');
95    this.tableSmall = this.shadowRoot!.querySelector<LitTable>('#tb-thread-small');
96    this.chartTotal = this.shadowRoot!.querySelector<LitChartColumn>('#chart_total');
97    this.chart2 = this.shadowRoot!.querySelector<LitChartColumn>('#chart_2');
98    this.chart3 = this.shadowRoot!.querySelector<LitChartColumn>('#chart_3');
99    this.chart4 = this.shadowRoot!.querySelector<LitChartColumn>('#chart_4');
100    this.map = new Map<string, { chart: LitChartColumn; table: LitTable }>();
101    this.map.set('total', { chart: this.chartTotal!, table: this.table! });
102    this.map.set('small', { chart: this.chart2!, table: this.tableSmall! });
103    this.map.set('mid', { chart: this.chart3!, table: this.tableMid! });
104    this.map.set('big', { chart: this.chart4!, table: this.tableBig! });
105    this.setting = this.shadowRoot!.querySelector<HTMLDivElement>('#setting');
106    this.cpuSetting = this.shadowRoot!.querySelector<CheckCpuSetting>('#cpu_setting');
107    this.cpuSetting!.cpuSetListener = () => {
108      this.cpuSetting!.style.display = 'none';
109      (this.shadowRoot!.querySelector('#total')! as any).style.display = 'grid';
110      (this.shadowRoot!.querySelector('#small')! as any).style.display =
111        CheckCpuSetting.small_cores.length > 0 ? 'grid' : 'none';
112      (this.shadowRoot!.querySelector('#mid')! as any).style.display =
113        CheckCpuSetting.mid_cores.length > 0 ? 'grid' : 'none';
114      (this.shadowRoot!.querySelector('#big')! as any).style.display =
115        CheckCpuSetting.big_cores.length > 0 ? 'grid' : 'none';
116      this.queryData();
117    };
118    this.setting?.addEventListener('click', (event) => {
119      for (let node of this.shadowRoot!.querySelectorAll('.content_grid')) {
120        (node as any).style.display = 'none';
121      }
122      this.cpuSetting!.style.display = 'inline';
123      this.cpuSetting?.init();
124    });
125
126    for (let key of this.map!.keys()) {
127      let tab = this.map!.get(key)!.table;
128      let chart = this.map!.get(key)!.chart;
129      tab!.addEventListener('row-click', (evt: any) => {
130        let data = evt.detail.data;
131        data.isSelected = true;
132        // @ts-ignore
133        if ((evt.detail as any).callBack) {
134          // @ts-ignore
135          (evt.detail as any).callBack(true);
136        }
137      });
138      tab!.addEventListener('column-click', (evt: any) => {
139        this.sort[key].key = evt.detail.key;
140        this.sort[key].sort = evt.detail.sort;
141        if (key == 'total') {
142          this.sortByColumn(evt.detail, tab, this.data);
143        } else if (key == 'small') {
144          this.sortByColumn(evt.detail, tab, this.dataSmall);
145        } else if (key == 'mid') {
146          this.sortByColumn(evt.detail, tab, this.dataMid);
147        } else if (key == 'big') {
148          this.sortByColumn(evt.detail, tab, this.dataBig);
149        }
150      });
151      tab!.addEventListener('row-hover', (evt: any) => {
152        if (evt.detail.data) {
153          let data = evt.detail.data;
154          data.isHover = true;
155          if ((evt.detail as any).callBack) {
156            (evt.detail as any).callBack(true);
157          }
158          chart.showHoverColumn(data.no);
159        }
160      });
161    }
162  }
163
164  sortByColumn(detail: any, table: LitTable | null | undefined, data: Array<any>) {
165    // @ts-ignore
166    function compare(threadCpuUsageProperty, sort, type) {
167      return function (a: any, b: any) {
168        if (type === 'number') {
169          // @ts-ignore
170          return sort === 2
171            ? parseFloat(b[threadCpuUsageProperty]) - parseFloat(a[threadCpuUsageProperty])
172            : parseFloat(a[threadCpuUsageProperty]) - parseFloat(b[threadCpuUsageProperty]);
173        } else {
174          if (sort === 2) {
175            return b[threadCpuUsageProperty].toString().localeCompare(a[threadCpuUsageProperty].toString());
176          } else {
177            return a[threadCpuUsageProperty].toString().localeCompare(b[threadCpuUsageProperty].toString());
178          }
179        }
180      };
181    }
182    let type = 'number';
183
184    if (detail.key === 'bigTimeStr') {
185      detail.key = 'big';
186    } else if (detail.key === 'midTimeStr') {
187      detail.key = 'mid';
188    } else if (detail.key === 'smallTimeStr') {
189      detail.key = 'small';
190    } else if (
191      detail.key === 'bigPercent' ||
192      detail.key === 'ratio' ||
193      detail.key === 'tid' ||
194      detail.key === 'pid' ||
195      detail.key === 'midPercent' ||
196      detail.key.includes('cpu')
197    ) {
198    } else {
199      type = 'string';
200    }
201    data.sort(compare(detail.key, detail.sort, type));
202    table!.recycleDataSource = data;
203  }
204
205  init() {
206    if (!this.traceChange) {
207      for (let key of this.map!.keys()) {
208        this.map!.get(key)!.table.reMeauseHeight();
209      }
210      return;
211    }
212    this.traceChange = false;
213    for (let key of this.map!.keys()) {
214      let table = this.map!.get(key)!.table;
215      table.innerHTML = '';
216      let columns = this.getTableColumns(key);
217      for (let i = 0; i < SpSchedulingAnalysis.cpuCount; i++) {
218        columns = `
219                ${columns}
220                <lit-table-column width="120px" title="cpu${i}(us)" data-index="cpu${i}" key="cpu${i}" align="flex-start" order></lit-table-column>
221            `;
222      }
223      table.innerHTML = columns;
224    }
225
226    if (!CheckCpuSetting.init_setting) {
227      for (let node of this.shadowRoot!.querySelectorAll('.content_grid')) {
228        (node as any).style.display = 'none';
229      }
230      this.cpuSetting!.style.display = 'inline';
231      this.cpuSetting?.init();
232    } else {
233      this.queryData();
234    }
235  }
236
237  clearData() {
238    this.traceChange = true;
239    for (let key of this.map!.keys()) {
240      this.map!.get(key)!.chart.dataSource = [];
241      this.map!.get(key)!.table.recycleDataSource = [];
242    }
243  }
244
245  queryData() {
246    this.progress!.loading = true;
247    this.queryLogicWorker(`scheduling-Thread CpuUsage`, `query Thread Cpu Usage Analysis Time:`, (res) => {
248      this.nodata!.noData = res.keys().length === 0;
249      for (let key of this.map!.keys()) {
250        let obj = this.map!.get(key)!;
251        let source: any[] = res.get(key) || [];
252        source = source.map((it: any, index: number) => {
253          let data: any = {
254            pid: it.pid,
255            pName: it.pName,
256            tid: it.tid,
257            tName: it.tName,
258            total: it.total,
259            big: it.big,
260            mid: it.mid,
261            small: it.small,
262            no: index + 1,
263            visible: 1,
264            bigPercent: it.bigPercent,
265            midPercent: it.midPercent,
266            smallPercent: it.smallPercent,
267            bigTimeStr: it.bigTimeStr,
268            midTimeStr: it.midTimeStr,
269            smallTimeStr: it.smallTimeStr,
270            hideHandler: () => {
271              let arr = source.filter((o) => o.visible === 1);
272              obj.chart.dataSource = this.getArrayDataBySize(key, arr);
273            },
274          };
275          for (let i = 0; i < SpSchedulingAnalysis.cpuCount; i++) {
276            data[`cpu${i}`] = (it[`cpu${i}`] || 0) / 1000;
277          }
278          return data;
279        });
280        obj.chart.config = {
281          data: this.getArrayDataBySize(key, source),
282          appendPadding: 10,
283          xField: 'tid',
284          yField: 'total',
285          seriesField: key === 'total' ? 'size' : '',
286          color: (a) => {
287            if (a.size === 'big core') {
288              return '#2f72f8';
289            } else if (a.size === 'middle core') {
290              return '#ffab67';
291            } else if (a.size === 'small core') {
292              return '#a285d2';
293            } else {
294              return '#0a59f7';
295            }
296          },
297          hoverHandler: (no) => {
298            let data = source.find((it) => it.no === no);
299            if (data) {
300              data.isHover = true;
301              obj.table!.setCurrentHover(data);
302            } else {
303              obj.table!.mouseOut();
304            }
305          },
306          tip: (a) => {
307            if (a && a[0]) {
308              let tip = '';
309              let total = 0;
310              for (let obj of a) {
311                total += obj.obj.total;
312                tip = `${tip}
313                                <div style="display:flex;flex-direction: row;align-items: center;">
314                                    <div style="width: 10px;height: 5px;background-color: ${
315                                      obj.color
316                                    };margin-right: 5px"></div>
317                                    <div>${obj.type || key}:${obj.obj.timeStr}</div>
318                                </div>
319                            `;
320              }
321              tip = `<div>
322                                        <div>tid:${a[0].obj.tid}</div>
323                                        ${tip}
324                                        ${a.length > 1 ? `<div>total:${getProbablyTime(total)}</div>` : ''}
325                                    </div>`;
326              return tip;
327            } else {
328              return '';
329            }
330          },
331          label: null,
332        };
333        if (key == 'total') {
334          this.data = source;
335        } else if (key == 'small') {
336          this.dataSmall = source;
337        } else if (key == 'mid') {
338          this.dataMid = source;
339        } else if (key == 'big') {
340          this.dataBig = source;
341        }
342        if (this.sort[key].key != '') {
343          this.sortByColumn(this.sort[key], obj.table, source);
344        } else {
345          obj.table.recycleDataSource = source;
346        }
347      }
348      this.progress!.loading = false;
349    });
350  }
351
352  getArrayDataBySize(type: string, arr: Array<any>) {
353    let data: any[] = [];
354    for (let obj of arr) {
355      if (type === 'total') {
356        data.push({
357          pid: obj.pid,
358          pName: obj.pName,
359          tid: obj.tid,
360          tName: obj.tName,
361          total: obj.big,
362          size: 'big core',
363          no: obj.no,
364          timeStr: obj.bigTimeStr,
365        });
366        data.push({
367          pid: obj.pid,
368          pName: obj.pName,
369          tid: obj.tid,
370          tName: obj.tName,
371          total: obj.mid,
372          size: 'middle core',
373          no: obj.no,
374          timeStr: obj.midTimeStr,
375        });
376        data.push({
377          pid: obj.pid,
378          pName: obj.pName,
379          tid: obj.tid,
380          tName: obj.tName,
381          total: obj.small,
382          size: 'small core',
383          no: obj.no,
384          timeStr: obj.smallTimeStr,
385        });
386      } else {
387        data.push({
388          pid: obj.pid,
389          pName: obj.pName,
390          tid: obj.tid,
391          tName: obj.tName,
392          total: obj[type],
393          no: obj.no,
394          timeStr: obj[`${type}TimeStr`],
395        });
396      }
397    }
398    return data;
399  }
400
401  queryLogicWorker(option: string, log: string, handler: (res: any) => void) {
402    let time = new Date().getTime();
403    procedurePool.submitWithName(
404      'logic1',
405      option,
406      {
407        bigCores: CheckCpuSetting.big_cores,
408        midCores: CheckCpuSetting.mid_cores,
409        smallCores: CheckCpuSetting.small_cores,
410      },
411      undefined,
412      handler
413    );
414    let durTime = new Date().getTime() - time;
415    info(log, durTime);
416  }
417
418  getTableColumns(type: string) {
419    if (type === 'total') {
420      return `${this.publicColumns}${this.bigColumn}${this.midColumn}${this.smallColumn}`;
421    } else if (type === 'big') {
422      return `${this.publicColumns}${this.bigColumn}`;
423    } else if (type === 'mid') {
424      return `${this.publicColumns}${this.midColumn}`;
425    } else if (type === 'small') {
426      return `${this.publicColumns}${this.smallColumn}`;
427    } else {
428      return '';
429    }
430  }
431
432  initHtml(): string {
433    return `
434        <style>
435        .content_grid{
436            display: grid;
437            padding: 15px;
438            grid-column-gap: 15px;
439            grid-row-gap: 15px;
440            grid-template-columns: 1fr 1fr;
441            background-color: var(--dark-background5,#F6F6F6);
442        }
443        .chart_div{
444            display: flex;
445            flex-direction: column;
446            background-color: var(--dark-background,#FFFFFF);
447            align-items: center;
448            height: 370px;
449            padding-left: 5px;
450            padding-right: 5px;
451            border-radius: 5px
452        }
453        :host {
454            width: 100%;
455            height: 100%;
456            background: var(--dark-background5,#F6F6F6);
457        }
458        .tb_cpu_usage{
459             overflow: auto;
460             background-color: var(--dark-background,#FFFFFF);
461             border-radius: 5px;
462             border: solid 1px var(--dark-border1,#e0e0e0);
463             display: flex;
464        }
465        .root{
466            overflow-y: auto;height: 80vh;background-color: var(--dark-background5,#F6F6F6)
467        }
468        .bg{
469            background-color: var(--dark-background5,#F6F6F6);
470            padding-left: 10px;
471        }
472        .labels{
473            display: flex;
474            flex-direction: row;
475            align-items: center;
476            justify-content: center;
477            font-size: 9pt;
478            padding-right: 15px;
479        }
480
481        </style>
482
483        <lit-progress-bar id="loading" style="height: 1px;width: 100%"></lit-progress-bar>
484        <table-no-data id="nodata" contentHeight="500px">
485        <div class="root">
486            <div class="bg" style="display: flex;flex-direction: row;">
487                <div id="setting" style="height: 45px;display: flex;flex-direction: row;align-items: center;cursor: pointer">
488                    CPU Setting
489                    <span style="width: 10px"></span>
490                    <lit-icon name="setting" size="20"></lit-icon>
491                </div>
492            </div>
493            <check-cpu-setting id="cpu_setting" style="display: none"></check-cpu-setting>
494            <div class="content_grid" id="total">
495                <div class="chart_div">
496                    <div style="line-height: 40px;height: 40px;width: 100%;text-align: center;">Top20线程大中小核占用率</div>
497                    <lit-chart-column id="chart_total" style="width:100%;height:300px"></lit-chart-column>
498                    <div style="height: 30px;width: 100%;display: flex;flex-direction: row;align-items: center;justify-content: center">
499                        <div class="labels"><div style="width: 20px;height: 10px;background-color: #2f72f8;margin-right: 5px"></div>big</div>
500                        <div class="labels"><div style="width: 20px;height: 10px;background-color: #ffab67;margin-right: 5px"></div>mid</div>
501                        <div class="labels"><div style="width: 20px;height: 10px;background-color: #a285d2;margin-right: 5px"></div>small</div>
502                    </div>
503                </div>
504                <div class="tb_cpu_usage" >
505                    <lit-table id="tb-thread-usage" hideDownload style="height: 360px;margin: 5px 15px"></lit-table>
506                </div>
507            </div>
508            <div class="content_grid" id="small">
509                <div class="chart_div">
510                    <div style="line-height: 40px;height: 40px;width: 100%;text-align: center;">Top20线程小核占用率</div>
511                    <lit-chart-column id="chart_2" style="width:100%;height:300px"></lit-chart-column>
512                    <div style="height: 30px;width: 100%;display: flex;flex-direction: row;align-items: center;justify-content: center">
513                        <div class="labels"><div style="width: 20px;height: 10px;background-color: #0a59f7;margin-right: 5px"></div>small</div>
514                    </div>
515                </div>
516                <div  class="tb_cpu_usage">
517                    <lit-table id="tb-thread-small" hideDownload style="height: 360px;margin: 5px 15px "></lit-table>
518                </div>
519            </div>
520            <div class="content_grid" id="mid">
521                <div class="chart_div">
522                    <div style="line-height: 40px;height: 40px;width: 100%;text-align: center;">Top20线程中核占用率</div>
523                    <lit-chart-column id="chart_3" style="width:100%;height:300px"></lit-chart-column>
524                    <div style="height: 30px;width: 100%;display: flex;flex-direction: row;align-items: center;justify-content: center">
525                        <div class="labels"><div style="width: 20px;height: 10px;background-color: #0a59f7;margin-right: 5px"></div>mid</div>
526                    </div>
527                </div>
528                <div  class="tb_cpu_usage">
529                    <lit-table id="tb-thread-mid" hideDownload style="height: 360px;margin: 5px 15px"></lit-table>
530                </div>
531            </div>
532            <div class="content_grid" id="big">
533                <div class="chart_div">
534                    <div style="line-height: 40px;height: 40px;width: 100%;text-align: center;">Top20线程大核占用率</div>
535                    <lit-chart-column id="chart_4" style="width:100%;height:300px"></lit-chart-column>
536                    <div style="height: 30px;width: 100%;display: flex;flex-direction: row;align-items: center;justify-content: center">
537                        <div class="labels"><div style="width: 20px;height: 10px;background-color: #0a59f7;margin-right: 5px"></div>big</div>
538                    </div>
539                </div>
540                <div class="tb_cpu_usage">
541                    <lit-table id="tb-thread-big" hideDownload style="height: 360px;margin: 5px 15px"></lit-table>
542                </div>
543            </div>
544        </div>
545        </table-no-data>
546
547        `;
548  }
549}
550