• 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 {BaseStruct, ns2x, Rect} from "./ProcedureWorkerCommon.js";
17
18export function thread(list: Array<any>, res: Array<any>, startNS: number, endNS: number, totalNS: number, frame: any,use:boolean) {
19    if(use && res.length > 0){
20        for (let i = 0; i < res.length; i++) {
21            let it = res[i];
22            if((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS){
23                ThreadStruct.setThreadFrame(it, 5, startNS, endNS, totalNS, frame)
24            }else{
25                it.frame = null;
26            }
27        }
28        return;
29    }
30    res.length = 0;
31    if (list) {
32        let groups = list.filter(it => (it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS).map(it => {
33            ThreadStruct.setThreadFrame(it, 5, startNS, endNS, totalNS, frame)
34            return it;
35        }).reduce((pre, current, index, arr) => {
36            (pre[`${current.frame.x}`] = pre[`${current.frame.x}`] || []).push(current);
37            return pre;
38        }, {});
39        Reflect.ownKeys(groups).map((kv => {
40            let arr = (groups[kv].sort((a: any, b: any) => b.frame.width - a.frame.width));
41            if (arr.length > 1) {
42                let idx = arr.findIndex((it: any) => it.state != "S")
43                if (idx != -1) {
44                    res.push(arr[idx]);
45                } else {
46                    res.push(arr[0]);
47                }
48            } else {
49                res.push(arr[0]);
50            }
51        }));
52    }
53}
54
55const padding = 3;
56
57export class ThreadStruct extends BaseStruct {
58    static runningColor: string = "#467b3b";
59    static rColor = "#a0b84d";
60    static otherColor = "#673ab7";
61    static uninterruptibleSleepColor = "#f19d38";
62    static traceColor = "#0d47a1";
63    static sColor = "#FBFBFB";
64    static hoverThreadStruct: ThreadStruct | undefined;
65    static selectThreadStruct: ThreadStruct | undefined;
66    static statusMap: any = {
67        "D": "Uninterruptible Sleep",
68        "S": "Sleeping",
69        "R": "Runnable",
70        "Running": "Running",
71        "R+": "Runnable (Preempted)",
72        "DK": "Uninterruptible Sleep + Wake Kill",
73        "I": "Task Dead",
74        "T": "Traced",
75        "t": "Traced",
76        "X": "Exit (Dead)",
77        "Z": "Exit (Zombie)",
78        "K": "Wake Kill",
79        "W": "Waking",
80        "P": "Parked",
81        "N": "No Load"
82    }
83    hasSched: number | undefined;// 14724852000
84    pid: number | undefined// 2519
85    processName: string | undefined //null
86    threadName: string | undefined//"ACCS0"
87    tid: number | undefined //2716
88    upid: number | undefined // 1
89    utid: number | undefined // 1
90    cpu: number | undefined // null
91    dur: number | undefined // 405000
92    end_ts: number | undefined // null
93    id: number | undefined // 1
94    is_main_thread: number | undefined // 0
95    name: string | undefined // "ACCS0"
96    startTime: number | undefined // 58000
97    start_ts: number | undefined // null
98    state: string | undefined // "S"
99    type: string | undefined // "thread"
100
101    static setThreadFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) {
102        let x1: number;
103        let x2: number;
104        if ((node.startTime || 0) < startNS) {
105            x1 = 0;
106        } else {
107            x1 = ns2x((node.startTime || 0), startNS, endNS, totalNS, frame);
108        }
109        if ((node.startTime || 0) + (node.dur || 0) > endNS) {
110            x2 = frame.width;
111        } else {
112            x2 = ns2x((node.startTime || 0) + (node.dur || 0), startNS, endNS, totalNS, frame);
113        }
114        let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1;
115        if (!node.frame) {
116            node.frame = {};
117        }
118        node.frame.x = Math.floor(x1);
119        node.frame.y = frame.y + padding;
120        node.frame.width = Math.ceil(getV);
121        node.frame.height = 30 - padding * 2;
122    }
123
124    static draw(ctx: CanvasRenderingContext2D, data: ThreadStruct) {
125        if (data.frame) {
126            ctx.globalAlpha = 1
127            let stateText = data.state || '';
128            if ("S" == data.state) {
129                ctx.fillStyle = ThreadStruct.sColor;
130                ctx.globalAlpha = 0.2; // transparency
131                ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2)
132                ctx.globalAlpha = 1; // transparency
133            } else if ("R" == data.state || "R+" == data.state) {
134                ctx.fillStyle = ThreadStruct.rColor;
135                ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2)
136                ctx.fillStyle = "#fff";
137                data.frame.width > 4 && ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame);
138            } else if ("D" == data.state) {
139                ctx.fillStyle = ThreadStruct.uninterruptibleSleepColor;
140                ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2)
141                ctx.fillStyle = "#fff";
142                data.frame.width > 4 && ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame);
143            } else if ("Running" == data.state) {
144                ctx.fillStyle = ThreadStruct.runningColor;
145                ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2)
146                ctx.fillStyle = "#fff";
147                data.frame.width > 4 && ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame);
148            } else if ("T" == data.state || "t" == data.state) {
149                ctx.fillStyle = ThreadStruct.traceColor;
150                ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2)
151                ctx.fillStyle = "#fff";
152                ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame);
153            } else {
154                ctx.fillStyle = ThreadStruct.otherColor;
155                ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2)
156                ctx.fillStyle = "#fff";
157                data.frame.width > 4 && ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame);
158            }
159            if (ThreadStruct.selectThreadStruct && ThreadStruct.equals(ThreadStruct.selectThreadStruct, data) && ThreadStruct.selectThreadStruct.state != "S") {
160                ctx.strokeStyle = '#232c5d'
161                ctx.lineWidth = 2
162                ctx.strokeRect(data.frame.x, data.frame.y + padding, data.frame.width - 2, data.frame.height - padding * 2)
163            }
164        }
165    }
166
167    static drawString(ctx: CanvasRenderingContext2D, str: string, textPadding: number, frame: Rect) {
168        let textMetrics = ctx.measureText(str);
169        let charWidth = Math.round(textMetrics.width / str.length)
170        if (textMetrics.width < frame.width - textPadding * 2) {
171            let x2 = Math.floor(frame.width / 2 - textMetrics.width / 2 + frame.x + textPadding)
172            ctx.textBaseline = "middle"
173            ctx.font = "8px sans-serif";
174            ctx.fillText(str, x2, Math.floor(frame.y + frame.height / 2), frame.width - textPadding * 2)
175            return;
176        }
177        if (frame.width - textPadding * 2 > charWidth * 4) {
178            let chatNum = (frame.width - textPadding * 2) / charWidth;
179            let x1 = frame.x + textPadding
180            ctx.textBaseline = "middle"
181            ctx.font = "8px sans-serif";
182            ctx.fillText(str.substring(0, chatNum - 4) + '...', x1, Math.floor(frame.y + frame.height / 2), frame.width - textPadding * 2)
183            return;
184        }
185    }
186
187    static getEndState(state: string): string {
188        let statusMapElement = ThreadStruct.statusMap[state];
189        if (statusMapElement) {
190            return statusMapElement
191        } else {
192            if ("" == statusMapElement || statusMapElement == null) {
193                return "";
194            }
195            return "Unknown State";
196        }
197    }
198
199    static equals(d1: ThreadStruct, d2: ThreadStruct): boolean {
200        if (d1 && d2 && d1.cpu == d2.cpu &&
201            d1.tid == d2.tid &&
202            d1.state == d2.state &&
203            d1.startTime == d2.startTime &&
204            d1.dur == d2.dur) {
205            return true;
206        } else {
207            return false;
208        }
209    }
210}