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