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, ColorUtils} from "./ProcedureWorkerCommon.js"; 17 18let dec = new TextDecoder(); 19export function rtCpu(buf: ArrayBuffer | null | undefined, res: Array<any>, startNS: number, endNS: number, totalNS: number, frame: any) { 20 if (buf) { 21 res.length=0; 22 let pns = (endNS - startNS) / frame.width; 23 let y = frame.y + 5; 24 let height = frame.height - 10; 25 26 let str = dec.decode(buf); 27 str = str.substring(str.indexOf("\n") + 1); 28 let parse = JSON.parse(str); 29 let columns = parse.columns; 30 let values = parse.values; 31 for (let i = 0; i < values.length; i++) { 32 let obj: any = {} 33 for (let j = 0; j < columns.length; j++) { 34 obj[columns[j]] = values[i][j] 35 } 36 obj.frame = { 37 // x: obj.x1, 38 y: frame.y + 5, 39 // width: obj.x2 - obj.x1 > 0 ? obj.x2 - obj.x1 : 1, 40 height: frame.height - 10, 41 } 42 CpuStruct.setCpuFrame(obj, pns, startNS, endNS, frame) 43 res.push(obj); 44 } 45 }else{ 46 let pns = (endNS - startNS) / frame.width; 47 res.forEach(it=>{ 48 CpuStruct.setCpuFrame(it, pns, startNS, endNS, frame) 49 }) 50 } 51} 52 53export function cpu(list: Array<any>, res: Array<any>, startNS: number, endNS: number, totalNS: number, frame: any,use:boolean) { 54 if(use && res.length > 0){ 55 let pns = (endNS - startNS) / frame.width; 56 let y = frame.y + 5; 57 let height = frame.height - 10; 58 for (let i = 0, len = res.length; i < len; i++) { 59 let it = res[i]; 60 if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS) { 61 if (!res[i].frame) { 62 res[i].frame = {}; 63 res[i].frame.y = y; 64 res[i].frame.height = height; 65 } 66 CpuStruct.setCpuFrame(res[i], pns, startNS, endNS, frame) 67 }else{ 68 res[i].frame = null; 69 } 70 } 71 return; 72 } 73 res.length = 0; 74 if (list) { 75 let pns = (endNS - startNS) / frame.width; 76 let y = frame.y + 5; 77 let height = frame.height - 10; 78 for (let i = 0, len = list.length; i < len; i++) { 79 let it = list[i]; 80 if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS) { 81 if (!list[i].frame) { 82 list[i].frame = {}; 83 list[i].frame.y = y; 84 list[i].frame.height = height; 85 } 86 CpuStruct.setCpuFrame(list[i], pns, startNS, endNS, frame) 87 if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && ((list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0)))) { 88 89 } else { 90 res.push(list[i]) 91 } 92 }else{ 93 it.frame = null; 94 } 95 } 96 } 97} 98 99export class CpuStruct extends BaseStruct { 100 static cpuCount: number = 1 //最大cpu数量 101 static hoverCpuStruct: CpuStruct | undefined; 102 static selectCpuStruct: CpuStruct | undefined; 103 cpu: number | undefined 104 dur: number | undefined 105 end_state: string | undefined 106 id: number | undefined 107 name: string | undefined 108 priority: number | undefined 109 processCmdLine: string | undefined 110 processId: number | undefined 111 processName: string | undefined 112 schedId: number | undefined 113 startTime: number | undefined 114 tid: number | undefined 115 type: string | undefined 116 117 static draw(ctx: CanvasRenderingContext2D, data: CpuStruct) { 118 if (data.frame) { 119 let width = data.frame.width || 0; 120 if (data.processId === CpuStruct.hoverCpuStruct?.processId || !CpuStruct.hoverCpuStruct) { 121 ctx.fillStyle = ColorUtils.colorForTid((data.processId || 0) > 0 ? (data.processId || 0) : (data.tid || 0)) 122 } else { 123 ctx.fillStyle = "#e0e0e0" 124 } 125 ctx.fillRect(data.frame.x, data.frame.y, width, data.frame.height) 126 if (width > textPadding * 2) { 127 let process = `${(data.processName || "Process")} [${data.processId}]` 128 let thread = `${data.name || "Thread"} [${data.tid}]` 129 let processMeasure = ctx.measureText(process); 130 let threadMeasure = ctx.measureText(thread); 131 let processCharWidth = Math.round(processMeasure.width / process.length) 132 let threadCharWidth = Math.round(threadMeasure.width / thread.length) 133 ctx.fillStyle = "#ffffff" 134 let y = data.frame.height / 2 + data.frame.y; 135 if (processMeasure.width < width - textPadding * 2) { 136 let x1 = Math.floor(width / 2 - processMeasure.width / 2 + data.frame.x + textPadding) 137 ctx.textBaseline = "bottom"; 138 ctx.fillText(process, x1, y, width - textPadding * 2) 139 } else if (width - textPadding * 2 > processCharWidth * 4) { 140 let chatNum = (width - textPadding * 2) / processCharWidth; 141 let x1 = data.frame.x + textPadding 142 ctx.textBaseline = "bottom"; 143 ctx.fillText(process.substring(0, chatNum - 4) + '...', x1, y, width - textPadding * 2) 144 } 145 ctx.fillStyle = "#ffffff" 146 ctx.font = "9px sans-serif"; 147 if (threadMeasure.width < width - textPadding * 2) { 148 ctx.textBaseline = "top"; 149 let x2 = Math.floor(width / 2 - threadMeasure.width / 2 + data.frame.x + textPadding) 150 ctx.fillText(thread, x2, y + 2, width - textPadding * 2) 151 } else if (width - textPadding * 2 > threadCharWidth * 4) { 152 let chatNum = (width - textPadding * 2) / threadCharWidth; 153 let x1 = data.frame.x + textPadding 154 ctx.textBaseline = "top"; 155 ctx.fillText(thread.substring(0, chatNum - 4) + '...', x1, y + 2, width - textPadding * 2) 156 } 157 } 158 if (CpuStruct.selectCpuStruct && CpuStruct.equals(CpuStruct.selectCpuStruct, data)) { 159 ctx.strokeStyle = '#232c5d' 160 ctx.lineWidth = 2 161 ctx.strokeRect(data.frame.x, data.frame.y, width - 2, data.frame.height) 162 } 163 } 164 } 165 166 static setCpuFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { 167 if ((node.startTime || 0) < startNS) { 168 node.frame.x = 0; 169 } else { 170 node.frame.x = Math.floor(((node.startTime || 0) - startNS) / pns); 171 } 172 if ((node.startTime || 0) + (node.dur || 0) > endNS) { 173 node.frame.width = frame.width - node.frame.x; 174 } else { 175 node.frame.width = Math.ceil(((node.startTime || 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 equals(d1: CpuStruct, d2: CpuStruct): boolean { 183 if (d1 && d2 && d1.cpu == d2.cpu && 184 d1.tid == d2.tid && 185 d1.processId == d2.processId && 186 d1.startTime == d2.startTime && 187 d1.dur == d2.dur) { 188 return true; 189 } else { 190 return false; 191 } 192 } 193} 194 195export class WakeupBean { 196 wakeupTime: number | undefined 197 cpu: number | undefined 198 process: string | undefined 199 pid: number | undefined 200 thread: string | undefined 201 tid: number | undefined 202 schedulingLatency: number | undefined 203 schedulingDesc: string | undefined 204 205} 206 207const textPadding = 2;