• 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 { SelectionParam } from '../../../../bean/BoxSelection';
19import { log } from '../../../../../log/Log';
20import { getProbablyTime } from '../../../../database/logic-worker/ProcedureLogicWorkerCommon';
21import { resizeObserver } from '../SheetUtils';
22import { AppStartupStruct } from '../../../../database/ui-worker/ProcedureWorkerAppStartup';
23import { getTabStartups } from '../../../../database/sql/ProcessThread.sql';
24
25interface StartupTreeItem {
26  name: string;
27  step: number;
28  dur: number;
29  durStr: string;
30  ratio: string;
31  children: StartupTreeItem[] | undefined;
32}
33
34@element('tabpane-startup')
35export class TabPaneStartup extends BaseElement {
36  private startupTbl: LitTable | null | undefined;
37  private range: HTMLLabelElement | null | undefined;
38  private startupSource: Array<StartupTreeItem> = [];
39  private currentSelectionParam: SelectionParam | undefined;
40
41  set data(startupParam: SelectionParam | unknown) {
42    if (this.currentSelectionParam === startupParam) {
43      return;
44    } // @ts-ignore
45    this.currentSelectionParam = startupParam;
46    //@ts-ignore
47    this.startupTbl?.shadowRoot?.querySelector('.table')?.style?.height = `${this.parentElement!.clientHeight - 45}px`; // @ts-ignore
48    this.range!.textContent = `Selected range: ${((startupParam.rightNs - startupParam.leftNs) / 1000000.0).toFixed(
49      5
50    )} ms`;
51    this.startupTbl!.loading = true; // @ts-ignore
52    getTabStartups(startupParam.processIds, startupParam.leftNs, startupParam.rightNs).then(
53      //@ts-ignore
54      (result: AppStartupStruct[]) => {
55        this.processTabStartups(result);
56      }
57    );
58  }
59
60  private processTabStartups(result: AppStartupStruct[]): void {
61    this.startupTbl!.loading = false;
62    if (result !== null && result.length > 0) {
63      log(`getTabStartups result  size : ${result.length}`);
64      let map: Map<number, StartupTreeItem> = new Map<number, StartupTreeItem>();
65      result.forEach((item) => {
66        this.processStartupItem(item, map);
67      });
68      let startups = Array.from(map.values());
69      startups.forEach((it) => {
70        it.durStr = getProbablyTime(it.dur);
71        if (it.dur === 0) {
72          it.ratio = '0%';
73        }
74        it.children!.forEach((child) => {
75          if (it.dur === 0) {
76            child.ratio = '0%';
77          } else {
78            child.ratio = `${((child.dur * 100) / it.dur).toFixed(2)}%`;
79          }
80        });
81      });
82      this.startupSource = startups;
83      this.startupTbl!.recycleDataSource = this.startupSource;
84    } else {
85      this.startupSource = [];
86      this.startupTbl!.recycleDataSource = [];
87    }
88  }
89
90  private processStartupItem(item: AppStartupStruct, map: Map<number, StartupTreeItem>): void {
91    let startup = {
92      name: AppStartupStruct.getStartupName(item.startName),
93      dur: item.dur || 0,
94      durStr: getProbablyTime(item.dur || 0),
95      ratio: '0%',
96      step: item.startName || 0,
97      children: [],
98    };
99    if (map.has(item.pid!)) {
100      let ps = map.get(item.pid!);
101      if (ps && ps.children) {
102        ps.dur += item.dur || 0;
103        ps.children!.push(startup);
104      }
105    } else {
106      map.set(item.pid!, {
107        name: item.process || `Process ${item.pid}`,
108        dur: item.dur || 0,
109        durStr: '',
110        ratio: '100%',
111        step: 0,
112        children: [startup],
113      });
114    }
115  }
116
117  initElements(): void {
118    this.startupTbl = this.shadowRoot?.querySelector<LitTable>('#tb-startup');
119    this.range = this.shadowRoot?.querySelector('#startup-time-range');
120    this.startupTbl!.addEventListener('column-click', (evt: unknown) => {
121      // @ts-ignore
122      this.sortByColumn(evt.detail);
123    });
124  }
125
126  connectedCallback(): void {
127    super.connectedCallback();
128    resizeObserver(this.parentElement!, this.startupTbl!);
129  }
130
131  initHtml(): string {
132    return `
133        <style>
134        .startup-table{
135          flex-direction: row;
136          margin-bottom: 5px;
137        }
138        :host{
139            display: flex;
140            flex-direction: column;
141            padding: 10px 10px;
142        }
143        </style>
144        <div class="startup-table" style="display: flex;height: 20px;align-items: center;
145        flex-direction: row;margin-bottom: 5px">
146            <div style="flex: 1"></div>
147            <label id="startup-time-range"  style="width: auto;text-align: end;font-size: 10pt;">
148            Selected range:0.0 ms</label>
149        </div>
150        <div style="overflow: auto">
151            <lit-table id="tb-startup" style="height: auto" tree >
152                <lit-table-column width="600px" title="Process / Startup"  data-index="name"
153                key="name"  align="flex-start" retract>
154                </lit-table-column>
155                <lit-table-column width="200px" title="Duration" data-index="durStr"
156                key="durStr"  align="flex-start" order >
157                </lit-table-column>
158                <lit-table-column width="200px" title="%" data-index="ratio"
159                key="ratio"  align="flex-start" order >
160                </lit-table-column>
161            </lit-table>
162        </div>
163        `;
164  }
165
166  sortByColumn(startupDetail: unknown): void {
167    let compare = (startupA: StartupTreeItem, startupB: StartupTreeItem): number => {
168      // @ts-ignore
169      if (startupDetail.sort === 0) {
170        return startupA.step - startupB.step; // @ts-ignore
171      } else if (startupDetail.sort === 1) {
172        return startupA.dur - startupB.dur;
173      } else {
174        return startupB.dur - startupA.dur;
175      }
176    };
177    this.startupSource.forEach((startup) => {
178      startup.children?.sort(compare);
179    });
180    this.startupSource.sort(compare);
181    this.startupTbl!.recycleDataSource = this.startupSource;
182  }
183}
184