• 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 { SelectionData, SelectionParam } from '../../../../bean/BoxSelection';
19import '../../../StackBar';
20import { Utils } from '../../base/Utils';
21import { StackBar } from '../../../StackBar';
22import { log } from '../../../../../log/Log';
23import { resizeObserver } from '../SheetUtils';
24import { sliceChildBoxSender } from '../../../../database/data-trafic/SliceSender';
25
26@element('tabpane-thread-states')
27export class TabPaneThreadStates extends BaseElement {
28  private threadStatesTbl: LitTable | null | undefined;
29  private range: HTMLLabelElement | null | undefined;
30  private stackBar: StackBar | null | undefined;
31  private threadStatesTblSource: Array<SelectionData> = [];
32  private currentSelectionParam: SelectionParam | undefined;
33
34  set data(threadStatesParam: SelectionParam | unknown) {
35    if (this.currentSelectionParam === threadStatesParam) {
36      return;
37    }
38    // @ts-ignore
39    this.currentSelectionParam = threadStatesParam;
40    //@ts-ignore
41    this.threadStatesTbl?.shadowRoot?.querySelector('.table')?.style?.height = `${
42      this.parentElement!.clientHeight - 45
43    }px`;
44    // // @ts-ignore
45    this.range!.textContent = `Selected range: ${// @ts-ignore
46    ((threadStatesParam.rightNs - threadStatesParam.leftNs) / 1000000.0).toFixed(5)} ms`;
47    this.threadStatesTbl!.loading = true;
48    this.initThreadStates(threadStatesParam);
49  }
50
51  async initThreadStates(threadStatesParam: SelectionParam | unknown): Promise<void> {
52    let threadStatesDetail = await sliceChildBoxSender(
53      'state-box',
54      // @ts-ignore
55      threadStatesParam.leftNs,
56      // @ts-ignore
57      threadStatesParam.rightNs,
58      // @ts-ignore
59      threadStatesParam.threadIds
60    );
61    // @ts-ignore
62    let targetListTemp = this.updateThreadStates(threadStatesDetail, threadStatesParam.leftNs, threadStatesParam.rightNs);
63
64    let compare = (threadState1: SelectionData, threadState2: SelectionData): number => {
65      let wallDuration1 = threadState1.wallDuration;
66      let wallDuration2 = threadState2.wallDuration;
67      if (wallDuration1 < wallDuration2) {
68        return 1;
69      } else if (wallDuration1 > wallDuration2) {
70        return -1;
71      } else {
72        return 0;
73      }
74    };
75    targetListTemp.sort(compare);
76    this.addSumLine(threadStatesParam, targetListTemp);
77  }
78
79  updateThreadStates(threadStatDetail: Array<unknown>, leftNs: number, rightNs: number): Array<SelectionData> {
80    let targetListTemp: unknown[] = [];
81    if (threadStatDetail.length > 0) {
82      let source: Map<string, unknown> = new Map<string, unknown>();
83      let target = threadStatDetail.reduce((map, current) => {
84        // @ts-ignore
85        let mapKey = `${current.pid}-${current.tid}`;
86        // @ts-ignore
87        let key = `${current.state}-${mapKey}`;
88        // @ts-ignore
89        if (current.startTime < leftNs && (current.startTime + current.dur) < rightNs) {
90          // @ts-ignore
91          current.dur = current.dur - (leftNs - current.startTime);// @ts-ignore
92        } else if (current.startTime + current.dur > rightNs && current.startTime > leftNs) {
93          // @ts-ignore
94          current.dur = current.dur - (current.startTime + current.dur - rightNs);
95          // @ts-ignore
96        } else if (current.startTime < leftNs && (current.startTime + current.dur) > rightNs ) {
97          // @ts-ignore
98          current.dur = rightNs - leftNs;
99        }
100        // @ts-ignore
101        if (map.has(key)) {
102          // @ts-ignore
103          map.get(key).wallDuration += current.dur;
104          // @ts-ignore
105          map.get(key).occurrences += 1;
106        } else {
107          // @ts-ignore
108          map.set(key, {
109            // @ts-ignore
110            pid: current.pid,
111            // @ts-ignore
112            tid: current.tid,
113            // @ts-ignore
114            state: current.state,
115            // @ts-ignore
116            wallDuration: current.dur || 0,
117            avgDuration: 0,
118            occurrences: 1,
119          });
120        }
121        return map;
122      }, source);
123      //@ts-ignore
124      targetListTemp = Array.from(target.values());
125    }
126    // @ts-ignore
127    return targetListTemp;
128  }
129
130  addSumLine(threadStatesParam: SelectionParam | unknown, targetListTemp: Array<unknown>): void {
131    log(targetListTemp);
132
133    if (targetListTemp !== null && targetListTemp.length > 0) {
134      log('getTabThreadStates result size : ' + targetListTemp.length);
135      let sumWall = 0.0;
136      let sumOcc = 0;
137      let targetList = [];
138      // @ts-ignore
139      let traceId = threadStatesParam.traceId;
140      for (let e of targetListTemp) {
141        // @ts-ignore
142        if (threadStatesParam.processIds.includes(e.pid)) {
143          // @ts-ignore
144          let process = Utils.getInstance().getProcessMap(traceId).get(e.pid);
145          // @ts-ignore
146          let thread = Utils.getInstance().getThreadMap(traceId).get(e.tid);
147          // @ts-ignore
148          e.process = process || '[NULL]';
149          // @ts-ignore
150          e.thread = thread || '[NULL]';
151          // @ts-ignore
152          e.stateJX = Utils.getEndState(e.state);
153          // @ts-ignore
154          e.tabTitle = `${e.process}[${e.pid}]`;
155          // @ts-ignore
156          e.avgDuration = parseFloat((e.wallDuration / e.occurrences / 1000000.0).toFixed(5));
157          // @ts-ignore
158          e.wallDuration = parseFloat((e.wallDuration / 1000000.0).toFixed(5));
159          // @ts-ignore
160          sumWall += e.wallDuration;
161          // @ts-ignore
162          sumOcc += e.occurrences;
163          targetList.push(e);
164        }
165      }
166      if (targetList.length > 0) {
167        let count: unknown = {};
168        // @ts-ignore
169        count.process = ' ';
170        // @ts-ignore
171        count.stateJX = ' ';
172        // @ts-ignore
173        count.wallDuration = parseFloat(sumWall.toFixed(5));
174        // @ts-ignore
175        count.occurrences = sumOcc;
176        //@ts-ignore
177        count.summary = true;
178        // @ts-ignore
179        count.tabTitle = 'Summary';
180        targetList.splice(0, 0, count);
181      }
182      // @ts-ignore
183      this.threadStatesTblSource = targetList;
184      this.threadStatesTbl!.recycleDataSource = targetList;
185      // @ts-ignore
186      this.stackBar!.data = targetList;
187    } else {
188      this.threadStatesTblSource = [];
189      this.stackBar!.data = [];
190      this.threadStatesTbl!.recycleDataSource = [];
191    }
192    this.threadStatesTbl!.loading = false;
193  }
194
195  initElements(): void {
196    this.threadStatesTbl = this.shadowRoot?.querySelector<LitTable>('#tb-thread-states');
197    this.range = this.shadowRoot?.querySelector('#thread-states-time-range');
198    this.stackBar = this.shadowRoot?.querySelector('#thread-states-stack-bar');
199    this.threadStatesTbl!.addEventListener('column-click', (evt: unknown) => {
200      // @ts-ignore
201      this.sortByColumn(evt.detail);
202    });
203  }
204
205  connectedCallback(): void {
206    super.connectedCallback();
207    resizeObserver(this.parentElement!, this.threadStatesTbl!);
208  }
209
210  initHtml(): string {
211    return `
212        <style>
213        .tread-states-table{
214            display: flex;
215            height: 20px;
216        }
217        :host{
218            display: flex;
219            flex-direction: column;
220            padding: 10px 10px;
221        }
222        </style>
223        <div class="tread-states-table" style="display: flex;height: 20px;align-items: center;
224        flex-direction: row;margin-bottom: 5px;justify-content: space-between">
225            <stack-bar id="thread-states-stack-bar" style="width: calc(100vw - 520px)"></stack-bar>
226            <label id="thread-states-time-range"  style="width: 250px;text-align: end;
227            font-size: 10pt;">Selected range:0.0 ms</label>
228        </div>
229        <lit-table id="tb-thread-states" style="height: auto;overflow-x: auto;width: 100%">
230            <lit-table-column class="tread-states-column" width="240px" title="Process"
231            data-index="process" key="process"  align="flex-start" order>
232            </lit-table-column>
233            <lit-table-column class="tread-states-column" width="120px" title="PID"
234            data-index="pid" key="pid"  align="flex-start" order >
235            </lit-table-column>
236            <lit-table-column class="tread-states-column" width="240px" title="Thread"
237            data-index="thread" key="thread"  align="flex-start" order >
238            </lit-table-column>
239            <lit-table-column class="tread-states-column" width="120px" title="TID"
240            data-index="tid" key="tid"  align="flex-start" order >
241            </lit-table-column>
242            <lit-table-column class="tread-states-column" width="240px" title="State"
243            data-index="stateJX" key="stateJX"  align="flex-start" order >
244            </lit-table-column>
245            <lit-table-column class="tread-states-column" width="120px" title="Wall duration(ms)"
246            data-index="wallDuration" key="wallDuration"  align="flex-start" order >
247            </lit-table-column>
248            <lit-table-column class="tread-states-column" width="120px" title="Avg Wall duration(ms)"
249            data-index="avgDuration" key="avgDuration"  align="flex-start" order >
250            </lit-table-column>
251            <lit-table-column class="tread-states-column" width="120px" title="Occurrences"
252            data-index="occurrences" key="occurrences"  align="flex-start" order tdJump>
253            </lit-table-column>
254        </lit-table>
255        `;
256  }
257
258  sortByColumn(treadStatesDetail: unknown): void {
259    function compare(property: unknown, treadStatesSort: unknown, type: unknown) {
260      return function (threadStatesLeftData: SelectionData | unknown, threadStatesRightData: SelectionData | unknown): number {
261        // @ts-ignore
262        if (threadStatesLeftData.process === ' ' || threadStatesRightData.process === ' ') {
263          return 0;
264        }
265        if (type === 'number') {
266          return treadStatesSort === 2
267            ? // @ts-ignore
268              parseFloat(threadStatesRightData[property]) - parseFloat(threadStatesLeftData[property])
269            : // @ts-ignore
270              parseFloat(threadStatesLeftData[property]) - parseFloat(threadStatesRightData[property]);
271        } else {
272          // @ts-ignore
273          if (threadStatesRightData[property] > threadStatesLeftData[property]) {
274            return treadStatesSort === 2 ? 1 : -1;
275            // @ts-ignore
276          } else if (threadStatesRightData[property] === threadStatesLeftData[property]) {
277            return 0;
278          } else {
279            return treadStatesSort === 2 ? -1 : 1;
280          }
281        }
282      };
283    }
284
285    // @ts-ignore
286    if (treadStatesDetail.key === 'name' || treadStatesDetail.key === 'thread' || treadStatesDetail.key === 'stateJX') {
287      // @ts-ignore
288      this.threadStatesTblSource.sort(compare(treadStatesDetail.key, treadStatesDetail.sort, 'string'));
289    } else {
290      // @ts-ignore
291      this.threadStatesTblSource.sort(compare(treadStatesDetail.key, treadStatesDetail.sort, 'number'));
292    }
293    this.threadStatesTbl!.recycleDataSource = this.threadStatesTblSource;
294  }
295}
296