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 { PerfToolRender, PerfToolStruct } from '../../database/ui-worker/ProcedureWorkerPerfTool';
21import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU';
22import { queryPerfOutputData, queryPerfToolsDur } from '../../database/sql/SqlLite.sql';
23
24export class SpPerfOutputDataChart {
25  private trace: SpSystemTrace;
26  private startTime: number | undefined;
27  private perfOutputArr: Array<string> | undefined;
28  private dur: number | undefined;
29
30  constructor(trace: SpSystemTrace) {
31    this.trace = trace;
32  }
33
34  async init(): Promise<void> {
35    let perfOutputData = await queryPerfOutputData();
36    if (perfOutputData.length === 0) {
37      return;
38    }
39    let perfToolsDur = await queryPerfToolsDur();
40    if (perfToolsDur.length > 0) {
41      // @ts-ignore
42      this.dur = perfToolsDur[0].dur;
43    } else {
44      this.dur = 3000000000;
45    }
46    // @ts-ignore
47    this.perfOutputArr = perfOutputData[0].name.split(':')[2].split(',');
48    // @ts-ignore
49    let endTime: number = perfOutputData[0].ts;
50    this.startTime = endTime - window.recordStartNS - this.dur!;
51    if (this.startTime < 0) {
52      this.startTime = 0;
53    }
54    let folder = await this.initFolder();
55    this.trace.rowsEL?.appendChild(folder);
56    this.initData(folder);
57  }
58
59  private clockThreadHandler(
60    traceRow: TraceRow<PerfToolStruct>,
61    it: {
62      name: string;
63    },
64    perfId: number
65  ): void {
66    traceRow.onThreadHandler = (useCache): void => {
67      let context: CanvasRenderingContext2D;
68      if (traceRow.currentContext) {
69        context = traceRow.currentContext;
70      } else {
71        context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
72      }
73      traceRow.canvasSave(context);
74      (renders.perfTool as PerfToolRender).renderMainThread(
75        {
76          context: context,
77          useCache: useCache,
78          type: it.name,
79          index: perfId,
80        },
81        traceRow
82      );
83      traceRow.canvasRestore(context, this.trace);
84    };
85  }
86  //@ts-ignore
87  async initData(folder: TraceRow<unknown>): Promise<void> {
88    let perfToolStartTime = new Date().getTime();
89    let perfToolList = [
90      { name: 'Application Process CPU Power Consumption(MAS)', idx: 27 },
91      { name: 'RS Process CPU Power Consumption(MAS)', idx: 28 },
92      { name: 'Media Process CPU Power Consumption(MAS)', idx: 29 },
93      { name: 'Foundation Process CPU Power Consumption(MAS)', idx: 30 },
94      { name: 'Gpu Power Consumption(MAS)', idx: 31 },
95      { name: 'DDR Power Consumption(MAS)', idx: 32 },
96      { name: 'IO Count', idx: 35 },
97      { name: 'Block Count', idx: 36 },
98      { name: 'IPI Count(Application Main Thread)', idx: 51 },
99      { name: 'IPI Count(RS)', idx: 52 },
100    ];
101    info('perfTools data size is: ', perfToolList!.length);
102    for (let i = 0; i < perfToolList.length; i++) {
103      const it = perfToolList[i];
104      let traceRow = TraceRow.skeleton<PerfToolStruct>();
105      traceRow.rowId = i + '';
106      traceRow.rowType = TraceRow.ROW_TYPE_PERF_TOOL;
107      traceRow.rowParentId = folder.rowId;
108      traceRow.style.height = '24px';
109      traceRow.name = it.name;
110      traceRow.rowHidden = !folder.expansion;
111      traceRow.setAttribute('children', '');
112      traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
113      traceRow.selectChangeHandler = this.trace.selectChangeHandler;
114      traceRow.supplierFrame = (): Promise<PerfToolStruct[]> => {
115        let data = new PerfToolStruct();
116        data.startTs = this.startTime;
117        data.dur = this.dur;
118        data.count = this.perfOutputArr![it.idx];
119        data.id = i + 1;
120        data.name = it.name;
121        //@ts-ignore
122        return new Promise<Array<unknown>>((resolve) => resolve([data]));
123      };
124      traceRow.findHoverStruct = (): void => {
125        PerfToolStruct.hoverPerfToolStruct = traceRow.getHoverStruct();
126      };
127      this.clockThreadHandler(traceRow, it, i);
128      folder.addChildTraceRow(traceRow);
129    }
130    let durTime = new Date().getTime() - perfToolStartTime;
131    info('The time to load the ClockData is: ', durTime);
132  }
133  //@ts-ignore
134  async initFolder(): Promise<TraceRow<unknown>> {
135    let perfFolder = TraceRow.skeleton();
136    perfFolder.rowId = 'perfTool';
137    perfFolder.index = 0;
138    perfFolder.rowType = TraceRow.ROW_TYPE_PERF_TOOL_GROUP;
139    perfFolder.rowParentId = '';
140    perfFolder.style.height = '40px';
141    perfFolder.folder = true;
142    perfFolder.name = 'Perf Tools';
143    perfFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler;
144    perfFolder.selectChangeHandler = this.trace.selectChangeHandler;
145    //@ts-ignore
146    perfFolder.supplier = (): Promise<unknown[]> => new Promise<Array<unknown>>((resolve) => resolve([]));
147    perfFolder.onThreadHandler = (useCache): void => {
148      perfFolder.canvasSave(this.trace.canvasPanelCtx!);
149      if (perfFolder.expansion) {
150        this.trace.canvasPanelCtx?.clearRect(0, 0, perfFolder.frame.width, perfFolder.frame.height);
151      } else {
152        (renders.empty as EmptyRender).renderMainThread(
153          {
154            context: this.trace.canvasPanelCtx,
155            useCache: useCache,
156            type: '',
157          },
158          perfFolder
159        );
160      }
161      perfFolder.canvasRestore(this.trace.canvasPanelCtx!, this.trace);
162    };
163    return perfFolder;
164  }
165}
166