• 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 { SelectionData, SelectionParam } from '../../../../bean/BoxSelection';
18import { LitTable } from '../../../../../base-ui/table/lit-table';
19import { JankFramesStruct } from '../../../../bean/JankFramesStruct';
20import { JanksStruct } from '../../../../bean/JanksStruct';
21import { resizeObserver } from '../SheetUtils';
22import { querySelectRangeData } from '../../../../database/sql/Janks.sql';
23
24@element('tabpane-frames')
25export class TabPaneFrames extends BaseElement {
26  private framesTbl: LitTable | null | undefined;
27  private range: HTMLLabelElement | null | undefined;
28  private framesSource: Array<unknown> = [];
29  set data(framesParam: SelectionParam | unknown) {
30    this.range!.textContent = // @ts-ignore
31      'Selected range: ' + parseFloat(((framesParam.rightNs - framesParam.leftNs) / 1000000.0).toFixed(5)) + '  ms';
32    this.queryDataByDB(framesParam);
33  }
34
35  queryDataByDB(framesParam: SelectionParam | unknown): void {
36    let tablelist = new Array<JankFramesStruct>();
37    let sumRes: JankFramesStruct = new JankFramesStruct();
38    let appJank: JankFramesStruct = new JankFramesStruct();
39    let rsJank: JankFramesStruct = new JankFramesStruct();
40    let noJank: JankFramesStruct = new JankFramesStruct(); // @ts-ignore
41    if (framesParam.jankFramesData.length > 0) {
42      let allPid: Array<number> = [];
43      let allData: Array<unknown> = []; // @ts-ignore
44      framesParam.jankFramesData.forEach((data: unknown) => {
45        if (typeof data === 'string') {
46          if (Number(data) && allPid.indexOf(Number(data)) < 0) {
47            allPid.push(Number(data));
48          }
49        } else {
50          allData.push(data);
51        }
52      }); // @ts-ignore
53      querySelectRangeData(allPid, framesParam.leftNs, framesParam.rightNs).then((result: unknown) => {
54        // @ts-ignore
55        sumRes.occurrences = allData.length + result.length;
56        allData.forEach((item) => {
57          // frameTime
58          // @ts-ignore
59          this.frameTimelineJankDataHandle(item, appJank, noJank);
60        }); // @ts-ignore
61        result.forEach((structValue: JanksStruct) => {
62          if (structValue.frameType === 'app') {
63            this.appJankDataHandle(structValue, appJank, noJank);
64          } else if (structValue.frameType === 'render_service') {
65            this.rsJankDataHandle(structValue, rsJank, noJank);
66          }
67        });
68        tablelist.push(sumRes);
69        tablelist = this.setFrameDataDur(appJank, rsJank, noJank, tablelist);
70        this.framesSource = tablelist;
71        this.framesTbl!.recycleDataSource = tablelist;
72      });
73    }
74  }
75
76  private setFrameDataDur(
77    appFrame: JankFramesStruct,
78    rsFrame: JankFramesStruct,
79    noFrame: JankFramesStruct,
80    tableList: JankFramesStruct[]
81  ): JankFramesStruct[] {
82    if (appFrame.occurrences > 0) {
83      appFrame.maxDurationStr = appFrame.maxDuration + '';
84      appFrame.minDurationStr = appFrame.minDuration + '';
85      appFrame.meanDurationStr = appFrame.meanDuration + '';
86      tableList.push(appFrame);
87    }
88    if (rsFrame.occurrences > 0) {
89      rsFrame.maxDurationStr = rsFrame.maxDuration + '';
90      rsFrame.minDurationStr = rsFrame.minDuration + '';
91      rsFrame.meanDurationStr = rsFrame.meanDuration + '';
92      tableList.push(rsFrame);
93    }
94    if (noFrame.occurrences > 0) {
95      noFrame.maxDurationStr = noFrame.maxDuration + '';
96      noFrame.minDurationStr = noFrame.minDuration + '';
97      noFrame.meanDurationStr = noFrame.meanDuration + '';
98      tableList.push(noFrame);
99    }
100    return tableList;
101  }
102
103  private frameTimelineJankDataHandle(
104    structValue: JanksStruct,
105    appJank: JankFramesStruct,
106    noJank: JankFramesStruct
107  ): void {
108    if (structValue.dur === null || structValue.dur === undefined) {
109      structValue.dur = 0;
110    }
111    if (structValue && structValue.jank_tag && structValue.jank_tag > 0) {
112      appJank.flag = structValue.jank_tag;
113      appJank.jankType = 'Deadline Missed';
114      appJank.occurrences += 1;
115      appJank.maxDuration = Math.max(structValue.dur, appJank.maxDuration);
116      appJank.minDuration = Math.min(structValue.dur, appJank.minDuration);
117      if (appJank.minDuration === -1) {
118        appJank.minDuration = structValue.dur;
119      } else {
120        appJank.minDuration = Math.min(structValue.dur, appJank.minDuration!);
121      }
122      if (appJank.meanDuration === -1) {
123        appJank.meanDuration = structValue.dur;
124      } else {
125        appJank.meanDuration = Number(((structValue.dur + appJank.meanDuration) / 2).toFixed(2));
126      }
127    } else {
128      noJank.flag = structValue.jank_tag;
129      noJank.jankType = 'None';
130      noJank.occurrences += 1;
131      noJank.maxDuration = Math.max(structValue.dur, noJank.maxDuration);
132      if (noJank.minDuration === -1) {
133        noJank.minDuration = structValue.dur;
134      } else {
135        noJank.minDuration = Math.min(structValue.dur, noJank.minDuration!);
136      }
137      if (noJank.meanDuration === -1) {
138        noJank.meanDuration = structValue.dur;
139      } else {
140        noJank.meanDuration = Number(((structValue.dur + noJank.meanDuration) / 2).toFixed(2));
141      }
142    }
143  }
144  private rsJankDataHandle(structValue: JanksStruct, rsJank: JankFramesStruct, noJank: JankFramesStruct): void {
145    if (structValue.dur === null || structValue.dur === undefined) {
146      structValue.dur = 0;
147    }
148    if (structValue.jank_tag && structValue.jank_tag > 0) {
149      rsJank.flag = structValue.jank_tag;
150      rsJank.jankType = 'RenderService Deadline Missed';
151      rsJank.occurrences += 1;
152      rsJank.maxDuration = Math.max(structValue.dur, rsJank.maxDuration!);
153      if (rsJank.minDuration === -1) {
154        rsJank.minDuration = structValue.dur;
155      } else {
156        rsJank.minDuration = Math.min(structValue.dur, rsJank.minDuration!);
157      }
158      if (rsJank.meanDuration === -1) {
159        rsJank.meanDuration = structValue.dur;
160      } else {
161        rsJank.meanDuration = Number(((structValue.dur + rsJank.meanDuration!) / 2).toFixed(2));
162      }
163    } else {
164      this.refreshNoJankData(noJank, structValue);
165    }
166  }
167  private appJankDataHandle(structValue: JanksStruct, appJank: JankFramesStruct, noJank: JankFramesStruct): void {
168    if (structValue.dur === null || structValue.dur === undefined) {
169      structValue.dur = 0;
170    }
171    if (structValue.jank_tag && structValue.jank_tag > 0) {
172      appJank.flag = structValue.jank_tag;
173      appJank.jankType = 'APP Deadline Missed';
174      appJank.occurrences += 1;
175      appJank.maxDuration = Math.max(structValue.dur, appJank.maxDuration!);
176      if (appJank.minDuration === -1) {
177        appJank.minDuration = structValue.dur;
178      } else {
179        appJank.minDuration = Math.min(structValue.dur, appJank.minDuration!);
180      }
181      if (appJank.meanDuration === -1) {
182        appJank.meanDuration = structValue.dur;
183      } else {
184        appJank.meanDuration = Number(((structValue.dur + appJank.meanDuration!) / 2).toFixed(2));
185      }
186    } else {
187      this.refreshNoJankData(noJank, structValue);
188    }
189  }
190  private refreshNoJankData(noJank: JankFramesStruct, structValue: JanksStruct): void {
191    noJank.flag = structValue.jank_tag;
192    noJank.jankType = 'None';
193    noJank.occurrences += 1;
194    noJank.maxDuration = Math.max(structValue.dur!, noJank.maxDuration!);
195    if (noJank.minDuration === -1) {
196      noJank.minDuration = structValue.dur!;
197    } else {
198      noJank.minDuration = Math.min(structValue.dur!, noJank.minDuration!);
199    }
200    if (noJank.meanDuration === -1) {
201      noJank.meanDuration = structValue.dur!;
202    } else {
203      noJank.meanDuration = Number(((structValue.dur! + noJank.meanDuration!) / 2).toFixed(2));
204    }
205  }
206
207  initElements(): void {
208    this.framesTbl = this.shadowRoot?.querySelector<LitTable>('#tb-frames');
209    this.range = this.shadowRoot?.querySelector('#jank-frames-time-range');
210    this.framesTbl!.addEventListener('column-click', (evt) => {
211      // @ts-ignore
212      this.sortByColumn(evt.detail);
213    });
214  }
215
216  connectedCallback(): void {
217    super.connectedCallback();
218    resizeObserver(this.parentElement!, this.framesTbl!);
219  }
220
221  initHtml(): string {
222    return `
223        <style>
224        .frames-label{
225          height: 20px;
226          text-align: end;
227        }
228        :host{
229            padding: 10px 10px;
230            display: flex;
231            flex-direction: column;
232        }
233        </style>
234        <label id="jank-frames-time-range" class="frames-label" style="width: 100%;font-size: 10pt;margin-bottom: 5px">Selected range:0.0 ms</label>
235        <lit-table id="tb-frames" style="height: auto">
236            <lit-table-column class="jank-frames-column" title="Jank Type" width="1fr" data-index="jankType" key="jankType"  align="flex-start" order>
237            </lit-table-column>
238            <lit-table-column class="jank-frames-column" title="Min duration" width="1fr" data-index="minDurationStr" key="minDurationStr"  align="flex-start" order >
239            </lit-table-column>
240            <lit-table-column class="jank-frames-column" title="Max duration" width="1fr" data-index="maxDurationStr" key="maxDurationStr"  align="flex-start" order >
241            </lit-table-column>
242            <lit-table-column class="jank-frames-column" title="Mean duration" width="1fr" data-index="meanDurationStr" key="meanDurationStr"  align="flex-start" order >
243            </lit-table-column>
244            <lit-table-column class="jank-frames-column" title="Occurrences" width="1fr" data-index="occurrences" key="occurrences"  align="flex-start" order >
245            </lit-table-column>
246        </lit-table>
247        `;
248  }
249
250  sortByColumn(framesDetail: unknown): void {
251    // @ts-ignore
252    function compare(property, sort, type) {
253      return function (framesLeftData: SelectionData, framesRightData: SelectionData) {
254        if (framesLeftData.process === ' ' || framesRightData.process === ' ') {
255          return 0;
256        }
257        if (type === 'number') {
258          return sort === 2
259            ? // @ts-ignore
260              parseFloat(framesRightData[property]) - parseFloat(framesLeftData[property])
261            : // @ts-ignore
262              parseFloat(framesLeftData[property]) - parseFloat(framesRightData[property]);
263        } else {
264          // @ts-ignore
265          if (framesRightData[property] > framesLeftData[property]) {
266            return sort === 2 ? 1 : -1;
267          } else {
268            // @ts-ignore
269            if (framesRightData[property] === framesLeftData[property]) {
270              return 0;
271            } else {
272              return sort === 2 ? -1 : 1;
273            }
274          }
275        }
276      };
277    }
278
279    // @ts-ignore
280    if (framesDetail.key === 'jankType') {
281      // @ts-ignore
282      this.framesSource.sort(compare(framesDetail.key, framesDetail.sort, 'string'));
283    } else {
284      // @ts-ignore
285      this.framesSource.sort(compare(framesDetail.key, framesDetail.sort, 'number'));
286    }
287    this.framesTbl!.recycleDataSource = this.framesSource;
288  }
289}
290