• 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 {TraceRow} from "../trace/base/TraceRow.js";
18import {procedurePool} from "../../database/Procedure.js";
19import {
20    queryHiPerfCpuData,
21    queryHiPerfCpuMergeData,
22    queryHiPerfEventData,
23    queryHiPerfEventList,
24    queryHiPerfEventListData,
25    queryHiPerfProcessData,
26    queryHiPerfThreadData,
27    queryPerfCmdline,
28    queryPerfThread
29} from "../../database/SqlLite.js";
30import {Utils} from "../trace/base/Utils.js";
31import {PerfThread} from "../../bean/PerfProfile.js";
32import {HiPerfCpuStruct} from "../../database/ProcedureWorkerHiPerfCPU.js";
33import {HiPerfThreadStruct} from "../../database/ProcedureWorkerHiPerfThread.js";
34import {HiPerfProcessStruct} from "../../database/ProcedureWorkerHiPerfProcess.js";
35import {info} from "../../../log/Log.js";
36import {HiPerfEventStruct} from "../../database/ProcedureWorkerHiPerfEvent.js";
37
38export interface ResultData {
39    existA: boolean | null | undefined,
40    existF: boolean | null | undefined,
41    fValue: number
42}
43
44export class SpHiPerf {
45    static hoverCpuStruct: HiPerfCpuStruct | undefined;
46    static hoverEventuctStruct: HiPerfEventStruct | undefined;
47    static selectCpuStruct: HiPerfCpuStruct | undefined;
48    static hoverProcessStruct: HiPerfProcessStruct | undefined;
49    static selectProcessStruct: HiPerfProcessStruct | undefined;
50    static hoverThreadStruct: HiPerfThreadStruct | undefined;
51    static selectThreadStruct: HiPerfThreadStruct | undefined;
52    static stringResult: ResultData | undefined;
53
54    private cpuData: Array<any> | undefined
55    public maxCpuId: number = 0
56    private rowFolder!: TraceRow<any>;
57    private perfThreads: Array<PerfThread> | undefined;
58    private trace: SpSystemTrace;
59    private group: any;
60    private eventTypeList: Array<{ id: number, report_value: string }> = [];
61
62    constructor(trace: SpSystemTrace) {
63        this.trace = trace;
64    }
65
66    async init() {
67        await this.initCmdLine()
68        this.perfThreads = await queryPerfThread();
69        this.eventTypeList = await queryHiPerfEventList();
70        info("PerfThread Data size is: ", this.perfThreads!.length)
71        this.group = Utils.groupBy(this.perfThreads || [], "pid");
72        this.cpuData = await queryHiPerfCpuMergeData();
73        this.maxCpuId = this.cpuData.length > 0 ? this.cpuData.reduce((max, v) => max.cpu_id >= v.cpu_id ? max : v).cpu_id : -Infinity;
74        if (this.cpuData.length > 0) {
75            await this.initFolder();
76            await this.initCpuMerge();
77            await this.initCpu();
78            await this.initProcess();
79        }
80        info("HiPerf Data initialized")
81    }
82
83    getStringResult(s: string = "") {
84        let list = s.split(" ").filter((e) => e);
85        let sA = list.findIndex((item) => item == "-a");
86        let sF = list.findIndex((item) => item == "-f");
87        SpHiPerf.stringResult = {
88            existA: sA !== -1,
89            existF: sF !== -1,
90            fValue: Number((1000 / (sF !== -1 ? parseInt(list[sF + 1]) : 1000)).toFixed(1)),
91        }
92    }
93
94    async initCmdLine() {
95        let perfCmdLines = await queryPerfCmdline();
96        if (perfCmdLines.length > 0) {
97            this.getStringResult(perfCmdLines[0].report_value)
98        } else {
99            SpHiPerf.stringResult = {
100                existA: true,
101                existF: false,
102                fValue: 1,
103            }
104        }
105    }
106
107    async initFolder() {
108        let row = new TraceRow({
109            canvasNumber: 1,
110            alpha: false,
111            contextId: '2d',
112            isOffScreen: SpSystemTrace.isCanvasOffScreen
113        });
114        row.setAttribute('disabled-check', '')
115        row.rowId = `HiPerf`;
116        row.index = 0;
117        row.rowType = TraceRow.ROW_TYPE_HIPERF
118        row.rowParentId = '';
119        row.folder = true;
120        if (SpHiPerf.stringResult?.existA === true) {
121            row.name = `HiPerf (All)`;
122        } else {
123            let names = Reflect.ownKeys(this.group).map((pid: any) => {
124                let array = this.group[pid] as Array<PerfThread>;
125                let process = array.filter(th => th.pid === th.tid)[0];
126                return process.processName;
127            }).join(',');
128            row.name = `HiPerf (${names})`;
129        }
130        row.supplier = () => new Promise<Array<any>>((resolve) => resolve([]));
131        row.onThreadHandler = (useCache) => {
132            procedurePool.submitWithName(`process${row.index}`, `HiPerf-Group`, {
133                list: row.must ? row.dataList : undefined,
134                offscreen: !row.isTransferCanvas ? row.offscreen[0] : undefined,
135                xs: TraceRow.range?.xs,
136                dpr: row.dpr,
137                isHover: row.isHover,
138                flagMoveInfo: this.trace.hoverFlag,
139                flagSelectedInfo: this.trace.selectFlag,
140                hoverX: row.hoverX,
141                hoverY: row.hoverY,
142                canvasWidth: row.canvasWidth,
143                canvasHeight: row.canvasHeight,
144                isRangeSelect: row.rangeSelect,
145                rangeSelectObject: TraceRow.rangeSelectObject,
146                useCache: useCache,
147                lineColor: row.getLineColor(),
148                startNS: TraceRow.range?.startNS || 0,
149                endNS: TraceRow.range?.endNS || 0,
150                totalNS: TraceRow.range?.totalNS || 0,
151                slicesTime: TraceRow.range?.slicesTime,
152                scale: TraceRow.range?.scale || 50,
153                intervalPerf: SpHiPerf.stringResult?.fValue || 1,
154                range:TraceRow.range,
155                frame: row.frame
156            }, !row.isTransferCanvas ? row.offscreen[0] : undefined, (res: any) => {
157                row.must = false;
158            })
159            row.isTransferCanvas = true;
160        }
161        this.rowFolder = row;
162        this.trace.rowsEL?.appendChild(row)
163    }
164
165    async initCpuMerge() {
166        let row = new TraceRow({
167            canvasNumber: 1,
168            alpha: false,
169            contextId: '2d',
170            isOffScreen: SpSystemTrace.isCanvasOffScreen
171        });
172        row.rowId = `HiPerf-cpu-merge`;
173        row.index = 0;
174        row.rowType = TraceRow.ROW_TYPE_HIPERF_CPU
175        row.rowParentId = 'HiPerf';
176        row.rowHidden = !this.rowFolder.expansion
177        row.folder = false;
178        row.name = `HiPerf`;
179        row.setAttribute('children', '')
180        row.favoriteChangeHandler = this.trace.favoriteChangeHandler;
181        row.selectChangeHandler = this.trace.selectChangeHandler;
182        let that = this;
183        row.supplier = () => queryHiPerfCpuMergeData();
184        row.onThreadHandler = (useCache) => {
185            procedurePool.submitWithName(`freq${row.index}`, `HiPerf-Cpu-Merge`, {
186                list: row.must ? row.dataList : undefined,
187                offscreen: !row.isTransferCanvas ? row.offscreen[0] : undefined,
188                xs: TraceRow.range?.xs,
189                dpr: row.dpr,
190                isHover: row.isHover,
191                flagMoveInfo: this.trace.hoverFlag,
192                flagSelectedInfo: this.trace.selectFlag,
193                hoverX: row.hoverX,
194                hoverY: row.hoverY,
195                canvasWidth: row.canvasWidth,
196                canvasHeight: row.canvasHeight,
197                hoverStruct: SpHiPerf.hoverCpuStruct,
198                selectStruct: SpHiPerf.selectCpuStruct,
199                isRangeSelect: row.rangeSelect,
200                rangeSelectObject: TraceRow.rangeSelectObject,
201                useCache: useCache,
202                lineColor: row.getLineColor(),
203                startNS: TraceRow.range?.startNS || 0,
204                endNS: TraceRow.range?.endNS || 0,
205                totalNS: TraceRow.range?.totalNS || 0,
206                slicesTime: TraceRow.range?.slicesTime,
207                scale: TraceRow.range?.scale || 50,
208                intervalPerf: SpHiPerf.stringResult?.fValue || 1,
209                range:TraceRow.range,
210                frame: row.frame,
211                maxCpu: (this.maxCpuId + 1)
212            }, !row.isTransferCanvas ? row.offscreen[0] : undefined, (res: any, hover: any) => {
213                row.must = false;
214                if (row.isHover) {
215                    SpHiPerf.hoverCpuStruct = hover;
216                }
217            })
218            row.isTransferCanvas = true;
219        }
220        this.trace.rowsEL?.appendChild(row)
221    }
222
223    async initCpu() {
224        for (let i = 0; i <= this.maxCpuId; i++) {
225            let row = new TraceRow({
226                canvasNumber: 1,
227                alpha: false,
228                contextId: '2d',
229                isOffScreen: SpSystemTrace.isCanvasOffScreen
230            });
231            row.rowId = `HiPerf-cpu-${i}`;
232            row.index = i;
233            row.rowType = TraceRow.ROW_TYPE_HIPERF_CPU
234            row.rowParentId = 'HiPerf';
235            row.rowHidden = !this.rowFolder.expansion
236            row.folder = false;
237            row.name = `Cpu ${i}`;
238            row.setAttribute('children', '')
239            row.favoriteChangeHandler = this.trace.favoriteChangeHandler;
240            row.selectChangeHandler = this.trace.selectChangeHandler;
241            let that = this;
242            row.supplier = () => queryHiPerfCpuData(i);
243            row.onThreadHandler = (useCache) => {
244                procedurePool.submitWithName(`cpu${row.index}`, `HiPerf-Cpu-${i}`, {
245                    list: row.must ? row.dataList : undefined,
246                    offscreen: !row.isTransferCanvas ? row.offscreen[0] : undefined,
247                    xs: TraceRow.range?.xs,
248                    dpr: row.dpr,
249                    isHover: row.isHover,
250                    flagMoveInfo: this.trace.hoverFlag,
251                    flagSelectedInfo: this.trace.selectFlag,
252                    hoverX: row.hoverX,
253                    hoverY: row.hoverY,
254                    canvasWidth: row.canvasWidth,
255                    canvasHeight: row.canvasHeight,
256                    hoverStruct: SpHiPerf.hoverCpuStruct,
257                    selectStruct: SpHiPerf.selectCpuStruct,
258                    isRangeSelect: row.rangeSelect,
259                    rangeSelectObject: TraceRow.rangeSelectObject,
260                    useCache: useCache,
261                    lineColor: row.getLineColor(),
262                    startNS: TraceRow.range?.startNS || 0,
263                    endNS: TraceRow.range?.endNS || 0,
264                    totalNS: TraceRow.range?.totalNS || 0,
265                    slicesTime: TraceRow.range?.slicesTime,
266                    scale: TraceRow.range?.scale || 50,
267                    intervalPerf: SpHiPerf.stringResult?.fValue || 1,
268                    range:TraceRow.range,
269                    frame: row.frame,
270                    maxCpu: undefined
271                }, !row.isTransferCanvas ? row.offscreen[0] : undefined, (res: any, hover: any) => {
272                    row.must = false;
273                    if (row.isHover) {
274                        SpHiPerf.hoverCpuStruct = hover;
275                    }
276                })
277                row.isTransferCanvas = true;
278            }
279            this.trace.rowsEL?.appendChild(row)
280        }
281    }
282
283    async initReport() {
284        this.eventTypeList.forEach((it, index) => {
285            let fold = new TraceRow({
286                canvasNumber: 1,
287                alpha: false,
288                contextId: '2d',
289                isOffScreen: SpSystemTrace.isCanvasOffScreen
290            });
291            fold.rowId = `Perf-Report-${it.id}-${it.report_value}`;
292            fold.index = index;
293            fold.rowType = TraceRow.ROW_TYPE_HIPERF_REPORT
294            fold.rowParentId = 'HiPerf';
295            fold.rowHidden = !this.rowFolder.expansion
296            fold.folder = true;
297            fold.name = `Event :${it.report_value}`;
298            fold.folderPaddingLeft = 30;
299            fold.favoriteChangeHandler = this.trace.favoriteChangeHandler;
300            fold.selectChangeHandler = this.trace.selectChangeHandler;
301            let that = this;
302            fold.supplier = () => queryHiPerfEventListData(it.id);
303            fold.onThreadHandler = (useCache) => {
304                procedurePool.submitWithName(`process${(fold.index) % procedurePool.processLen.length}`, `HiPerf-Report-Fold-${it.report_value}-${it.id}`, {
305                    list: fold.must ? fold.dataList : undefined,
306                    offscreen: !fold.isTransferCanvas ? fold.offscreen[0] : undefined,
307                    xs: TraceRow.range?.xs,
308                    dpr: fold.dpr,
309                    isHover: fold.isHover,
310                    flagMoveInfo: this.trace.hoverFlag,
311                    flagSelectedInfo: this.trace.selectFlag,
312                    hoverX: fold.hoverX,
313                    hoverY: fold.hoverY,
314                    canvasWidth: fold.canvasWidth,
315                    canvasHeight: fold.canvasHeight,
316                    isRangeSelect: fold.rangeSelect,
317                    rangeSelectObject: TraceRow.rangeSelectObject,
318                    useCache: useCache,
319                    lineColor: fold.getLineColor(),
320                    startNS: TraceRow.range?.startNS || 0,
321                    endNS: TraceRow.range?.endNS || 0,
322                    totalNS: TraceRow.range?.totalNS || 0,
323                    slicesTime: TraceRow.range?.slicesTime,
324                    scale: TraceRow.range?.scale || 50,
325                    intervalPerf: SpHiPerf.stringResult?.fValue || 1,
326                    range:TraceRow.range,
327                    frame: fold.frame
328                }, !fold.isTransferCanvas ? fold.offscreen[0] : undefined, (res: any, hover: any) => {
329                    fold.must = false;
330                    if (fold.isHover) {
331                    }
332                })
333                fold.isTransferCanvas = true;
334            }
335            this.trace.rowsEL?.appendChild(fold)
336
337            for (let i = 0; i <= this.maxCpuId; i++) {
338                let row = new TraceRow({
339                    canvasNumber: 1,
340                    alpha: false,
341                    contextId: '2d',
342                    isOffScreen: SpSystemTrace.isCanvasOffScreen
343                });
344                row.rowId = `HiPerf-Report-Event-${it.report_value}-${i}`;
345                row.index = i;
346                row.rowType = TraceRow.ROW_TYPE_HIPERF_EVENT
347                row.rowParentId = fold.rowId;
348                row.rowHidden = !fold.expansion
349                row.folder = false;
350                row.name = `Cpu ${i}`;
351                row.setAttribute('children', '')
352                row.favoriteChangeHandler = this.trace.favoriteChangeHandler;
353                row.selectChangeHandler = this.trace.selectChangeHandler;
354                let that = this;
355                row.supplier = () => queryHiPerfEventData(it.id, row.index);
356                row.onThreadHandler = (useCache) => {
357                    procedurePool.submitWithName(`process${row.index % procedurePool.processLen.length}`, `HiPerf-Report-Event-${it.report_value}-${i}`, {
358                        list: row.must ? row.dataList : undefined,
359                        offscreen: !row.isTransferCanvas ? row.offscreen[0] : undefined,
360                        xs: TraceRow.range?.xs,
361                        dpr: row.dpr,
362                        isHover: row.isHover,
363                        flagMoveInfo: this.trace.hoverFlag,
364                        flagSelectedInfo: this.trace.selectFlag,
365                        hoverX: row.hoverX,
366                        hoverY: row.hoverY,
367                        canvasWidth: row.canvasWidth,
368                        canvasHeight: row.canvasHeight,
369                        hoverStruct: SpHiPerf.hoverEventuctStruct,
370                        selectStruct: SpHiPerf.selectCpuStruct,
371                        isRangeSelect: row.rangeSelect,
372                        rangeSelectObject: TraceRow.rangeSelectObject,
373                        useCache: useCache,
374                        lineColor: row.getLineColor(),
375                        startNS: TraceRow.range?.startNS || 0,
376                        endNS: TraceRow.range?.endNS || 0,
377                        totalNS: TraceRow.range?.totalNS || 0,
378                        slicesTime: TraceRow.range?.slicesTime,
379                        scale: TraceRow.range?.scale || 50,
380                        intervalPerf: SpHiPerf.stringResult?.fValue || 1,
381                        range:TraceRow.range,
382                        frame: row.frame,
383                        maxCpu: undefined
384                    }, !row.isTransferCanvas ? row.offscreen[0] : undefined, (res: any, hover: any) => {
385                        row.must = false;
386                        if (row.isHover) {
387                            SpHiPerf.hoverEventuctStruct = hover;
388                        }
389                    })
390                    row.isTransferCanvas = true;
391                }
392                this.trace.rowsEL?.appendChild(row)
393            }
394        })
395    }
396
397    async initProcess() {
398        Reflect.ownKeys(this.group).forEach((key, index) => {
399            let array = this.group[key] as Array<PerfThread>;
400            let process = array.filter(th => th.pid === th.tid)[0];
401            let row = new TraceRow({
402                canvasNumber: 1,
403                alpha: false,
404                contextId: '2d',
405                isOffScreen: SpSystemTrace.isCanvasOffScreen
406            });
407            row.rowId = `${process.pid}-Perf-Process`;
408            row.index = index;
409            row.rowType = TraceRow.ROW_TYPE_HIPERF_PROCESS
410            row.rowParentId = 'HiPerf';
411            row.rowHidden = !this.rowFolder.expansion
412            row.folder = true;
413            row.name = `${process.processName||'Process'} [${process.pid}]`;
414            row.folderPaddingLeft = 30;
415            row.favoriteChangeHandler = this.trace.favoriteChangeHandler;
416            row.selectChangeHandler = this.trace.selectChangeHandler;
417            let that = this;
418            row.supplier = () => queryHiPerfProcessData(process.pid);
419            row.onThreadHandler = (useCache) => {
420                procedurePool.submitWithName(`process${(row.index) % procedurePool.processLen.length}`, `HiPerf-Process-${row.index}`, {
421                    list: row.must ? row.dataList : undefined,
422                    offscreen: !row.isTransferCanvas ? row.offscreen[0] : undefined,
423                    xs: TraceRow.range?.xs,
424                    dpr: row.dpr,
425                    isHover: row.isHover,
426                    flagMoveInfo: this.trace.hoverFlag,
427                    flagSelectedInfo: this.trace.selectFlag,
428                    hoverX: row.hoverX,
429                    hoverY: row.hoverY,
430                    canvasWidth: row.canvasWidth,
431                    canvasHeight: row.canvasHeight,
432                    hoverStruct: SpHiPerf.hoverProcessStruct,
433                    selectStruct: SpHiPerf.selectProcessStruct,
434                    isRangeSelect: row.rangeSelect,
435                    rangeSelectObject: TraceRow.rangeSelectObject,
436                    useCache: useCache,
437                    lineColor: row.getLineColor(),
438                    startNS: TraceRow.range?.startNS || 0,
439                    endNS: TraceRow.range?.endNS || 0,
440                    totalNS: TraceRow.range?.totalNS || 0,
441                    slicesTime: TraceRow.range?.slicesTime,
442                    scale: TraceRow.range?.scale || 50,
443                    intervalPerf: SpHiPerf.stringResult?.fValue || 1,
444                    range:TraceRow.range,
445                    frame: row.frame
446                }, !row.isTransferCanvas ? row.offscreen[0] : undefined, (res: any, hover: any) => {
447                    row.must = false;
448                    if (row.isHover) {
449                        SpHiPerf.hoverProcessStruct = hover;
450                    }
451                })
452                row.isTransferCanvas = true;
453            }
454            this.trace.rowsEL?.appendChild(row)
455
456            array.forEach((thObj, thIdx) => {
457                let thread = new TraceRow({
458                    canvasNumber: 1,
459                    alpha: false,
460                    contextId: '2d',
461                    isOffScreen: SpSystemTrace.isCanvasOffScreen
462                });
463                thread.rowId = `${thObj.tid}-Perf-Thread`;
464                thread.index = thIdx;
465                thread.rowType = TraceRow.ROW_TYPE_HIPERF_THREAD
466                thread.rowParentId = row.rowId;
467                thread.rowHidden = !row.expansion
468                thread.folder = false;
469                thread.name = `${thObj.threadName||'Thread'} [${thObj.tid}]`;
470                thread.setAttribute('children', '')
471                thread.folderPaddingLeft = 30;
472                thread.favoriteChangeHandler = this.trace.favoriteChangeHandler;
473                thread.selectChangeHandler = this.trace.selectChangeHandler;
474                let that = this;
475                thread.supplier = () => queryHiPerfThreadData(thObj.tid);
476                thread.onThreadHandler = (useCache) => {
477                    procedurePool.submitWithName(`process${(thread.index) % procedurePool.processLen.length}`, `HiPerf-Thread-${row.index}-${thread.index}`, {
478                        list: thread.must ? thread.dataList : undefined,
479                        offscreen: !thread.isTransferCanvas ? thread.offscreen[0] : undefined,
480                        xs: TraceRow.range?.xs,
481                        dpr: thread.dpr,
482                        isHover: thread.isHover,
483                        flagMoveInfo: this.trace.hoverFlag,
484                        flagSelectedInfo: this.trace.selectFlag,
485                        hoverX: thread.hoverX,
486                        hoverY: thread.hoverY,
487                        canvasWidth: thread.canvasWidth,
488                        canvasHeight: thread.canvasHeight,
489                        hoverStruct: SpHiPerf.hoverThreadStruct,
490                        selectStruct: SpHiPerf.selectThreadStruct,
491                        isRangeSelect: thread.rangeSelect,
492                        rangeSelectObject: TraceRow.rangeSelectObject,
493                        useCache: useCache,
494                        lineColor: thread.getLineColor(),
495                        startNS: TraceRow.range?.startNS || 0,
496                        endNS: TraceRow.range?.endNS || 0,
497                        totalNS: TraceRow.range?.totalNS || 0,
498                        slicesTime: TraceRow.range?.slicesTime,
499                        scale: TraceRow.range?.scale || 50,
500                        intervalPerf: SpHiPerf.stringResult?.fValue || 1,
501                        range:TraceRow.range,
502                        frame: thread.frame
503                    }, !thread.isTransferCanvas ? thread.offscreen[0] : undefined, (res: any, hover: any) => {
504                        thread.must = false;
505                        if (thread.isHover) {
506                            SpHiPerf.hoverThreadStruct = hover;
507                        }
508                    })
509                    thread.isTransferCanvas = true;
510                }
511                this.trace.rowsEL?.appendChild(thread)
512            });
513        })
514    }
515}
516