• 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 { SpSystemTrace } from '../SpSystemTrace';
17import { TraceRow } from '../trace/base/TraceRow';
18import { renders } from '../../database/ui-worker/ProcedureWorker';
19import { info } from '../../../log/Log';
20import { ClockRender, ClockStruct } from '../../database/ui-worker/ProcedureWorkerClock';
21import { ColorUtils } from '../trace/base/ColorUtils';
22import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU';
23import { Utils } from '../trace/base/Utils';
24import { clockDataSender } from '../../database/data-trafic/ClockDataSender';
25import {queryClockData} from "../../database/sql/Clock.sql";
26
27export class SpClockChart {
28  private trace: SpSystemTrace;
29
30  constructor(trace: SpSystemTrace) {
31    this.trace = trace;
32  }
33
34  async init() {
35    let folder = await this.initFolder();
36    await this.initData(folder);
37  }
38
39  async initData(folder: TraceRow<any>) {
40    let clockStartTime = new Date().getTime();
41    let clockList = await queryClockData();
42    if (clockList.length == 0) {
43      return;
44    }
45    info('clockList data size is: ', clockList!.length);
46    this.trace.rowsEL?.appendChild(folder);
47    ClockStruct.maxValue = clockList.map((item) => item.num).reduce((a, b) => Math.max(a, b));
48    for (let i = 0; i < clockList.length; i++) {
49      const it = clockList[i];
50      let maxValue = 0;
51      let traceRow = TraceRow.skeleton<ClockStruct>();
52      let isState = it.name.endsWith(' State');
53      let isScreenState = it.name.endsWith('ScreenState');
54      traceRow.rowId = it.name;
55      traceRow.rowType = TraceRow.ROW_TYPE_CLOCK;
56      traceRow.rowParentId = folder.rowId;
57      traceRow.style.height = '40px';
58      traceRow.name = it.name;
59      traceRow.rowHidden = !folder.expansion;
60      traceRow.setAttribute('children', '');
61      traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
62      traceRow.selectChangeHandler = this.trace.selectChangeHandler;
63      traceRow.supplierFrame = () => {
64        let promiseData = null;
65        if (it.name.endsWith(' Frequency')) {
66          promiseData = clockDataSender(it.srcname, 'clockFrequency', traceRow);
67        } else if (isState) {
68          promiseData = clockDataSender(it.srcname, 'clockState', traceRow);
69        } else if (isScreenState) {
70          promiseData = clockDataSender('', 'screenState', traceRow);
71        }
72        if (promiseData == null) {
73          return new Promise<Array<any>>((resolve) => resolve([]));
74        } else {
75          return promiseData.then((resultClock: Array<any>) => {
76            for (let j = 0; j < resultClock.length; j++) {
77              resultClock[j].type = 'measure';
78              if ((resultClock[j].value || 0) > maxValue) {
79                maxValue = resultClock[j].value || 0;
80              }
81              if (j > 0) {
82                resultClock[j].delta = (resultClock[j].value || 0) - (resultClock[j - 1].value || 0);
83              } else {
84                resultClock[j].delta = 0;
85              }
86            }
87            return resultClock;
88          });
89        }
90      };
91      traceRow.getCacheData = (args: any): Promise<Array<any>> | undefined => {
92        if (it.name.endsWith(' Frequency')) {
93          return clockDataSender(it.srcname, 'clockFrequency', traceRow, args);
94        } else if (isState) {
95          return clockDataSender(it.srcname, 'clockState', traceRow, args);
96        } else if (isScreenState) {
97          return clockDataSender('', 'screenState', traceRow, args);
98        }
99      };
100      traceRow.focusHandler = (ev) => {
101        this.trace?.displayTip(
102          traceRow,
103          ClockStruct.hoverClockStruct,
104          `<span>${ColorUtils.formatNumberComma(ClockStruct.hoverClockStruct?.value!)}</span>`
105        );
106      };
107      traceRow.findHoverStruct = () => {
108        ClockStruct.hoverClockStruct = traceRow.getHoverStruct();
109      };
110      traceRow.onThreadHandler = (useCache) => {
111        let context: CanvasRenderingContext2D;
112        if (traceRow.currentContext) {
113          context = traceRow.currentContext;
114        } else {
115          context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
116        }
117        traceRow.canvasSave(context);
118        (renders['clock'] as ClockRender).renderMainThread(
119          {
120            context: context,
121            useCache: useCache,
122            type: it.name,
123            maxValue: maxValue === 0 ? 1 : maxValue,
124            index: i,
125            maxName:
126              isState || isScreenState ? maxValue.toString() : Utils.getFrequencyWithUnit(maxValue / 1000).maxFreqName,
127          },
128          traceRow
129        );
130        traceRow.canvasRestore(context, this.trace);
131      };
132      folder.addChildTraceRow(traceRow);
133    }
134    let durTime = new Date().getTime() - clockStartTime;
135    info('The time to load the ClockData is: ', durTime);
136  }
137
138  async initFolder(): Promise<TraceRow<any>> {
139    let clockFolder = TraceRow.skeleton();
140    clockFolder.rowId = `Clocks`;
141    clockFolder.index = 0;
142    clockFolder.rowType = TraceRow.ROW_TYPE_CLOCK_GROUP;
143    clockFolder.rowParentId = '';
144    clockFolder.style.height = '40px';
145    clockFolder.folder = true;
146    clockFolder.name = `Clocks`; /* & I/O Latency */
147    clockFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler;
148    clockFolder.selectChangeHandler = this.trace.selectChangeHandler;
149    clockFolder.supplier = () => new Promise<Array<any>>((resolve) => resolve([]));
150    clockFolder.onThreadHandler = (useCache) => {
151      clockFolder.canvasSave(this.trace.canvasPanelCtx!);
152      if (clockFolder.expansion) {
153        this.trace.canvasPanelCtx?.clearRect(0, 0, clockFolder.frame.width, clockFolder.frame.height);
154      } else {
155        (renders['empty'] as EmptyRender).renderMainThread(
156          {
157            context: this.trace.canvasPanelCtx,
158            useCache: useCache,
159            type: ``,
160          },
161          clockFolder
162        );
163      }
164      clockFolder.canvasRestore(this.trace.canvasPanelCtx!, this.trace);
165    };
166    return clockFolder;
167  }
168}
169