• 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 { ColorUtils } from "../../component/trace/base/ColorUtils.js";
17import {
18    BaseStruct,
19    drawFlagLine,
20    drawLines,
21    drawLoading,
22    drawSelection, PerfRender,
23    RequestMessage
24} from "./ProcedureWorkerCommon.js";
25import {HiPerfCpuStruct} from "./ProcedureWorkerHiPerfCPU.js";
26
27export class HiperfThreadRender extends PerfRender {
28    render(req: RequestMessage, list: Array<any>, filter: Array<any>, dataList2: Array<any>) {
29        let groupBy10MS = req.scale > 100_000_000;
30        if (req.lazyRefresh) {
31            hiPerfThread(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.intervalPerf, req.useCache || !req.range.refresh);
32        } else {
33            if (!req.useCache) {
34                hiPerfThread(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, groupBy10MS, req.intervalPerf, false);
35            }
36        }
37        if (req.canvas) {
38            req.context.clearRect(0, 0, req.frame.width, req.frame.height);
39            let arr = filter;
40            if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) {
41                drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startNS, arr[arr.length - 1].startNS + arr[arr.length - 1].dur)
42            }
43            drawLines(req.context, req.xs, req.frame.height, req.lineColor)
44            req.context.stroke();
45            req.context.beginPath();
46            HiPerfThreadStruct.hoverStruct = undefined;
47            req.context.fillStyle = ColorUtils.FUNC_COLOR[0];
48            req.context.strokeStyle = ColorUtils.FUNC_COLOR[0];
49            if (req.isHover) {
50                let offset = groupBy10MS ? 0 : 3;
51                for (let re of filter) {
52                    if (re.frame && req.hoverX >= re.frame.x - offset && req.hoverX <= re.frame.x + re.frame.width + offset) {//&& req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height
53                        HiPerfThreadStruct.hoverStruct = re;
54                        break;
55                    }
56                }
57            } else {
58                HiPerfThreadStruct.hoverStruct = req.params.hoverStruct;
59            }
60            HiPerfThreadStruct.selectStruct = req.params.selectStruct;
61            let path = new Path2D();
62            for (let re of filter) {
63                HiPerfThreadStruct.draw(req.context, path, re, groupBy10MS);
64            }
65            groupBy10MS ? req.context.fill(path) : req.context.stroke(path);
66            req.context.stroke();
67            req.context.closePath();
68            drawSelection(req.context, req.params);
69            drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime);
70        }
71        // @ts-ignore
72        self.postMessage({
73            id: req.id,
74            type: req.type,
75            results: req.canvas ? undefined : filter,
76            hover: HiPerfThreadStruct.hoverStruct
77        });
78    }
79}
80
81export function hiPerfThread(arr: Array<any>, res: Array<any>, startNS: number, endNS: number, totalNS: number, frame: any, groupBy10MS: boolean, intervalPerf: number, use: boolean) {
82    if (use && res.length > 0) {
83        let pns = (endNS - startNS) / frame.width;
84        let y = frame.y;
85        for (let i = 0; i < res.length; i++) {
86            let it = res[i];
87            if ((it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) {
88                if (!it.frame) {
89                    it.frame = {};
90                    it.frame.y = y;
91                }
92                it.frame.height = it.height;
93                HiPerfThreadStruct.setFrame(it, pns, startNS, endNS, frame);
94            } else {
95                it.frame = null;
96            }
97        }
98        return;
99    }
100    res.length = 0;
101    if (arr) {
102        let list = groupBy10MS ? HiPerfThreadStruct.groupBy10MS(arr, intervalPerf) : arr;
103        let pns = (endNS - startNS) / frame.width;
104        let y = frame.y;
105        for (let i = 0, len = list.length; i < len; i++) {
106            let it = list[i];
107            if ((it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) {
108                if (!list[i].frame) {
109                    list[i].frame = {};
110                    list[i].frame.y = y;
111                }
112                list[i].frame.height = it.height;
113                HiPerfThreadStruct.setFrame(list[i], pns, startNS, endNS, frame)
114                if (groupBy10MS) {
115                    if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0)
116                        && ((list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))
117                        && ((list[i - 1].frame?.height || 0) == (list[i].frame?.height || 0))
118                    )) {
119
120                    } else {
121                        res.push(list[i])
122                    }
123                } else {
124                    if (i > 0 && (Math.abs((list[i - 1].frame?.x || 0) - (list[i].frame?.x || 0)) < 4)) {
125                    } else {
126                        res.push(list[i])
127                    }
128                }
129            }
130        }
131    }
132}
133
134export class HiPerfThreadStruct extends BaseStruct {
135    static hoverStruct: HiPerfThreadStruct | undefined;
136    static selectStruct: HiPerfThreadStruct | undefined;
137    id: number | undefined;
138    callchain_id: number | undefined;
139    timestamp: number | undefined;
140    thread_id: number | undefined;
141    event_count: number | undefined;
142    event_type_id: number | undefined;
143    cpu_id: number | undefined;
144    thread_state: string | undefined;
145    //------------------------------------------------------
146    startNS: number | undefined;
147    endNS: number | undefined;
148    dur: number | undefined;
149    height: number | undefined;
150    cpu: number | undefined;
151
152    static draw(ctx: CanvasRenderingContext2D, path: Path2D, data: HiPerfThreadStruct, groupBy10MS: boolean) {
153        if (data.frame) {
154            if (groupBy10MS) {
155                let width = data.frame.width;
156                path.rect(data.frame.x, 40 - (data.height || 0), width, data.height || 0)
157            } else {
158                path.moveTo(data.frame.x + 7, 20);
159                HiPerfCpuStruct.drawRoundRectPath(path, data.frame.x - 7, 20 - 7, 14, 14, 3)
160                path.moveTo(data.frame.x, 27);
161                path.lineTo(data.frame.x, 33);
162            }
163        }
164    }
165
166    static setFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) {
167        if ((node.startNS || 0) < startNS) {
168            node.frame.x = 0;
169        } else {
170            node.frame.x = Math.floor(((node.startNS || 0) - startNS) / pns);
171        }
172        if ((node.startNS || 0) + (node.dur || 0) > endNS) {
173            node.frame.width = frame.width - node.frame.x;
174        } else {
175            node.frame.width = Math.ceil(((node.startNS || 0) + (node.dur || 0) - startNS) / pns - node.frame.x);
176        }
177        if (node.frame.width < 1) {
178            node.frame.width = 1;
179        }
180    }
181
182    static groupBy10MS(array: Array<any>, intervalPerf: number): Array<any> {
183        let obj = array.map(it => {
184            it.timestamp_group = Math.trunc(it.startNS / 1_000_000_0) * 1_000_000_0;
185            return it;
186        }).reduce((pre, current) => {
187            (pre[current["timestamp_group"]] = pre[current["timestamp_group"]] || []).push(current);
188            return pre;
189        }, {});
190        let arr: any[] = [];
191        for (let aKey in obj) {
192            let ns = parseInt(aKey);
193            let height: number = 0;
194            height = Math.floor(obj[aKey].length / (10 / intervalPerf) * 40);
195            arr.push({
196                startNS: ns,
197                height: height,
198                dur: 1_000_000_0,
199            })
200        }
201        return arr;
202    }
203}
204