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 drawLines, 20 drawLoading, 21 drawSelection, 22 isFrameContainPoint, 23 ns2x, 24 Render, 25 drawFlagLine, 26 RequestMessage, 27 dataFilterHandler, 28} from './ProcedureWorkerCommon.js'; 29import { TraceRow } from '../../component/trace/base/TraceRow.js'; 30 31export class DiskIoAbilityRender extends Render { 32 renderMainThread( 33 req: { 34 context: CanvasRenderingContext2D; 35 useCache: boolean; 36 type: string; 37 maxDiskRate: number; 38 maxDiskRateName: string; 39 }, 40 diskIoAbilityRow: TraceRow<DiskAbilityMonitorStruct> 41 ): void { 42 let diskIoAbilityList = diskIoAbilityRow.dataList; 43 let diskIoFilter = diskIoAbilityRow.dataListCache; 44 dataFilterHandler(diskIoAbilityList, diskIoFilter, { 45 startKey: 'startNS', 46 durKey: 'dur', 47 startNS: TraceRow.range?.startNS ?? 0, 48 endNS: TraceRow.range?.endNS ?? 0, 49 totalNS: TraceRow.range?.totalNS ?? 0, 50 frame: diskIoAbilityRow.frame, 51 paddingTop: 5, 52 useCache: req.useCache || !(TraceRow.range?.refresh ?? false), 53 }); 54 req.context.beginPath(); 55 let find = false; 56 for (let re of diskIoFilter) { 57 DiskAbilityMonitorStruct.draw(req.context, re, req.maxDiskRate, diskIoAbilityRow.isHover); 58 if (diskIoAbilityRow.isHover && re.frame && 59 isFrameContainPoint(re.frame, diskIoAbilityRow.hoverX, diskIoAbilityRow.hoverY) 60 ) { 61 DiskAbilityMonitorStruct.hoverDiskAbilityStruct = re; 62 find = true; 63 } 64 } 65 if (!find && diskIoAbilityRow.isHover) { 66 DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined; 67 } 68 req.context.closePath(); 69 let textMetrics = req.context.measureText(req.maxDiskRateName); 70 req.context.globalAlpha = 0.8; 71 req.context.fillStyle = '#f0f0f0'; 72 req.context.fillRect(0, 5, textMetrics.width + 8, 18); 73 req.context.globalAlpha = 1; 74 req.context.fillStyle = '#333'; 75 req.context.textBaseline = 'middle'; 76 req.context.fillText(req.maxDiskRateName, 4, 5 + 9); 77 } 78 79 render(diskAbilityRequest: RequestMessage, diskIoAbilityList: Array<any>, filter: Array<any>) { 80 if (diskAbilityRequest.lazyRefresh) { 81 diskIoAbility( 82 diskIoAbilityList, 83 filter, 84 diskAbilityRequest.startNS, 85 diskAbilityRequest.endNS, 86 diskAbilityRequest.totalNS, 87 diskAbilityRequest.frame, 88 diskAbilityRequest.useCache || !diskAbilityRequest.range.refresh 89 ); 90 } else { 91 if (!diskAbilityRequest.useCache) { 92 diskIoAbility( 93 diskIoAbilityList, 94 filter, 95 diskAbilityRequest.startNS, 96 diskAbilityRequest.endNS, 97 diskAbilityRequest.totalNS, 98 diskAbilityRequest.frame, 99 false 100 ); 101 } 102 } 103 if (diskAbilityRequest.canvas) { 104 diskAbilityRequest.context.clearRect(0, 0, diskAbilityRequest.frame.width, diskAbilityRequest.frame.height); 105 let diskIoArr = filter; 106 if ( 107 diskIoArr.length > 0 && 108 !diskAbilityRequest.range.refresh && 109 !diskAbilityRequest.useCache && 110 diskAbilityRequest.lazyRefresh 111 ) { 112 drawLoading( 113 diskAbilityRequest.context, 114 diskAbilityRequest.startNS, 115 diskAbilityRequest.endNS, 116 diskAbilityRequest.totalNS, 117 diskAbilityRequest.frame, 118 diskIoArr[0].startNS, 119 diskIoArr[diskIoArr.length - 1].startNS + diskIoArr[diskIoArr.length - 1].dur 120 ); 121 } 122 diskAbilityRequest.context.beginPath(); 123 let maxDiskRate = diskAbilityRequest.params.maxDiskRate; 124 let maxDiskRateName = diskAbilityRequest.params.maxDiskRateName; 125 drawLines( 126 diskAbilityRequest.context, 127 diskAbilityRequest.xs, 128 diskAbilityRequest.frame.height, 129 diskAbilityRequest.lineColor 130 ); 131 DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined; 132 if (diskAbilityRequest.isHover) { 133 for (let re of filter) { 134 if ( 135 re.frame && 136 diskAbilityRequest.hoverX >= re.frame.x && 137 diskAbilityRequest.hoverX <= re.frame.x + re.frame.width && 138 diskAbilityRequest.hoverY >= re.frame.y && 139 diskAbilityRequest.hoverY <= re.frame.y + re.frame.height 140 ) { 141 DiskAbilityMonitorStruct.hoverDiskAbilityStruct = re; 142 break; 143 } 144 } 145 } 146 DiskAbilityMonitorStruct.selectDiskAbilityStruct = diskAbilityRequest.params.selectDiskAbilityStruct; 147 for (let re of filter) { 148 DiskAbilityMonitorStruct.draw(diskAbilityRequest.context, re, maxDiskRate, true); 149 } 150 drawSelection(diskAbilityRequest.context, diskAbilityRequest.params); 151 diskAbilityRequest.context.closePath(); 152 let textMetrics = diskAbilityRequest.context.measureText(maxDiskRateName); 153 diskAbilityRequest.context.globalAlpha = 0.8; 154 diskAbilityRequest.context.fillStyle = '#f0f0f0'; 155 diskAbilityRequest.context.fillRect(0, 5, textMetrics.width + 8, 18); 156 diskAbilityRequest.context.globalAlpha = 1; 157 diskAbilityRequest.context.fillStyle = '#333'; 158 diskAbilityRequest.context.textBaseline = 'middle'; 159 diskAbilityRequest.context.fillText(maxDiskRateName, 4, 5 + 9); 160 drawFlagLine( 161 diskAbilityRequest.context, 162 diskAbilityRequest.flagMoveInfo, 163 diskAbilityRequest.flagSelectedInfo, 164 diskAbilityRequest.startNS, 165 diskAbilityRequest.endNS, 166 diskAbilityRequest.totalNS, 167 diskAbilityRequest.frame, 168 diskAbilityRequest.slicesTime 169 ); 170 } 171 // @ts-ignore 172 self.postMessage({ 173 id: diskAbilityRequest.id, 174 type: diskAbilityRequest.type, 175 results: diskAbilityRequest.canvas ? undefined : filter, 176 hover: DiskAbilityMonitorStruct.hoverDiskAbilityStruct, 177 }); 178 } 179} 180 181export function diskIoAbility( 182 diskIoAbilityList: Array<any>, 183 res: Array<any>, 184 startNS: number, 185 endNS: number, 186 totalNS: number, 187 frame: any, 188 use: boolean 189) { 190 if (use && res.length > 0) { 191 for (let i = 0; i < res.length; i++) { 192 let diskIoAbilityItem = res[i]; 193 if ( 194 (diskIoAbilityItem.startNS || 0) + (diskIoAbilityItem.dur || 0) > (startNS || 0) && 195 (diskIoAbilityItem.startNS || 0) < (endNS || 0) 196 ) { 197 DiskAbilityMonitorStruct.setDiskIOFrame(diskIoAbilityItem, 5, startNS || 0, endNS || 0, totalNS || 0, frame); 198 } else { 199 diskIoAbilityItem.frame = null; 200 } 201 } 202 return; 203 } 204 res.length = 0; 205 if (diskIoAbilityList) { 206 for (let index = 0; index < diskIoAbilityList.length; index++) { 207 let item = diskIoAbilityList[index]; 208 if (index === diskIoAbilityList.length - 1) { 209 item.dur = (endNS || 0) - (item.startNS || 0); 210 } else { 211 item.dur = (diskIoAbilityList[index + 1].startNS || 0) - (item.startNS || 0); 212 } 213 if ((item.startNS || 0) + (item.dur || 0) > (startNS || 0) && (item.startNS || 0) < (endNS || 0)) { 214 DiskAbilityMonitorStruct.setDiskIOFrame( 215 diskIoAbilityList[index], 216 5, 217 startNS || 0, 218 endNS || 0, 219 totalNS || 0, 220 frame 221 ); 222 if ( 223 index > 0 && 224 (diskIoAbilityList[index - 1].frame?.x || 0) == (diskIoAbilityList[index].frame?.x || 0) && 225 (diskIoAbilityList[index - 1].frame?.width || 0) == (diskIoAbilityList[index].frame?.width || 0) 226 ) { 227 } else { 228 res.push(item); 229 } 230 } 231 } 232 } 233} 234 235export class DiskAbilityMonitorStruct extends BaseStruct { 236 static maxDiskRate: number = 0; 237 static maxDiskRateName: string = '0 KB/S'; 238 static hoverDiskAbilityStruct: DiskAbilityMonitorStruct | undefined; 239 static selectDiskAbilityStruct: DiskAbilityMonitorStruct | undefined; 240 value: number | undefined; 241 startNS: number | undefined; 242 dur: number | undefined; //自补充,数据库没有返回 243 244 static draw( 245 diskIoAbilityContext: CanvasRenderingContext2D, 246 diskIoAbilityData: DiskAbilityMonitorStruct, 247 maxDiskRate: number, 248 isHover: boolean 249 ) { 250 if (diskIoAbilityData.frame) { 251 let width = diskIoAbilityData.frame.width || 0; 252 let index = 2; 253 diskIoAbilityContext.fillStyle = ColorUtils.colorForTid(index); 254 diskIoAbilityContext.strokeStyle = ColorUtils.colorForTid(index); 255 if (diskIoAbilityData.startNS === DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.startNS && isHover) { 256 diskIoAbilityContext.lineWidth = 1; 257 diskIoAbilityContext.globalAlpha = 0.6; 258 let drawHeight: number = Math.floor(((diskIoAbilityData.value || 0) * (diskIoAbilityData.frame.height || 0) * 1.0) / maxDiskRate); 259 diskIoAbilityContext.fillRect( 260 diskIoAbilityData.frame.x, 261 diskIoAbilityData.frame.y + diskIoAbilityData.frame.height - drawHeight + 4, 262 width, 263 drawHeight 264 ); 265 diskIoAbilityContext.beginPath(); 266 diskIoAbilityContext.arc( 267 diskIoAbilityData.frame.x, 268 diskIoAbilityData.frame.y + diskIoAbilityData.frame.height - drawHeight + 4, 269 3, 270 0, 271 2 * Math.PI, 272 true 273 ); 274 diskIoAbilityContext.fill(); 275 diskIoAbilityContext.globalAlpha = 1.0; 276 diskIoAbilityContext.stroke(); 277 diskIoAbilityContext.beginPath(); 278 diskIoAbilityContext.moveTo(diskIoAbilityData.frame.x + 3, diskIoAbilityData.frame.y + diskIoAbilityData.frame.height - drawHeight + 4); 279 diskIoAbilityContext.lineWidth = 3; 280 diskIoAbilityContext.lineTo(diskIoAbilityData.frame.x + width, diskIoAbilityData.frame.y + diskIoAbilityData.frame.height - drawHeight + 4); 281 diskIoAbilityContext.stroke(); 282 } else { 283 diskIoAbilityContext.globalAlpha = 0.6; 284 diskIoAbilityContext.lineWidth = 1; 285 let drawHeight: number = Math.floor(((diskIoAbilityData.value || 0) * (diskIoAbilityData.frame.height || 0)) / maxDiskRate); 286 diskIoAbilityContext.fillRect( 287 diskIoAbilityData.frame.x, 288 diskIoAbilityData.frame.y + diskIoAbilityData.frame.height - drawHeight + 4, 289 width, 290 drawHeight 291 ); 292 } 293 } 294 diskIoAbilityContext.globalAlpha = 1.0; 295 diskIoAbilityContext.lineWidth = 1; 296 } 297 298 static setDiskIOFrame(diskIONode: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { 299 let diskIOStartPointX: number, diskIOEndPointX: number; 300 301 if ((diskIONode.startNS || 0) < startNS) { 302 diskIOStartPointX = 0; 303 } else { 304 diskIOStartPointX = ns2x(diskIONode.startNS || 0, startNS, endNS, totalNS, frame); 305 } 306 if ((diskIONode.startNS || 0) + (diskIONode.dur || 0) > endNS) { 307 diskIOEndPointX = frame.width; 308 } else { 309 diskIOEndPointX = ns2x((diskIONode.startNS || 0) + (diskIONode.dur || 0), startNS, endNS, totalNS, frame); 310 } 311 let frameWidth: number = diskIOEndPointX - diskIOStartPointX <= 1 ? 1 : diskIOEndPointX - diskIOStartPointX; 312 if (!diskIONode.frame) { 313 diskIONode.frame = {}; 314 } 315 diskIONode.frame.x = Math.floor(diskIOStartPointX); 316 diskIONode.frame.y = frame.y + padding; 317 diskIONode.frame.width = Math.ceil(frameWidth); 318 diskIONode.frame.height = Math.floor(frame.height - padding * 2); 319 } 320} 321