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