• 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 { querySysCallEventWithBoxSelect } from '../../../../database/sql/ProcessThread.sql';
23import { Utils } from '../../base/Utils';
24import { SysCallMap } from '../../base/SysCallUtils';
25
26interface SysCallItem {
27  nameId: number;
28  name: string;
29  pName: string;
30  tName: string;
31  tid: number;
32  pid: number;
33  totalCount: number;
34  sumDur: number;
35  durStr?: string;
36}
37
38interface SysCallTreeItem {
39  name: string;
40  id: number;
41  parentId?: number;
42  totalCount: number;
43  sumDur: number;
44  durStr: string;
45  level: string;
46  children: SysCallTreeItem[]
47}
48
49@element('tabpane-syscall')
50export class TabPaneSysCall extends BaseElement {
51  private sysCallTbl: LitTable | null | undefined;
52  private range: HTMLLabelElement | null | undefined;
53  private sysCallSource: Array<SysCallTreeItem> = [];
54  private currentSelectionParam: SelectionParam | undefined;
55
56  set data(sysCallParam: SelectionParam | unknown) {
57    if (this.currentSelectionParam === sysCallParam) {
58      return;
59    } // @ts-ignore
60    this.currentSelectionParam = sysCallParam;
61    //@ts-ignore
62    this.sysCallTbl?.shadowRoot?.querySelector('.table')?.style?.height = `${this.parentElement!.clientHeight - 45}px`; // @ts-ignore
63    this.range!.textContent = `Selected range: ${((sysCallParam.rightNs - sysCallParam.leftNs) / 1000000.0).toFixed(
64      5
65    )} ms`;
66    this.sysCallTbl!.loading = true;
67    let ipidArr: number[] = [];
68    Array.from(Utils.getInstance().sysCallEventTidsMap.values()).forEach(it => {
69      //@ts-ignore
70      if (sysCallParam?.processSysCallIds?.includes(it.pid)) {
71        ipidArr.push(it.ipid);
72      }
73    })
74    //@ts-ignore
75    querySysCallEventWithBoxSelect(ipidArr, sysCallParam.threadSysCallIds, sysCallParam.leftNs, sysCallParam.rightNs).then(
76      (retult) => {
77        this.flatternToTree(retult as SysCallItem[]);
78      }
79    );
80  }
81
82  private flatternToTree(result: SysCallItem[]): void {
83    this.sysCallTbl!.loading = false;
84    if (result !== null && result.length > 0) {
85      log(`getTabsysCalls result  size : ${result.length}`);
86      let map: Map<number, SysCallTreeItem> = new Map<number, SysCallTreeItem>();
87      result.forEach((item) => {
88        item.name = SysCallMap.get(item.nameId) || '';
89        item.durStr = getProbablyTime(item.sumDur);
90        this.processSysCallItem(item, map);
91      });
92      let sysCalls: SysCallTreeItem[] = Array.from(map.values());
93      this.sysCallSource = sysCalls;
94      this.sysCallTbl!.recycleDataSource = this.sysCallSource;
95    } else {
96      this.sysCallSource = [];
97      this.sysCallTbl!.recycleDataSource = [];
98    }
99  }
100
101  private processSysCallItem(item: SysCallItem, map: Map<number, SysCallTreeItem>): void {
102    const treeItem: SysCallTreeItem = {
103      id: item.nameId,
104      name: item.name,
105      level: 'SysCall',
106      parentId: item.tid,
107      totalCount: item.totalCount,
108      sumDur: item.sumDur,
109      durStr: item.durStr!,
110      children:[]
111    };
112    let ps = map.get(item.pid!);
113    if (ps) {
114      ps.sumDur += item.sumDur || 0;
115      ps.durStr = getProbablyTime(ps.sumDur);
116      ps.totalCount += item.totalCount || 0;
117      let ts = ps.children?.find(it => it.id === item.tid);
118      if (ts) {
119        ts.sumDur += item.sumDur || 0;
120        ts.durStr = getProbablyTime(ts.sumDur);
121        ts.totalCount += item.totalCount || 0;
122        ts.children.push(treeItem);
123      } else {
124        ps.children.push({
125          id: item.tid,
126          name: item.tName,
127          parentId: item.pid,
128          level: 'Thread',
129          totalCount: item.totalCount,
130          sumDur: item.sumDur,
131          durStr: item.durStr!,
132          children: [treeItem]
133        })
134      }
135    } else {
136      map.set(item.pid!, {
137        id: item.pid,
138        level: 'Process',
139        name: `${item.pName} [${item.pid}]`,
140        totalCount: item.totalCount,
141        sumDur: item.sumDur,
142        durStr: item.durStr!,
143        children: [{
144          id: item.tid,
145          level: 'Thread',
146          parentId: item.pid,
147          name: `${item.tName} [${item.tid}]`,
148          durStr: item.durStr!,
149          totalCount: item.totalCount,
150          sumDur: item.sumDur,
151          children: [treeItem]
152        }]
153      });
154    }
155  }
156
157  initElements(): void {
158    this.sysCallTbl = this.shadowRoot?.querySelector<LitTable>('#tb-syscall');
159    this.range = this.shadowRoot?.querySelector('#syscall-time-range');
160    this.sysCallTbl!.addEventListener('column-click', (evt: unknown) => {
161      // @ts-ignore
162      this.sortByColumn(evt.detail);
163    });
164  }
165
166  connectedCallback(): void {
167    super.connectedCallback();
168    resizeObserver(this.parentElement!, this.sysCallTbl!);
169  }
170
171  initHtml(): string {
172    return `
173        <style>
174        .syscall-table{
175          flex-direction: row;
176          margin-bottom: 5px;
177        }
178        :host{
179            display: flex;
180            flex-direction: column;
181            padding: 10px 10px;
182        }
183        </style>
184        <div class="syscall-table" style="display: flex;height: 20px;align-items: center;
185        flex-direction: row;margin-bottom: 5px">
186            <div style="flex: 1"></div>
187            <label id="syscall-time-range"  style="width: auto;text-align: end;font-size: 10pt;">
188            Selected range:0.0 ms</label>
189        </div>
190        <div style="overflow: auto">
191            <lit-table id="tb-syscall" style="height: auto" tree >
192                <lit-table-column width="600px" title="Process / Thread / SysCall"  data-index="name"
193                key="name"  align="flex-start" retract>
194                </lit-table-column>
195                <lit-table-column width="200px" title="Duration" data-index="durStr"
196                key="durStr"  align="flex-start" order >
197                </lit-table-column>
198                <lit-table-column width="200px" title="Count" data-index="totalCount"
199                key="totalCount"  align="flex-start" order tdJump>
200                </lit-table-column>
201            </lit-table>
202        </div>
203        `;
204  }
205
206  sortByColumn(sortDetail: unknown): void {
207    let compare = (itemA: SysCallTreeItem, itemB: SysCallTreeItem): number => {
208      // @ts-ignore
209      if (sortDetail.key === 'durStr') {
210        // @ts-ignore
211        if (sortDetail.sort === 0) {
212          return itemA.sumDur - itemB.sumDur; // @ts-ignore
213        } else if (sortDetail.sort === 1) {
214          return itemA.sumDur - itemB.sumDur;
215        } else {
216          return itemB.sumDur - itemA.sumDur;
217        }
218      } else {
219         // @ts-ignore
220        if (sortDetail.sort === 0) {
221          return itemA.totalCount - itemB.totalCount; // @ts-ignore
222        } else if (sortDetail.sort === 1) {
223          return itemA.totalCount - itemB.totalCount;
224        } else {
225          return itemB.totalCount - itemA.totalCount;
226        }
227      }
228    };
229    this.sysCallSource.forEach((syscall) => {
230      syscall.children?.sort(compare);
231    });
232    const deepSort = (arr: SysCallTreeItem[]) => {
233      arr.sort(compare);
234      arr.forEach(item => {
235        if (item.children) {
236          deepSort(item.children);
237        }
238      })
239    };
240    deepSort(this.sysCallSource);
241    this.sysCallTbl!.recycleDataSource = this.sysCallSource;
242  }
243}
244