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 dataFilterHandler, 20 isFrameContainPoint, 21 ns2x, 22 RequestMessage, 23 Render, 24} from './ProcedureWorkerCommon.js'; 25import { TraceRow } from '../../component/trace/base/TraceRow.js'; 26import { DiskAbilityMonitorStruct } from './ProcedureWorkerDiskIoAbility.js'; 27 28export class CpuAbilityRender extends Render { 29 renderMainThread( 30 req: { 31 context: CanvasRenderingContext2D; 32 useCache: boolean; 33 type: string; 34 maxCpuUtilization: number; 35 maxCpuUtilizationName: string; 36 }, 37 row: TraceRow<CpuAbilityMonitorStruct> 38 ) { 39 let cpuAbilityList = row.dataList; 40 let cpuAbilityFilter = row.dataListCache; 41 dataFilterHandler(cpuAbilityList, cpuAbilityFilter, { 42 startKey: 'startNS', 43 durKey: 'dur', 44 startNS: TraceRow.range?.startNS ?? 0, 45 endNS: TraceRow.range?.endNS ?? 0, 46 totalNS: TraceRow.range?.totalNS ?? 0, 47 frame: row.frame, 48 paddingTop: 5, 49 useCache: req.useCache || !(TraceRow.range?.refresh ?? false), 50 }); 51 req.context.beginPath(); 52 let find = false; 53 for (let re of cpuAbilityFilter) { 54 CpuAbilityMonitorStruct.draw(req.context, re, req.maxCpuUtilization, row.isHover); 55 if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { 56 CpuAbilityMonitorStruct.hoverCpuAbilityStruct = re; 57 find = true; 58 } 59 } 60 if (!find && row.isHover) CpuAbilityMonitorStruct.hoverCpuAbilityStruct = undefined; 61 req.context.closePath(); 62 let textMetrics = req.context.measureText(req.maxCpuUtilizationName); 63 req.context.globalAlpha = 0.8; 64 req.context.fillStyle = '#f0f0f0'; 65 req.context.fillRect(0, 5, textMetrics.width + 8, 18); 66 req.context.globalAlpha = 1; 67 req.context.fillStyle = '#333'; 68 req.context.textBaseline = 'middle'; 69 req.context.fillText(req.maxCpuUtilizationName, 4, 5 + 9); 70 } 71 72 render(req: RequestMessage, list: Array<any>, filter: Array<any>) {} 73} 74 75export function cpuAbility( 76 cpuAbilityList: Array<any>, 77 res: Array<any>, 78 startNS: number, 79 endNS: number, 80 totalNS: number, 81 frame: any, 82 use: boolean 83) { 84 if (use && res.length > 0) { 85 for (let index = 0; index < res.length; index++) { 86 let item = res[index]; 87 if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { 88 CpuAbilityMonitorStruct.setCpuAbilityFrame(res[index], 5, startNS || 0, endNS || 0, totalNS || 0, frame); 89 } else { 90 res[index].frame = null; 91 } 92 } 93 return; 94 } 95 res.length = 0; 96 if (cpuAbilityList) { 97 for (let cpuAbilityIndex = 0; cpuAbilityIndex < cpuAbilityList.length; cpuAbilityIndex++) { 98 let item = cpuAbilityList[cpuAbilityIndex]; 99 if (cpuAbilityIndex === cpuAbilityList.length - 1) { 100 item.dur = (endNS || 0) - (item.startNS || 0); 101 } else { 102 item.dur = (cpuAbilityList[cpuAbilityIndex + 1].startNS || 0) - (item.startNS || 0); 103 } 104 if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { 105 CpuAbilityMonitorStruct.setCpuAbilityFrame( 106 cpuAbilityList[cpuAbilityIndex], 107 5, 108 startNS || 0, 109 endNS || 0, 110 totalNS || 0, 111 frame 112 ); 113 if ( 114 cpuAbilityIndex > 0 && 115 (cpuAbilityList[cpuAbilityIndex - 1].frame?.x || 0) == (cpuAbilityList[cpuAbilityIndex].frame?.x || 0) && 116 (cpuAbilityList[cpuAbilityIndex - 1].frame?.width || 0) == (cpuAbilityList[cpuAbilityIndex].frame?.width || 0) 117 ) { 118 } else { 119 res.push(item); 120 } 121 } 122 } 123 } 124} 125 126export class CpuAbilityMonitorStruct extends BaseStruct { 127 static maxCpuUtilization: number = 0; 128 static maxCpuUtilizationName: string = '0 %'; 129 static hoverCpuAbilityStruct: CpuAbilityMonitorStruct | undefined; 130 static selectCpuAbilityStruct: CpuAbilityMonitorStruct | undefined; 131 132 type: number | undefined; 133 value: number | undefined; 134 startNS: number | undefined; 135 dur: number | undefined; //自补充,数据库没有返回 136 137 static draw( 138 cpuAbilityContext2D: CanvasRenderingContext2D, 139 data: CpuAbilityMonitorStruct, 140 maxCpuUtilization: number, 141 isHover: boolean 142 ) { 143 if (data.frame) { 144 let width = data.frame.width || 0; 145 let index = 2; 146 cpuAbilityContext2D.fillStyle = ColorUtils.colorForTid(index); 147 cpuAbilityContext2D.strokeStyle = ColorUtils.colorForTid(index); 148 if (data.startNS === CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.startNS && isHover) { 149 cpuAbilityContext2D.lineWidth = 1; 150 cpuAbilityContext2D.globalAlpha = 0.6; 151 let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / maxCpuUtilization); 152 cpuAbilityContext2D.fillRect( 153 data.frame.x, 154 data.frame.y + data.frame.height - drawHeight + 4, 155 width, 156 drawHeight 157 ); 158 cpuAbilityContext2D.beginPath(); 159 cpuAbilityContext2D.arc( 160 data.frame.x, 161 data.frame.y + data.frame.height - drawHeight + 4, 162 3, 163 0, 164 2 * Math.PI, 165 true 166 ); 167 cpuAbilityContext2D.fill(); 168 cpuAbilityContext2D.globalAlpha = 1.0; 169 cpuAbilityContext2D.stroke(); 170 cpuAbilityContext2D.beginPath(); 171 cpuAbilityContext2D.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight + 4); 172 cpuAbilityContext2D.lineWidth = 3; 173 cpuAbilityContext2D.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight + 4); 174 cpuAbilityContext2D.stroke(); 175 } else { 176 cpuAbilityContext2D.globalAlpha = 0.6; 177 cpuAbilityContext2D.lineWidth = 1; 178 let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / maxCpuUtilization); 179 cpuAbilityContext2D.fillRect( 180 data.frame.x, 181 data.frame.y + data.frame.height - drawHeight + 4, 182 width, 183 drawHeight 184 ); 185 } 186 } 187 cpuAbilityContext2D.globalAlpha = 1.0; 188 cpuAbilityContext2D.lineWidth = 1; 189 } 190 191 static setCpuAbilityFrame( 192 cpuAbilityNode: any, 193 padding: number, 194 startNS: number, 195 endNS: number, 196 totalNS: number, 197 frame: any 198 ) { 199 let cpuAbilityStartPointX: number, cpuAbilityEndPointX: number; 200 201 if ((cpuAbilityNode.startNS || 0) < startNS) { 202 cpuAbilityStartPointX = 0; 203 } else { 204 cpuAbilityStartPointX = ns2x(cpuAbilityNode.startNS || 0, startNS, endNS, totalNS, frame); 205 } 206 if ((cpuAbilityNode.startNS || 0) + (cpuAbilityNode.dur || 0) > endNS) { 207 cpuAbilityEndPointX = frame.width; 208 } else { 209 cpuAbilityEndPointX = ns2x( 210 (cpuAbilityNode.startNS || 0) + (cpuAbilityNode.dur || 0), 211 startNS, 212 endNS, 213 totalNS, 214 frame 215 ); 216 } 217 let frameWidth: number = 218 cpuAbilityEndPointX - cpuAbilityStartPointX <= 1 ? 1 : cpuAbilityEndPointX - cpuAbilityStartPointX; 219 if (!cpuAbilityNode.frame) { 220 cpuAbilityNode.frame = {}; 221 } 222 cpuAbilityNode.frame.x = Math.floor(cpuAbilityStartPointX); 223 cpuAbilityNode.frame.y = frame.y + padding; 224 cpuAbilityNode.frame.width = Math.ceil(frameWidth); 225 cpuAbilityNode.frame.height = Math.floor(frame.height - padding * 2); 226 } 227} 228 229export class CpuAbility { 230 context: any; 231 params: any; 232} 233