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'; 17import { 18 BaseStruct, 19 isFrameContainPoint, 20 ns2x, 21 Render, 22 dataFilterHandler, 23 drawLoadingFrame, 24 Rect, 25} from './ProcedureWorkerCommon'; 26import { TraceRow } from '../../component/trace/base/TraceRow'; 27 28export class DiskIoAbilityRender extends Render { 29 renderMainThread( 30 req: { 31 context: CanvasRenderingContext2D; 32 useCache: boolean; 33 type: string; 34 maxDiskRate: number; 35 maxDiskRateName: string; 36 }, 37 diskIoAbilityRow: TraceRow<DiskAbilityMonitorStruct> 38 ): void { 39 let diskIoAbilityList = diskIoAbilityRow.dataList; 40 let diskIoFilter = diskIoAbilityRow.dataListCache; 41 dataFilterHandler(diskIoAbilityList, diskIoFilter, { 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: diskIoAbilityRow.frame, 48 paddingTop: 5, 49 useCache: req.useCache || !(TraceRow.range?.refresh ?? false), 50 }); 51 drawLoadingFrame(req.context, diskIoAbilityRow.dataListCache, diskIoAbilityRow); 52 req.context.beginPath(); 53 let find = false; 54 for (let re of diskIoFilter) { 55 DiskAbilityMonitorStruct.draw(req.context, re, req.maxDiskRate, diskIoAbilityRow.isHover); 56 if ( 57 diskIoAbilityRow.isHover && 58 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 80export function diskIoAbility( 81 diskIoAbilityList: Array<DiskAbilityMonitorStruct>, 82 res: Array<DiskAbilityMonitorStruct>, 83 startNS: number, 84 endNS: number, 85 totalNS: number, 86 frame: Rect, 87 use: boolean 88): void { 89 if (use && res.length > 0) { 90 for (let i = 0; i < res.length; i++) { 91 let diskIoAbilityItem = res[i]; 92 if ( 93 (diskIoAbilityItem.startNS || 0) + (diskIoAbilityItem.dur || 0) > (startNS || 0) && 94 (diskIoAbilityItem.startNS || 0) < (endNS || 0) 95 ) { 96 DiskAbilityMonitorStruct.setDiskIOFrame(diskIoAbilityItem, 5, startNS || 0, endNS || 0, totalNS || 0, frame); 97 } else { 98 diskIoAbilityItem.frame = undefined; 99 } 100 } 101 return; 102 } 103 res.length = 0; 104 setDiskIoAbilityFilter(diskIoAbilityList, res, startNS || 0, endNS || 0, totalNS || 0, frame); 105} 106function setDiskIoAbilityFilter( 107 diskIoAbilityList: Array<DiskAbilityMonitorStruct>, 108 res: Array<DiskAbilityMonitorStruct>, 109 startNS: number, 110 endNS: number, 111 totalNS: number, 112 frame: Rect 113): void { 114 if (diskIoAbilityList) { 115 for (let index = 0; index < diskIoAbilityList.length; index++) { 116 let item = diskIoAbilityList[index]; 117 item.dur = 118 index === diskIoAbilityList.length - 1 119 ? endNS - (item.startNS || 0) 120 : (diskIoAbilityList[index + 1].startNS || 0) - (item.startNS || 0); 121 if ((item.startNS || 0) + (item.dur || 0) > startNS && (item.startNS || 0) < endNS) { 122 DiskAbilityMonitorStruct.setDiskIOFrame(diskIoAbilityList[index], 5, startNS, endNS, totalNS, frame); 123 if ( 124 !( 125 index > 0 && 126 (diskIoAbilityList[index - 1].frame!.x || 0) === (diskIoAbilityList[index].frame!.x || 0) && 127 (diskIoAbilityList[index - 1].frame!.width || 0) === (diskIoAbilityList[index].frame!.width || 0) 128 ) 129 ) { 130 res.push(item); 131 } 132 } 133 } 134 } 135} 136export class DiskAbilityMonitorStruct extends BaseStruct { 137 static maxDiskRate: number = 0; 138 static maxDiskRateName: string = '0 KB/S'; 139 static hoverDiskAbilityStruct: DiskAbilityMonitorStruct | undefined; 140 static selectDiskAbilityStruct: DiskAbilityMonitorStruct | undefined; 141 value: number | undefined; 142 startNS: number | undefined; 143 dur: number | undefined; //自补充,数据库没有返回 144 145 static draw( 146 diskIoAbilityContext: CanvasRenderingContext2D, 147 diskIoAbilityData: DiskAbilityMonitorStruct, 148 maxDiskRate: number, 149 isHover: boolean 150 ): void { 151 if (diskIoAbilityData.frame) { 152 let width = diskIoAbilityData.frame.width || 0; 153 let index = 2; 154 diskIoAbilityContext.fillStyle = ColorUtils.colorForTid(index); 155 diskIoAbilityContext.strokeStyle = ColorUtils.colorForTid(index); 156 if (diskIoAbilityData.startNS === DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.startNS && isHover) { 157 diskIoAbilityContext.lineWidth = 1; 158 diskIoAbilityContext.globalAlpha = 0.6; 159 let drawHeight: number = Math.floor( 160 ((diskIoAbilityData.value || 0) * (diskIoAbilityData.frame.height || 0) * 1.0) / maxDiskRate 161 ); 162 let y = diskIoAbilityData.frame.y + diskIoAbilityData.frame.height - drawHeight + 4; 163 diskIoAbilityContext.fillRect(diskIoAbilityData.frame.x, y, width, drawHeight); 164 diskIoAbilityContext.beginPath(); 165 diskIoAbilityContext.arc(diskIoAbilityData.frame.x, y, 3, 0, 2 * Math.PI, true); 166 diskIoAbilityContext.fill(); 167 diskIoAbilityContext.globalAlpha = 1.0; 168 diskIoAbilityContext.stroke(); 169 diskIoAbilityContext.beginPath(); 170 diskIoAbilityContext.moveTo(diskIoAbilityData.frame.x + 3, y); 171 diskIoAbilityContext.lineWidth = 3; 172 diskIoAbilityContext.lineTo(diskIoAbilityData.frame.x + width, y); 173 diskIoAbilityContext.stroke(); 174 } else { 175 diskIoAbilityContext.globalAlpha = 0.6; 176 diskIoAbilityContext.lineWidth = 1; 177 let drawHeight: number = Math.floor( 178 ((diskIoAbilityData.value || 0) * (diskIoAbilityData.frame.height || 0)) / maxDiskRate 179 ); 180 let y = diskIoAbilityData.frame.y + diskIoAbilityData.frame.height - drawHeight + 4; 181 diskIoAbilityContext.fillRect(diskIoAbilityData.frame.x, y, width, drawHeight); 182 } 183 } 184 diskIoAbilityContext.globalAlpha = 1.0; 185 diskIoAbilityContext.lineWidth = 1; 186 } 187 188 static setDiskIOFrame( 189 diskIONode: DiskAbilityMonitorStruct, 190 padding: number, 191 startNS: number, 192 endNS: number, 193 totalNS: number, 194 frame: Rect 195 ): void { 196 let diskIOStartPointX: number; 197 let diskIOEndPointX: number; 198 199 if ((diskIONode.startNS || 0) < startNS) { 200 diskIOStartPointX = 0; 201 } else { 202 diskIOStartPointX = ns2x(diskIONode.startNS || 0, startNS, endNS, totalNS, frame); 203 } 204 if ((diskIONode.startNS || 0) + (diskIONode.dur || 0) > endNS) { 205 diskIOEndPointX = frame.width; 206 } else { 207 diskIOEndPointX = ns2x((diskIONode.startNS || 0) + (diskIONode.dur || 0), startNS, endNS, totalNS, frame); 208 } 209 let frameWidth: number = diskIOEndPointX - diskIOStartPointX <= 1 ? 1 : diskIOEndPointX - diskIOStartPointX; 210 if (!diskIONode.frame) { 211 diskIONode.frame = new Rect(0, 0, 0, 0); 212 } 213 diskIONode.frame.x = Math.floor(diskIOStartPointX); 214 diskIONode.frame.y = frame.y + padding; 215 diskIONode.frame.width = Math.ceil(frameWidth); 216 diskIONode.frame.height = Math.floor(frame.height - padding * 2); 217 } 218} 219