• 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, drawWakeUp, Render,
23    RequestMessage
24} from "./ProcedureWorkerCommon.js";
25
26export class EmptyRender extends Render{
27    render(req: RequestMessage, list: Array<any>, filter: Array<any>){
28        if (req.canvas) {
29            req.context.clearRect(0, 0, req.frame.width, req.frame.height);
30            req.context.beginPath();
31            drawLines(req.context, req.xs, req.frame.height, req.lineColor)
32            drawSelection(req.context, req.params);
33            req.context.closePath();
34            drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime);
35        }
36        // @ts-ignore
37        self.postMessage({
38            id: req.id,
39            type: req.type,
40            results: req.canvas ? undefined : filter,
41            hover: null
42        });
43    }
44}
45
46export class CpuRender {
47    render(req:RequestMessage,list:Array<any>,filter:Array<any>){
48        if (req.lazyRefresh) {
49            this.cpu(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, req.useCache || !req.range.refresh);
50        } else {
51            if (!req.useCache) {
52                this.cpu(list, filter, req.startNS, req.endNS, req.totalNS, req.frame, false);
53            }
54        }
55        if (req.canvas) {
56            req.context.clearRect(0, 0, req.frame.width, req.frame.height);
57            let arr = filter;
58            if (arr.length > 0 && !req.range.refresh && !req.useCache && req.lazyRefresh) {
59                drawLoading(req.context, req.startNS, req.endNS, req.totalNS, req.frame, arr[0].startTime, arr[arr.length - 1].startTime + arr[arr.length - 1].dur)
60            }
61            req.context.beginPath();
62            drawLines(req.context, req.xs, req.frame.height, req.lineColor);
63            CpuStruct.hoverCpuStruct = undefined;
64            if (req.isHover) {
65                for (let re of filter) {
66                    if (re.frame && req.hoverX >= re.frame.x && req.hoverX <= re.frame.x + re.frame.width && req.hoverY >= re.frame.y && req.hoverY <= re.frame.y + re.frame.height) {
67                        CpuStruct.hoverCpuStruct = re;
68                        break;
69                    }
70                }
71            } else {
72                CpuStruct.hoverCpuStruct = req.params.hoverCpuStruct;
73            }
74            CpuStruct.selectCpuStruct = req.params.selectCpuStruct;
75            req.context.font = "11px sans-serif";
76            for (let re of filter) {
77                CpuStruct.draw(req.context, re);
78            }
79            drawSelection(req.context, req.params);
80            req.context.closePath();
81            drawFlagLine(req.context, req.flagMoveInfo, req.flagSelectedInfo, req.startNS, req.endNS, req.totalNS, req.frame, req.slicesTime);
82            let currentCpu = parseInt(req.type!.replace("cpu-data-", ""));
83            drawWakeUp(req.context, req.wakeupBean, req.startNS, req.endNS, req.totalNS, req.frame, req.type == `cpu-data-${CpuStruct.selectCpuStruct?.cpu || 0}` ? CpuStruct.selectCpuStruct : undefined, currentCpu);
84        }
85        // @ts-ignore
86        self.postMessage({
87            id: req.id,
88            type: req.type,
89            results: req.canvas ? undefined : filter,
90            hover: CpuStruct.hoverCpuStruct
91        });
92    }
93
94    cpu(list: Array<any>, res: Array<any>, startNS: number, endNS: number, totalNS: number, frame: any,use:boolean) {
95        if(use && res.length > 0){
96            let pns = (endNS - startNS) / frame.width;
97            let y = frame.y + 5;
98            let height = frame.height - 10;
99            for (let i = 0, len = res.length; i < len; i++) {
100                let it = res[i];
101                if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS) {
102                    if (!res[i].frame) {
103                        res[i].frame = {};
104                        res[i].frame.y = y;
105                        res[i].frame.height = height;
106                    }
107                    CpuStruct.setCpuFrame(res[i], pns, startNS, endNS, frame)
108                }else{
109                    res[i].frame = null;
110                }
111            }
112            return;
113        }
114        res.length = 0;
115        if (list) {
116            let pns = (endNS - startNS) / frame.width;
117            let y = frame.y + 5;
118            let height = frame.height - 10;
119            for (let i = 0, len = list.length; i < len; i++) {
120                let it = list[i];
121                if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS) {
122                    if (!it.frame) {
123                        it.frame = {};
124                        it.frame.y = y;
125                        it.frame.height = height;
126                    }
127                    CpuStruct.setCpuFrame(it, pns, startNS, endNS, frame)
128                    if (i > 0 && ((list[i - 1].frame?.x || 0) == (it.frame?.x || 0) && ((list[i - 1].frame?.width || 0) == (it.frame?.width || 0)))) {
129
130                    } else {
131                        res.push(it)
132                    }
133                }else{
134                    it.frame = null;
135                }
136            }
137        }
138    }
139}
140
141
142let dec = new TextDecoder();
143function rtCpu(buf: ArrayBuffer | null | undefined, res: Array<any>, startNS: number, endNS: number, totalNS: number, frame: any) {
144    if (buf) {
145        res.length=0;
146        let pns = (endNS - startNS) / frame.width;
147        let y = frame.y + 5;
148        let height = frame.height - 10;
149        let str = dec.decode(buf);
150        str = str.substring(str.indexOf("\n") + 1);
151        let parse = JSON.parse(str);
152        let columns = parse.columns;
153        let values = parse.values;
154        for (let i = 0; i < values.length; i++) {
155            let obj: any = {}
156            for (let j = 0; j < columns.length; j++) {
157                obj[columns[j]] = values[i][j]
158            }
159            obj.frame = {
160                // x: obj.x1,
161                y: frame.y + 5,
162                // width: obj.x2 - obj.x1 > 0 ? obj.x2 - obj.x1 : 1,
163                height: frame.height - 10,
164            }
165            CpuStruct.setCpuFrame(obj, pns, startNS, endNS, frame)
166            res.push(obj);
167        }
168    }else{
169        let pns = (endNS - startNS) / frame.width;
170        res.forEach(it=>{
171            CpuStruct.setCpuFrame(it, pns, startNS, endNS, frame)
172        })
173    }
174}
175
176export class CpuStruct extends BaseStruct {
177    static cpuCount: number = 1 //最大cpu数量
178    static hoverCpuStruct: CpuStruct | undefined;
179    static selectCpuStruct: CpuStruct | undefined;
180    cpu: number | undefined
181    dur: number | undefined
182    end_state: string | undefined
183    id: number | undefined
184    name: string | undefined
185    priority: number | undefined
186    processCmdLine: string | undefined
187    processId: number | undefined
188    processName: string | undefined
189    schedId: number | undefined
190    startTime: number | undefined
191    tid: number | undefined
192    type: string | undefined
193
194    static draw(ctx: CanvasRenderingContext2D, data: CpuStruct) {
195        if (data.frame) {
196            let width = data.frame.width || 0;
197            if (data.tid === CpuStruct.hoverCpuStruct?.tid || !CpuStruct.hoverCpuStruct) {
198                ctx.globalAlpha = 1
199                ctx.fillStyle = ColorUtils.colorForTid((data.processId || 0) > 0 ? (data.processId || 0) : (data.tid || 0))
200            } else if(data.processId === CpuStruct.hoverCpuStruct?.processId ){
201                ctx.globalAlpha = 0.6
202                ctx.fillStyle = ColorUtils.colorForTid((data.processId || 0) > 0 ? (data.processId || 0) : (data.tid || 0))
203            } else {
204                ctx.globalAlpha = 1
205                ctx.fillStyle = "#e0e0e0"
206            }
207            ctx.fillRect(data.frame.x, data.frame.y, width, data.frame.height)
208            ctx.globalAlpha = 1
209            if (width > textPadding * 2) {
210                let process = `${(data.processName || "Process")} [${data.processId}]`
211                let thread = `${data.name || "Thread"} [${data.tid}] [Prio:${data.priority||0}]`
212                let processMeasure = ctx.measureText(process);
213                let threadMeasure = ctx.measureText(thread);
214                let processCharWidth = Math.round(processMeasure.width / process.length)
215                let threadCharWidth = Math.round(threadMeasure.width / thread.length)
216                ctx.fillStyle = "#ffffff"
217                let y = data.frame.height / 2 + data.frame.y;
218                if (processMeasure.width < width - textPadding * 2) {
219                    let x1 = Math.floor(width / 2 - processMeasure.width / 2 + data.frame.x + textPadding)
220                    ctx.textBaseline = "bottom";
221                    ctx.fillText(process, x1, y, width - textPadding * 2)
222                } else if (width - textPadding * 2 > processCharWidth * 4) {
223                    let chatNum = (width - textPadding * 2) / processCharWidth;
224                    let x1 = data.frame.x + textPadding
225                    ctx.textBaseline = "bottom";
226                    ctx.fillText(process.substring(0, chatNum - 4) + '...', x1, y, width - textPadding * 2)
227                }
228                ctx.fillStyle = "#ffffff"
229                ctx.font = "9px sans-serif";
230                if (threadMeasure.width < width - textPadding * 2) {
231                    ctx.textBaseline = "top";
232                    let x2 = Math.floor(width / 2 - threadMeasure.width / 2 + data.frame.x + textPadding)
233                    ctx.fillText(thread, x2, y + 2, width - textPadding * 2)
234                } else if (width - textPadding * 2 > threadCharWidth * 4) {
235                    let chatNum = (width - textPadding * 2) / threadCharWidth;
236                    let x1 = data.frame.x + textPadding
237                    ctx.textBaseline = "top";
238                    ctx.fillText(thread.substring(0, chatNum - 4) + '...', x1, y + 2, width - textPadding * 2)
239                }
240            }
241            if (CpuStruct.selectCpuStruct && CpuStruct.equals(CpuStruct.selectCpuStruct, data)) {
242                ctx.strokeStyle = '#232c5d'
243                ctx.lineWidth = 2
244                ctx.strokeRect(data.frame.x, data.frame.y, width - 2, data.frame.height)
245            }
246        }
247    }
248
249    static setCpuFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) {
250        if ((node.startTime || 0) < startNS) {
251            node.frame.x = 0;
252        } else {
253            node.frame.x = Math.floor(((node.startTime || 0) - startNS) / pns);
254        }
255        if ((node.startTime || 0) + (node.dur || 0) > endNS) {
256            node.frame.width = frame.width - node.frame.x;
257        } else {
258            node.frame.width = Math.ceil(((node.startTime || 0) + (node.dur || 0) - startNS) / pns - node.frame.x);
259        }
260        if (node.frame.width < 1) {
261            node.frame.width = 1;
262        }
263    }
264
265    static equals(d1: CpuStruct, d2: CpuStruct): boolean {
266        if (d1 && d2 && d1.cpu == d2.cpu &&
267            d1.tid == d2.tid &&
268            d1.processId == d2.processId &&
269            d1.startTime == d2.startTime &&
270            d1.dur == d2.dur) {
271            return true;
272        } else {
273            return false;
274        }
275    }
276}
277
278export class WakeupBean {
279    wakeupTime: number | undefined
280    cpu: number | undefined
281    process: string | undefined
282    pid: number | undefined
283    thread: string | undefined
284    tid: number | undefined
285    schedulingLatency: number | undefined
286    schedulingDesc: string | undefined
287
288}
289
290const textPadding = 2;