• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2021 Huawei Device Co., Ltd.
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6//     http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14import { TraficEnum } from './utils/QueryEnum';
15import { JanksStruct } from '../../bean/JanksStruct';
16import { processFrameList } from './utils/AllMemoryCache';
17import { Args } from './CommonArgs';
18
19export const frameJankDataSql = (args: Args, configure: unknown): string => {
20  let condition: string = '';
21  let flag: string = '';
22  let fsType: number = -1;
23  let fsFlag: string = '';
24  //@ts-ignore
25  const endNS = args.endNS;
26  //@ts-ignore
27  const startNS = args.startNS;
28  //@ts-ignore
29  const recordStartNS = args.recordStartNS;
30  switch (configure) {
31    case 'ExepectMemory':
32      fsType = 1;
33      flag = 'fs.flag as jankTag,';
34      condition = 'AND t.tid = pro.pid';
35      break;
36    case 'ExpectedData':
37      fsType = 1;
38      flag = 'fs.flag as jankTag,';
39      condition = `
40       AND (fs.ts - ${recordStartNS} + fs.dur) >= ${Math.floor(startNS)}
41       AND (fs.ts - ${recordStartNS}) <= ${Math.floor(endNS)}`;
42      break;
43    case 'ActualMemoryData':
44      fsType = 0;
45      flag =
46        '(case when (sf.flag == 1 or fs.flag == 1 ) then 1 when (sf.flag == 3 or fs.flag == 3 ) then 3 else 0 end) as jankTag,';
47      fsFlag = 'AND fs.flag <> 2';
48      break;
49    case 'ActualData':
50      fsType = 0;
51      flag =
52        '(case when (sf.flag == 1 or fs.flag == 1 ) then 1 when (sf.flag == 3 or fs.flag == 3 ) then 3 else 0 end) as jankTag,';
53      fsFlag = 'AND fs.flag <> 2';
54      condition = `AND (fs.ts - ${recordStartNS} + fs.dur) >= ${Math.floor(startNS)}
55       AND (fs.ts - ${recordStartNS}) <= ${Math.floor(endNS)}`;
56      break;
57    default:
58      break;
59  }
60  let sql = setFrameJanksSql(args, condition, flag, fsType, fsFlag);
61  return sql;
62};
63function setFrameJanksSql(args: Args, timeLimit: string, flag: string, fsType: number, fsFlag: string): string {
64  //@ts-ignore
65  const recordStartNS = args.recordStartNS;
66  return `SELECT sf.id,
67            'frameTime' as frameType,
68            fs.ipid,
69            fs.vsync as name,
70            fs.dur as appDur,
71            (sf.ts + sf.dur - fs.ts) as dur,
72            (fs.ts - ${recordStartNS}) AS ts,
73            fs.type,
74            ${flag}
75            pro.pid,
76            t.tid,
77            pro.name as cmdline,
78            (sf.ts - ${recordStartNS}) AS rsTs,
79            sf.vsync AS rsVsync,
80            sf.dur AS rsDur,
81            sf.ipid AS rsIpid,
82            proc.pid AS rsPid,
83            proc.name AS rsName
84        FROM frame_slice AS fs
85        LEFT JOIN process AS pro ON pro.id = fs.ipid
86        LEFT JOIN frame_slice AS sf ON fs.dst = sf.id
87        LEFT JOIN process AS proc ON proc.id = sf.ipid
88        LEFT JOIN thread as t on fs.itid = t.id
89        WHERE fs.dst IS NOT NULL
90        AND fs.type = ${fsType}
91        ${fsFlag} ${timeLimit}
92        UNION
93        SELECT -1 as id,
94            'frameTime' as frameType,
95            fs.ipid,
96            fs.vsync  as name,
97            fs.dur as appDur,
98            fs.dur,
99            (fs.ts - ${recordStartNS}) AS ts,
100            fs.type,
101            fs.flag as jankTag,
102            pro.pid,
103            t.tid,
104            pro.name as cmdline,
105            NULL AS rsTs, NULL AS rsVsync, NULL AS rsDur, NULL AS rsIpid, NULL AS rsPid, NULL AS rsName
106        FROM frame_slice AS fs LEFT JOIN process AS pro ON pro.id = fs.ipid
107        LEFT JOIN thread as t on fs.itid = t.id
108        WHERE fs.dst IS NULL
109        AND pro.name NOT LIKE '%render_service%'
110        AND fs.type = 1
111        ${fsFlag} ${timeLimit}
112        ORDER by ts`;
113}
114
115export function frameExpectedReceiver(data: unknown, proc: Function): void {
116  // @ts-ignore
117  if (data.params.trafic === TraficEnum.Memory) {
118    if (!processFrameList.has('FrameTimeLine_expected')) {
119      // @ts-ignore
120      let sql = frameJankDataSql(data.params, 'ExepectMemory');
121      processFrameList.set('FrameTimeLine_expected', proc(sql));
122    }
123    frameJanksReceiver(data, processFrameList.get('FrameTimeLine_expected')!, 'expected', true);
124  } else {
125    // @ts-ignore
126    let sql = frameJankDataSql(data.params, 'ExpectedData');
127    let res = proc(sql);
128    // @ts-ignore
129    frameJanksReceiver(data, res, 'expect', data.params.trafic !== TraficEnum.SharedArrayBuffer);
130  }
131}
132
133export function frameActualReceiver(data: unknown, proc: Function): void {
134  // @ts-ignore
135  if (data.params.trafic === TraficEnum.Memory) {
136    if (!processFrameList.has('FrameTimeLine_actual')) {
137      // @ts-ignore
138      let sql = frameJankDataSql(data.params, 'ActualMemoryData');
139      processFrameList.set('FrameTimeLine_actual', proc(sql));
140    }
141    frameJanksReceiver(data, processFrameList.get('FrameTimeLine_actual')!, 'actual', true);
142  } else {
143    // @ts-ignore
144    let sql = frameJankDataSql(data.params, 'ActualData');
145    let res = proc(sql);
146    // @ts-ignore
147    frameJanksReceiver(data, res, 'actual', data.params.trafic !== TraficEnum.SharedArrayBuffer);
148  }
149}
150let isIntersect = (leftData: JanksStruct, rightData: JanksStruct): boolean =>
151  Math.max(leftData.ts! + leftData.dur!, rightData.ts! + rightData.dur!) - Math.min(leftData.ts!, rightData.ts!) <
152  leftData.dur! + rightData.dur!;
153function frameJanksReceiver(data: unknown, res: unknown[], type: string, transfer: boolean): void {
154  let frameJanks = new FrameJanks(data, transfer, res.length);
155  let unitIndex: number = 1;
156  let depths: unknown[] = [];
157  for (let index = 0; index < res.length; index++) {
158    let item = res[index];
159    // @ts-ignore
160    data.params.trafic === TraficEnum.ProtoBuffer && (item = item.frameData);
161    // @ts-ignore
162    if (!item.dur || item.dur < 0) {
163      continue;
164    }
165    if (depths.length === 0) {
166      // @ts-ignore
167      item.depth = 0;
168      depths[0] = item;
169    } else {
170      let depthIndex: number = 0;
171      let isContinue: boolean = true;
172      while (isContinue) {
173        // @ts-ignore
174        if (isIntersect(depths[depthIndex], item)) {
175          if (depths[depthIndex + unitIndex] === undefined || !depths[depthIndex + unitIndex]) {
176            // @ts-ignore
177            item.depth = depthIndex + unitIndex;
178            depths[depthIndex + unitIndex] = item;
179            isContinue = false;
180          }
181        } else {
182          // @ts-ignore
183          item.depth = depthIndex;
184          depths[depthIndex] = item;
185          isContinue = false;
186        }
187        depthIndex++;
188      }
189    }
190    setFrameJanks(frameJanks, item, index);
191  }
192  postFrameJanksMessage(data, transfer, frameJanks, res.length);
193}
194function setFrameJanks(frameJanks: FrameJanks, itemData: unknown, index: number): void {
195  // @ts-ignore
196  frameJanks.id[index] = itemData.id;
197  // @ts-ignore
198  frameJanks.ipId[index] = itemData.ipid;
199  // @ts-ignore
200  frameJanks.name[index] = itemData.name;
201  // @ts-ignore
202  frameJanks.appDur[index] = itemData.appDur;
203  // @ts-ignore
204  frameJanks.dur[index] = itemData.dur;
205  // @ts-ignore
206  frameJanks.ts[index] = itemData.ts;
207  // @ts-ignore
208  frameJanks.jankTag[index] = itemData.jankTag ? itemData.jankTag : 0;
209  // @ts-ignore
210  frameJanks.pid[index] = itemData.pid;
211  // @ts-ignore
212  frameJanks.tid[index] = itemData.tid;
213  // @ts-ignore
214  frameJanks.rsTs[index] = itemData.rsTs;
215  // @ts-ignore
216  frameJanks.rsVsync[index] = itemData.rsVsync;
217  // @ts-ignore
218  frameJanks.rsDur[index] = itemData.rsDur;
219  // @ts-ignore
220  frameJanks.rsIpId[index] = itemData.rsIpid;
221  // @ts-ignore
222  frameJanks.rsPid[index] = itemData.rsPid;
223  // @ts-ignore
224  frameJanks.rsName[index] = itemData.rsName;
225  // @ts-ignore
226  frameJanks.depth[index] = itemData.depth;
227}
228function setResults(transfer: boolean, frameJanks: FrameJanks): unknown {
229  return transfer
230    ? {
231        id: frameJanks.id.buffer,
232        ipid: frameJanks.ipId.buffer,
233        name: frameJanks.name.buffer,
234        app_dur: frameJanks.appDur.buffer,
235        dur: frameJanks.dur.buffer,
236        ts: frameJanks.ts.buffer,
237        jank_tag: frameJanks.jankTag.buffer,
238        pid: frameJanks.pid.buffer,
239        tid: frameJanks.tid.buffer,
240        rs_ts: frameJanks.rsTs.buffer,
241        rs_vsync: frameJanks.rsVsync.buffer,
242        rs_dur: frameJanks.rsDur.buffer,
243        rs_ipid: frameJanks.rsIpId.buffer,
244        rs_pid: frameJanks.rsPid.buffer,
245        rs_name: frameJanks.rsName.buffer,
246        depth: frameJanks.depth.buffer,
247      }
248    : {};
249}
250function postFrameJanksMessage(data: unknown, transfer: boolean, frameJanks: FrameJanks, len: number): void {
251  let results = setResults(transfer, frameJanks);
252  (self as unknown as Worker).postMessage(
253    {
254      // @ts-ignore
255      id: data.id,
256      // @ts-ignore
257      action: data.action,
258      results: results,
259      len: len,
260      transfer: transfer,
261    },
262    transfer
263      ? [
264          frameJanks.id.buffer,
265          frameJanks.ipId.buffer,
266          frameJanks.name.buffer,
267          frameJanks.appDur.buffer,
268          frameJanks.dur.buffer,
269          frameJanks.ts.buffer,
270          frameJanks.jankTag.buffer,
271          frameJanks.pid.buffer,
272          frameJanks.tid.buffer,
273          frameJanks.rsTs.buffer,
274          frameJanks.rsVsync.buffer,
275          frameJanks.rsDur.buffer,
276          frameJanks.rsIpId.buffer,
277          frameJanks.rsPid.buffer,
278          frameJanks.rsName.buffer,
279          frameJanks.depth.buffer,
280        ]
281      : []
282  );
283}
284class FrameJanks {
285  id: Uint16Array;
286  ipId: Uint16Array;
287  name: Int32Array;
288  appDur: Float64Array;
289  dur: Float64Array;
290  ts: Float64Array;
291  jankTag: Uint16Array;
292  pid: Uint32Array;
293  tid: Uint32Array;
294  rsTs: Float64Array;
295  rsVsync: Int32Array;
296  rsDur: Float64Array;
297  rsIpId: Uint16Array;
298  rsPid: Uint32Array;
299  rsName: Int32Array;
300  depth: Uint16Array;
301  constructor(data: unknown, transfer: boolean, len: number) {
302    // @ts-ignore
303    this.id = new Uint16Array(transfer ? len : data.params.sharedArrayBuffers.id);
304    // @ts-ignore
305    this.ipId = new Uint16Array(transfer ? len : data.params.sharedArrayBuffers.ipid);
306    // @ts-ignore
307    this.name = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.name);
308    // @ts-ignore
309    this.appDur = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.app_dur);
310    // @ts-ignore
311    this.dur = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.dur);
312    // @ts-ignore
313    this.ts = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.ts);
314    // @ts-ignore
315    this.jankTag = new Uint16Array(transfer ? len : data.params.sharedArrayBuffers.jank_tag);
316    // @ts-ignore
317    this.pid = new Uint32Array(transfer ? len : data.params.sharedArrayBuffers.pid);
318    // @ts-ignore
319    this.tid = new Uint32Array(transfer ? len : data.params.sharedArrayBuffers.tid);
320    // @ts-ignore
321    this.rsTs = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.rs_ts);
322    // @ts-ignore
323    this.rsVsync = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.rs_vsync);
324    // @ts-ignore
325    this.rsDur = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.rs_dur);
326    // @ts-ignore
327    this.rsIpId = new Uint16Array(transfer ? len : data.params.sharedArrayBuffers.rs_ipid);
328    // @ts-ignore
329    this.rsPid = new Uint32Array(transfer ? len : data.params.sharedArrayBuffers.rs_pid);
330    // @ts-ignore
331    this.rsName = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.rs_name);
332    // @ts-ignore
333    this.depth = new Uint16Array(transfer ? len : data.params.sharedArrayBuffers.depth);
334  }
335}
336