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