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 { 17 BaseStruct, 18 dataFilterHandler, 19 drawFlagLine, 20 drawLines, 21 drawLoading, 22 drawLoadingFrame, 23 drawSelection, 24 drawWakeUp, 25 ns2x, 26 PerfRender, 27 Render, 28 RequestMessage, 29} from '../ProcedureWorkerCommon'; 30import { TraceRow } from '../../../component/trace/base/TraceRow'; 31import { ColorUtils } from '../../../component/trace/base/ColorUtils'; 32import { convertJSON } from '../../logic-worker/ProcedureLogicWorkerCommon'; 33import {SpSystemTrace} from "../../../component/SpSystemTrace"; 34 35export class CpuStateRender extends PerfRender { 36 renderMainThread( 37 req: { 38 useCache: boolean; 39 cpuStateContext: CanvasRenderingContext2D; 40 type: string; 41 cpu: number; 42 }, 43 cpuStateRow: TraceRow<CpuStateStruct> 44 ): void { 45 let list = cpuStateRow.dataList; 46 let filter = cpuStateRow.dataListCache; 47 dataFilterHandler(list, filter, { 48 startKey: 'startTs', 49 durKey: 'dur', 50 startNS: TraceRow.range?.startNS ?? 0, 51 endNS: TraceRow.range?.endNS ?? 0, 52 totalNS: TraceRow.range?.totalNS ?? 0, 53 frame: cpuStateRow.frame, 54 paddingTop: 5, 55 useCache: req.useCache || !(TraceRow.range?.refresh ?? false), 56 }); 57 drawLoadingFrame(req.cpuStateContext, filter, cpuStateRow); 58 let path = new Path2D(); 59 let find = false; 60 let offset = 3; 61 let heights = [4, 12, 21, 30]; 62 for (let re of filter) { 63 re.height = heights[(re as any).value]; 64 CpuStateStruct.draw(req.cpuStateContext, path, re); 65 if (cpuStateRow.isHover) { 66 if ( 67 re.frame && 68 cpuStateRow.hoverX >= re.frame.x - offset && 69 cpuStateRow.hoverX <= re.frame.x + re.frame.width + offset 70 ) { 71 CpuStateStruct.hoverStateStruct = re; 72 find = true; 73 } 74 } 75 } 76 if (!find && cpuStateRow.isHover) { 77 CpuStateStruct.hoverStateStruct = undefined; 78 } 79 req.cpuStateContext.fill(path); 80 } 81 82 render(cpuStateReq: RequestMessage, list: Array<any>, filter: Array<any>, dataList2: Array<any>) {} 83 84 setFrameByArr(cpuStateRes: any[], startNS: number, endNS: number, totalNS: number, frame: any, arr2: any[]) { 85 let list: any[] = arr2; 86 cpuStateRes.length = 0; 87 let pns = (endNS - startNS) / frame.width; 88 let y = frame.y + 5; 89 let frameHeight = frame.height - 10; 90 let left = 0, 91 right = 0; 92 for (let i = 0, j = list.length - 1, ib = true, jb = true; i < list.length, j >= 0; i++, j--) { 93 if (list[j].startTs <= endNS && jb) { 94 right = j; 95 jb = false; 96 } 97 if (list[i].startTs + list[i].dur >= startNS && ib) { 98 left = i; 99 ib = false; 100 } 101 if (!ib && !jb) { 102 break; 103 } 104 } 105 let slice = list.slice(left, right + 1); 106 let sum = 0; 107 for (let i = 0; i < slice.length; i++) { 108 if (!slice[i].frame) { 109 slice[i].frame = {}; 110 slice[i].frame.y = y; 111 slice[i].frame.height = frameHeight; 112 } 113 if (slice[i].dur >= pns) { 114 slice[i].v = true; 115 CpuStateStruct.setFrame(slice[i], 5, startNS, endNS, totalNS, frame); 116 } else { 117 if (i > 0) { 118 let c = slice[i].startTs - slice[i - 1].startTs - slice[i - 1].dur; 119 if (c < pns && sum < pns) { 120 sum += c + slice[i - 1].dur; 121 slice[i].v = false; 122 } else { 123 slice[i].v = true; 124 CpuStateStruct.setFrame(slice[i], 5, startNS, endNS, totalNS, frame); 125 sum = 0; 126 } 127 } 128 } 129 } 130 cpuStateRes.push(...slice.filter((it) => it.v)); 131 } 132 133 setFrameByFilter(cpuStateRes: any[], startNS: number, endNS: number, totalNS: number, frame: any) { 134 for (let i = 0, len = cpuStateRes.length; i < len; i++) { 135 if ( 136 (cpuStateRes[i].startTs || 0) + (cpuStateRes[i].dur || 0) >= startNS && 137 (cpuStateRes[i].startTs || 0) <= endNS 138 ) { 139 CpuStateStruct.setFrame(cpuStateRes[i], 5, startNS, endNS, totalNS, frame); 140 } else { 141 cpuStateRes[i].frame = null; 142 } 143 } 144 } 145 146 cpuState( 147 arr: any[], 148 arr2: any[], 149 type: string, 150 cpuStateRes: any[], 151 cpu: number, 152 startNS: number, 153 endNS: number, 154 totalNS: number, 155 frame: any, 156 use: boolean 157 ) { 158 if (use && cpuStateRes.length > 0) { 159 this.setFrameByFilter(cpuStateRes, startNS, endNS, totalNS, frame); 160 return; 161 } 162 cpuStateRes.length = 0; 163 if (arr) { 164 this.setFrameByArr(cpuStateRes, startNS, endNS, totalNS, frame, arr2); 165 } 166 } 167} 168export function CpuStateStructOnClick(clickRowType: string, sp: SpSystemTrace) { 169 return new Promise((resolve, reject) => { 170 if (clickRowType === TraceRow.ROW_TYPE_CPU_STATE && CpuStateStruct.hoverStateStruct) { 171 CpuStateStruct.selectStateStruct = CpuStateStruct.hoverStateStruct; 172 sp.traceSheetEL?.displayCpuStateData(); 173 sp.timerShaftEL?.modifyFlagList(undefined); 174 reject(); 175 }else{ 176 resolve(null); 177 } 178 }); 179} 180export class CpuStateStruct extends BaseStruct { 181 static hoverStateStruct: CpuStateStruct | undefined; 182 static selectStateStruct: CpuStateStruct | undefined; 183 dur: number | undefined; 184 value: string | undefined; 185 startTs: number | undefined; 186 height: number | undefined; 187 cpu: number | undefined; 188 189 static draw(ctx: CanvasRenderingContext2D, path: Path2D, data: CpuStateStruct) { 190 if (data.frame) { 191 let chartColor = ColorUtils.colorForTid(data.cpu!); 192 ctx.font = '11px sans-serif'; 193 ctx.fillStyle = chartColor; 194 ctx.strokeStyle = chartColor; 195 ctx.globalAlpha = 0.6; 196 if (data === CpuStateStruct.hoverStateStruct || data === CpuStateStruct.selectStateStruct) { 197 path.rect(data.frame.x, 35 - (data.height || 0), data.frame.width, data.height || 0); 198 ctx.lineWidth = 1; 199 ctx.globalAlpha = 1.0; 200 ctx.beginPath(); 201 ctx.arc(data.frame.x, 35 - (data.height || 0), 3, 0, 2 * Math.PI, true); 202 ctx.stroke(); 203 ctx.beginPath(); 204 ctx.moveTo(data.frame.x + 3, 35 - (data.height || 0)); 205 ctx.lineWidth = 3; 206 ctx.lineTo(data.frame.x + data.frame.width, 35 - (data.height || 0)); 207 ctx.stroke(); 208 ctx.lineWidth = 1; 209 ctx.globalAlpha = 0.6; 210 ctx.fillRect(data.frame.x, 35 - (data.height || 0), data.frame.width, data.height || 0); 211 } else { 212 ctx.globalAlpha = 0.6; 213 ctx.fillRect(data.frame.x, 35 - (data.height || 0), data.frame.width, data.height || 0); 214 } 215 } 216 } 217 218 static setCpuFrame(cpuStateNode: any, pns: number, startNS: number, endNS: number, frame: any) { 219 if ((cpuStateNode.startTime || 0) < startNS) { 220 cpuStateNode.frame.x = 0; 221 } else { 222 cpuStateNode.frame.x = Math.floor(((cpuStateNode.startTs || 0) - startNS) / pns); 223 } 224 if ((cpuStateNode.startTime || 0) + (cpuStateNode.dur || 0) > endNS) { 225 cpuStateNode.frame.width = frame.width - cpuStateNode.frame.x; 226 } else { 227 cpuStateNode.frame.width = Math.ceil( 228 ((cpuStateNode.startTs || 0) + (cpuStateNode.dur || 0) - startNS) / pns - cpuStateNode.frame.x 229 ); 230 } 231 if (cpuStateNode.frame.width < 1) { 232 cpuStateNode.frame.width = 1; 233 } 234 } 235 static setFrame(cpuStateNode: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { 236 let x1: number, x2: number; 237 if ((cpuStateNode.startTs || 0) < startNS) { 238 x1 = 0; 239 } else { 240 x1 = ns2x(cpuStateNode.startTs || 0, startNS, endNS, totalNS, frame); 241 } 242 if ((cpuStateNode.startTs || 0) + (cpuStateNode.dur || 0) > endNS) { 243 x2 = frame.width; 244 } else { 245 x2 = ns2x((cpuStateNode.startTs || 0) + (cpuStateNode.dur || 0), startNS, endNS, totalNS, frame); 246 } 247 let cpuStateGetV: number = x2 - x1 <= 1 ? 1 : x2 - x1; 248 if (!cpuStateNode.frame) { 249 cpuStateNode.frame = {}; 250 } 251 cpuStateNode.frame.x = Math.ceil(x1); 252 cpuStateNode.frame.y = frame.y + padding; 253 cpuStateNode.frame.width = Math.floor(cpuStateGetV); 254 cpuStateNode.frame.height = cpuStateNode.height; 255 } 256} 257