• 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 sp 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 { JankStruct } from '../database/ui-worker/ProcedureWorkerJank';
17import { SpSystemTrace } from './SpSystemTrace';
18import { TraceRow } from './trace/base/TraceRow';
19import { LineType, ns2xByTimeShaft } from '../database/ui-worker/ProcedureWorkerCommon';
20import { TabPaneTaskFrames } from './trace/sheet/task/TabPaneTaskFrames';
21import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc';
22import { queryBySelectExecute } from '../database/sql/ProcessThread.sql';
23import { queryTaskPoolOtherRelationData, queryTaskPoolRelationData } from '../database/sql/Func.sql';
24import { queryBySelectAllocationOrReturn } from '../database/sql/SqlLite.sql';
25import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread';
26
27function collectionHasJank(jankRow: any, collectList: TraceRow<any>[]): boolean {
28  for (let item of collectList!) {
29    if (item.rowId === jankRow.rowId && item.rowType === jankRow.rowType) {
30      return false;
31    }
32  }
33  return true;
34}
35
36function setPoint(
37  x: number,
38  y: number,
39  offsetY: number,
40  ns: number,
41  rowEL: any,
42  isRight: boolean,
43  business: string
44): any {
45  return {
46    x: x,
47    y: y,
48    offsetY: offsetY,
49    ns: ns,
50    rowEL: rowEL!,
51    isRight: isRight,
52    business: business,
53  };
54}
55
56function selectJankApp(
57  endParentRow: any,
58  sp: SpSystemTrace,
59  data: any,
60  startRow: any,
61  selectJankStruct: JankStruct,
62  endRowStruct: any
63): void {
64  let collectList = sp.favoriteChartListEL!.getAllCollectRows();
65  let findJankEntry = endRowStruct!.dataListCache!.find((dat: any) => dat.name == data.name && dat.pid == data.pid);
66  let tts =
67    findJankEntry.frame_type == 'frameTime' ? selectJankStruct.ts! : selectJankStruct.ts! + selectJankStruct.dur!;
68  let startParentRow: any;
69  // startRow为子泳道,子泳道不存在,使用父泳道
70  if (startRow) {
71    startParentRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>(
72      `trace-row[row-id='${startRow.rowParentId}'][folder]`
73    );
74  } else {
75    startRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>(
76      `trace-row[row-id='${selectJankStruct?.pid}'][folder]`
77    );
78  }
79  let endY = endRowStruct!.translateY! + 20 * (findJankEntry!.depth! + 0.5);
80  let endRowEl = endRowStruct;
81  let endOffSetY = 20 * (findJankEntry!.depth! + 0.5);
82  let expansionFlag = collectionHasJank(endRowStruct, collectList);
83  if (!endParentRow.expansion && expansionFlag) {
84    endY = endParentRow!.translateY! + 10 * (findJankEntry!.depth! + 0.5);
85    endRowEl = endParentRow;
86    endOffSetY = 10 * (findJankEntry!.depth! + 0.5);
87  }
88  let startY = startRow!.translateY! + 20 * (selectJankStruct!.depth! + 0.5);
89  let startRowEl = startRow;
90  let startOffSetY = 20 * (selectJankStruct!.depth! + 0.5);
91  expansionFlag = collectionHasJank(startRow, collectList);
92  if (startParentRow && !startParentRow.expansion && expansionFlag) {
93    startY = startParentRow!.translateY! + 10 * (selectJankStruct!.depth! + 0.5);
94    startRowEl = startParentRow;
95    startOffSetY = 10 * (selectJankStruct!.depth! + 0.5);
96  }
97  let startX = ns2xByTimeShaft(tts, sp.timerShaftEL!);
98  let endX = ns2xByTimeShaft(findJankEntry.ts!, sp.timerShaftEL!);
99  const startPoint = setPoint(startX, startY, startOffSetY, tts, startRowEl, selectJankStruct.ts == tts, 'janks');
100  const endPoint = setPoint(endX, endY, endOffSetY, findJankEntry.ts!, endRowEl, true, 'janks');
101  sp.addPointPair(startPoint, endPoint);
102}
103
104function findJankApp(
105  endParentRow: any,
106  sp: SpSystemTrace,
107  data: any,
108  startRow: any,
109  selectJankStruct: JankStruct,
110  endRowStruct: any
111): void {
112  let collectList = sp.favoriteChartListEL!.getAllCollectRows();
113  let findJankEntry = endRowStruct!.dataListCache!.find((dat: any) => dat.name == data.name && dat.pid == data.pid);
114  let tts = selectJankStruct.frame_type == 'frameTime' ? findJankEntry.ts : findJankEntry.ts! + findJankEntry.dur!;
115  let endY = endRowStruct!.translateY! + 20 * (findJankEntry!.depth! + 0.5);
116  let endRowEl = endRowStruct;
117  let endOffSetY = 20 * (findJankEntry!.depth! + 0.5);
118  let expansionFlag = collectionHasJank(endRowStruct, collectList);
119  if (!endParentRow.expansion && expansionFlag) {
120    endY = endParentRow!.translateY! + 10 * (findJankEntry!.depth! + 0.5);
121    endRowEl = endParentRow;
122    endOffSetY = 10 * (findJankEntry!.depth! + 0.5);
123  }
124  let startY = startRow!.translateY! + 20 * (selectJankStruct!.depth! + 0.5);
125  let startRowEl = startRow;
126  expansionFlag = collectionHasJank(startRow, collectList);
127  let startOffsetY = 20 * (selectJankStruct!.depth! + 0.5);
128  let startParentRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>(
129    `trace-row[row-id='${startRow.rowParentId}'][folder]`
130  );
131  if (startParentRow && !startParentRow.expansion && expansionFlag) {
132    startY = startParentRow!.translateY! + 10 * (selectJankStruct!.depth! + 0.5);
133    startRowEl = startParentRow;
134    startOffsetY = 10 * (selectJankStruct!.depth! + 0.5);
135  }
136  let startX = ns2xByTimeShaft(selectJankStruct.ts!, sp.timerShaftEL!);
137  let endX = ns2xByTimeShaft(tts, sp.timerShaftEL!);
138  const startPoint = setPoint(startX, startY, startOffsetY, selectJankStruct.ts!, startRowEl, true, 'janks');
139  const endPoint = setPoint(endX, endY, endOffSetY, tts, endRowEl, selectJankStruct.ts == tts, 'janks');
140  sp.addPointPair(startPoint, endPoint);
141}
142
143function addPointLink(
144  endParentRow: any,
145  sp: SpSystemTrace,
146  data: any,
147  startRow: any,
148  selectJankStruct: JankStruct,
149  endRowStruct: any
150): void {
151  let findJankEntry = endRowStruct!.dataListCache!.find((dat: any) => dat.name == data.name && dat.pid == data.pid);
152  //连线规则:frametimeline的头----app的头,app的尾----renderservice的头
153  let tts: number = 0;
154  if (findJankEntry) {
155    if (selectJankStruct.frame_type == 'app') {
156      selectJankApp(endParentRow, sp, data, startRow, selectJankStruct, endRowStruct);
157    }
158    if (findJankEntry.frame_type == 'app') {
159      findJankApp(endParentRow, sp, data, startRow, selectJankStruct, endRowStruct);
160    }
161    if (data.children.length >= 1) {
162      let endP;
163      if (data.children[0].frame_type == 'frameTime') {
164        endP = sp.shadowRoot?.querySelector<TraceRow<any>>("trace-row[row-id='frameTime']");
165      } else {
166        endP = sp.shadowRoot?.querySelector<TraceRow<any>>(`trace-row[row-id='${data.children[0].pid}'][folder]`);
167      }
168      sp.drawJankLine(endP, findJankEntry, data.children[0]);
169    }
170  }
171}
172
173function getEndStruct(data: any, sp: SpSystemTrace): any {
174  let endRowStruct: any;
175  if (data.frame_type == 'frameTime') {
176    endRowStruct = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>(
177      "trace-row[row-id='actual frameTime'][row-type='janks']"
178    );
179  } else {
180    endRowStruct = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>(
181      `trace-row[row-id='${data.type}-${data.pid}'][row-type='janks']`
182    );
183  }
184  return endRowStruct;
185}
186
187function drawJankLineEndParent(
188  endParentRow: any,
189  sp: SpSystemTrace,
190  data: any,
191  startRow: any,
192  selectJankStruct: JankStruct
193): void {
194  endParentRow.expansion = true;
195  //终点的父泳道过滤出选中的Struct
196  let endRowStruct = getEndStruct(data, sp);
197  //泳道未展开的情况,查找endRowStruct
198  if (!endRowStruct) {
199    if (data.frame_type == 'frameTime') {
200      endParentRow.childrenList.forEach((item: TraceRow<JankStruct>) => {
201        if (item.rowId === 'actual frameTime' && item.rowType === 'janks') {
202          endRowStruct = item;
203        }
204      });
205      //frameTime未展开
206      if (!endRowStruct) {
207        endParentRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>("trace-row[row-id='frameTime'][folder]");
208        endParentRow?.childrenList?.forEach((item: TraceRow<JankStruct>) => {
209          if (item.rowId === 'actual frameTime' && item.rowType === 'janks') {
210            endRowStruct = item;
211          }
212        });
213      }
214    } else {
215      endParentRow.childrenList.forEach((item: TraceRow<JankStruct>) => {
216        if (item.name.startsWith('Actual Timeline') && item.rowType === 'janks') {
217          endRowStruct = item;
218        }
219      });
220    }
221  }
222  if (endRowStruct) {
223    if (endRowStruct.isComplete) {
224      addPointLink(endParentRow, sp, data, startRow, selectJankStruct, endRowStruct);
225    } else {
226      endRowStruct.supplierFrame!().then((res: any) => {
227        endRowStruct.dataListCache = res;
228        endRowStruct.loadingFrame = false;
229        addPointLink(endParentRow, sp, data, startRow, selectJankStruct, endRowStruct);
230      });
231    }
232  }
233}
234
235export function spSystemTraceDrawJankLine(
236  sp: SpSystemTrace,
237  endParentRow: any,
238  selectJankStruct: JankStruct,
239  data: any
240): void {
241  let collectList = sp.favoriteChartListEL!.getAllCollectRows();
242  let startRow: any;
243  if (selectJankStruct == undefined || selectJankStruct == null) {
244    return;
245  }
246  let selectRowId = 'actual frameTime';
247  if (selectJankStruct.frame_type == 'frameTime') {
248    startRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>(
249      `trace-row[row-id='${selectRowId}'][row-type='janks']`
250    );
251  } else {
252    selectRowId = selectJankStruct?.type + '-' + selectJankStruct?.pid;
253    startRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>(
254      `trace-row[row-id='${selectRowId}'][row-type='janks']`
255    );
256  }
257  if (!startRow) {
258    for (let collectChart of collectList) {
259      if (collectChart.rowId === selectRowId && collectChart.rowType === 'janks') {
260        startRow = collectChart;
261        break;
262      }
263    }
264  }
265  if (endParentRow) {
266    drawJankLineEndParent(endParentRow, sp, data, startRow, selectJankStruct);
267  }
268}
269
270function taskPoolOtherRelationData(
271  selectRow: any,
272  sp: SpSystemTrace,
273  row: TraceRow<any>,
274  relationDataList: FuncStruct[],
275  res: any
276): void {
277  selectRow!.fixedList = relationDataList;
278  relationDataList.forEach((value) => {
279    TabPaneTaskFrames.TaskArray.push(value);
280    // allocation to execute
281    const selectY = (FuncStruct.selectFuncStruct!.depth! + 0.5) * 20;
282    const offSetY = (value.depth! + 0.5) * 20;
283    const selectRowY = selectRow?.translateY!;
284    const selectStartTs = FuncStruct.selectFuncStruct!.startTs!;
285    const selectDur = FuncStruct.selectFuncStruct!.dur!;
286
287    if (value.id === res[0].allocation_task_row) {
288      sp.addPointPair(
289        sp.makePoint(value.startTs!, 0, selectRowY, selectRow, offSetY, 'task', LineType.bezierCurve, true),
290        sp.makePoint(selectStartTs, 0, row?.translateY!, row, selectY, 'task', LineType.bezierCurve, true)
291      );
292    } else {
293      sp.addPointPair(
294        sp.makePoint(selectStartTs, selectDur, row?.translateY!, row, selectY, 'task', LineType.bezierCurve, false),
295        sp.makePoint(value.startTs!, value.dur!, selectRowY, selectRow, offSetY, 'task', LineType.bezierCurve, false)
296      );
297    }
298  });
299  sp.refreshCanvas(true);
300}
301
302function taskPoolRelationDataAllocation(
303  executeRow: TraceRow<FuncStruct> | null | undefined,
304  sp: SpSystemTrace,
305  row: TraceRow<any>,
306  relationDataList: FuncStruct[],
307  res: any
308): void {
309  let executeStruct = relationDataList.filter((item) => item.id === res[0].execute_task_row)[0];
310  relationDataList.forEach((value) => {
311    const selectY = (FuncStruct.selectFuncStruct!.depth! + 0.5) * 20;
312    const offSetY = (value.depth! + 0.5) * 20;
313    const executeRowY = executeRow?.translateY!;
314    const selectStartTs = FuncStruct.selectFuncStruct!.startTs!;
315    const executeY = (executeStruct.depth! + 0.5) * 20;
316    TabPaneTaskFrames.TaskArray.push(value);
317    if (value.id === res[0].execute_task_row) {
318      sp.addPointPair(
319        sp.makePoint(selectStartTs, 0, row?.translateY!, row, selectY, 'task', LineType.bezierCurve, true),
320        sp.makePoint(value.startTs!, 0, executeRowY, executeRow, offSetY, 'task', LineType.bezierCurve, true)
321      );
322    } else {
323      sp.addPointPair(
324        sp.makePoint(
325          executeStruct.startTs!,
326          executeStruct.dur!,
327          executeRowY,
328          executeRow,
329          executeY,
330          'task',
331          LineType.bezierCurve,
332          false
333        ),
334        sp.makePoint(value.startTs!, value.dur!, row?.translateY!, row, offSetY, 'task', LineType.bezierCurve, false)
335      );
336    }
337  });
338}
339
340function taskPoolRelationDataPerformTask(
341  executeRow: TraceRow<FuncStruct> | null | undefined,
342  sp: SpSystemTrace,
343  row: TraceRow<any>,
344  relationDataList: FuncStruct[],
345  res: any
346): void {
347  let executeStruct = relationDataList.filter((item) => item.id === res[0].execute_task_row)[0];
348  relationDataList.forEach((value) => {
349    const executeRowY = executeRow?.translateY!;
350    const selectStartTs = FuncStruct.selectFuncStruct!.startTs!;
351    const executeY = (executeStruct.depth! + 0.5) * 20;
352    const selectY = (FuncStruct.selectFuncStruct!.depth! + 0.5) * 20;
353    const offSetY = (value.depth! + 0.5) * 20;
354    TabPaneTaskFrames.TaskArray.push(value);
355    if (value.id === res[0].execute_task_row) {
356      sp.addPointPair(
357        sp.makePoint(
358          selectStartTs,
359          FuncStruct.selectFuncStruct!.dur!,
360          row?.translateY!,
361          row,
362          selectY,
363          'task',
364          LineType.bezierCurve,
365          false
366        ),
367        sp.makePoint(value.startTs!, value.dur!, executeRowY, executeRow, offSetY, 'task', LineType.bezierCurve, false)
368      );
369    } else {
370      sp.addPointPair(
371        sp.makePoint(executeStruct.startTs!, 0, executeRowY, executeRow, executeY, 'task', LineType.bezierCurve, true),
372        sp.makePoint(value.startTs!, 0, row?.translateY!, row, offSetY, 'task', LineType.bezierCurve, true)
373      );
374    }
375  });
376  sp.refreshCanvas(true);
377}
378
379function taskAllocationOrPerformTask(sp: SpSystemTrace, row: TraceRow<any>, executeID: string): void {
380  TabPaneTaskFrames.IsShowConcurrency = false;
381  queryBySelectAllocationOrReturn(executeID, FuncStruct.selectFuncStruct!.itid!).then((res) => {
382    if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task Allocation:') >= 0 && res.length > 0) {
383      let executeRow = sp.shadowRoot?.querySelector<TraceRow<FuncStruct>>(
384        `trace-row[row-id='${res[0].tid}'][row-type='func']`
385      );
386      if (!executeRow) {
387        return;
388      }
389      let idList: number[] = [];
390      let tidList: number[] = [];
391      if (res[0].execute_task_row) {
392        idList.push(res[0].execute_task_row);
393        tidList.push(Number(res[0].tid));
394      }
395      if (res[0].return_task_row) {
396        idList.push(res[0].return_task_row);
397        tidList.push(Number(row.rowId));
398      }
399      queryTaskPoolRelationData(idList, tidList).then((relationDataList) => {
400        taskPoolRelationDataAllocation(executeRow, sp, row, relationDataList, res);
401      });
402    } else if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task PerformTask End:') >= 0) {
403      let executeRow = sp.shadowRoot?.querySelector<TraceRow<FuncStruct>>(
404        `trace-row[row-id='${res[0].tid}'][row-type='func']`
405      );
406      TabPaneTaskFrames.TaskArray.push(FuncStruct.selectFuncStruct!);
407      let idList: number[] = [];
408      let tidList: number[] = [];
409      if (res[0].execute_task_row) {
410        idList.push(res[0].execute_task_row);
411        tidList.push(Number(res[0].tid));
412      }
413      if (res[0].allocation_task_row) {
414        idList.push(res[0].allocation_task_row);
415        tidList.push(Number(row.rowId));
416      }
417      queryTaskPoolRelationData(idList, tidList).then((relationDataList) => {
418        taskPoolRelationDataPerformTask(executeRow, sp, row, relationDataList, res);
419      });
420    }
421  });
422}
423
424export function spSystemTraceDrawTaskPollLine(sp: SpSystemTrace, row?: TraceRow<any>): void {
425  let executeID = TabPaneTaskFrames.getExecuteId(FuncStruct.selectFuncStruct!.funName!);
426  TabPaneTaskFrames.TaskArray.push(FuncStruct.selectFuncStruct!);
427  if (!row) {
428    return;
429  }
430  if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task Perform:') >= 0) {
431    TabPaneTaskFrames.IsShowConcurrency = true;
432    queryBySelectExecute(executeID, FuncStruct.selectFuncStruct!.itid!).then((res) => {
433      if (res.length === 1) {
434        let allocationRowId = res[0].tid;
435        let selectRow = sp.shadowRoot?.querySelector<TraceRow<FuncStruct>>(
436          `trace-row[row-id='${allocationRowId}'][row-type='func']`
437        );
438        if (!selectRow) {
439          let collectList = sp.favoriteChartListEL!.getAllCollectRows();
440          for (let selectCollectRow of collectList) {
441            if (selectCollectRow.rowId === allocationRowId.toString() && selectCollectRow.rowType === 'func') {
442              selectRow = selectCollectRow;
443              break;
444            }
445          }
446        }
447        let idList: number[] = [];
448        if (res[0].allocation_task_row) {
449          idList.push(res[0].allocation_task_row);
450        }
451        if (res[0].return_task_row) {
452          idList.push(res[0].return_task_row);
453        }
454        queryTaskPoolOtherRelationData(idList, allocationRowId).then((relationDataList) => {
455          taskPoolOtherRelationData(selectRow, sp, row, relationDataList, res);
456        });
457      }
458    });
459  } else {
460    taskAllocationOrPerformTask(sp, row, executeID);
461  }
462}
463
464function jankPoint(
465  endRowStruct: any,
466  data: any,
467  sp: SpSystemTrace,
468  selectThreadStruct: ThreadStruct,
469  startRow: any,
470  endParentRow: any
471): void {
472  if (endRowStruct) {
473    let findJankEntry = endRowStruct!.dataListCache!.find(
474      (dat: any) => dat.startTime == data.startTime && dat.dur! > 0
475    );
476    let ts: number = 0;
477    if (findJankEntry) {
478      ts = selectThreadStruct.startTime! + selectThreadStruct.dur! / 2;
479      const [startY, startRowEl, startOffSetY] = sp.calculateStartY(startRow, selectThreadStruct);
480      const [endY, endRowEl, endOffSetY] = sp.calculateEndY(endParentRow, endRowStruct);
481      sp.addPointPair(
482        sp.makePoint(
483          ns2xByTimeShaft(ts, sp.timerShaftEL!),
484          ts,
485          startY,
486          startRowEl!,
487          startOffSetY,
488          'thread',
489          LineType.straightLine,
490          selectThreadStruct.startTime == ts
491        ),
492        sp.makePoint(
493          ns2xByTimeShaft(findJankEntry.startTime!, sp.timerShaftEL!),
494          findJankEntry.startTime!,
495          endY,
496          endRowEl,
497          endOffSetY,
498          'thread',
499          LineType.straightLine,
500          true
501        )
502      );
503      sp.refreshCanvas(true);
504    }
505  }
506}
507
508export function spSystemTraceDrawThreadLine(
509  sp: SpSystemTrace,
510  endParentRow: any,
511  selectThreadStruct: ThreadStruct | undefined,
512  data: any
513): void {
514  const collectList = sp.favoriteChartListEL!.getCollectRows();
515  if (!selectThreadStruct) {
516    return;
517  }
518  const selectRowId = selectThreadStruct?.tid;
519  let startRow = sp.getStartRow(selectRowId, collectList);
520  if (!endParentRow) {
521    return;
522  }
523  let endRowStruct: any = sp.shadowRoot?.querySelector<TraceRow<ThreadStruct>>(
524    `trace-row[row-id='${data.tid}'][row-type='thread']`
525  );
526  if (!endRowStruct) {
527    endRowStruct = endParentRow.childrenList.find((item: TraceRow<ThreadStruct>) => {
528      return item.rowId === `${data.tid}` && item.rowType === 'thread';
529    });
530  }
531  jankPoint(endParentRow, data, sp, selectThreadStruct, startRow, endParentRow);
532}
533