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 dataFilterHandler, 20 Render, 21 isFrameContainPoint, 22 ns2x, 23 drawLoadingFrame, 24 Rect, 25} from './ProcedureWorkerCommon'; 26import { TraceRow } from '../../component/trace/base/TraceRow'; 27 28export class MemoryAbilityRender extends Render { 29 renderMainThread( 30 req: { 31 context: CanvasRenderingContext2D; 32 useCache: boolean; 33 type: string; 34 maxMemoryByte: number; 35 maxMemoryByteName: string; 36 }, 37 memoryAbilityRow: TraceRow<MemoryAbilityMonitorStruct> 38 ): void { 39 let memoryAbilityList = memoryAbilityRow.dataList; 40 let memoryAbilityFilter = memoryAbilityRow.dataListCache; 41 dataFilterHandler(memoryAbilityList, memoryAbilityFilter, { 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: memoryAbilityRow.frame, 48 paddingTop: 5, 49 useCache: req.useCache || !(TraceRow.range?.refresh ?? false), 50 }); 51 drawLoadingFrame(req.context, memoryAbilityRow.dataListCache, memoryAbilityRow); 52 req.context.beginPath(); 53 let find = false; 54 for (let re of memoryAbilityFilter) { 55 MemoryAbilityMonitorStruct.draw(req.context, re, req.maxMemoryByte, memoryAbilityRow.isHover); 56 if ( 57 memoryAbilityRow.isHover && 58 re.frame && 59 isFrameContainPoint(re.frame, memoryAbilityRow.hoverX, memoryAbilityRow.hoverY) 60 ) { 61 MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = re; 62 find = true; 63 } 64 } 65 66 if (!find && memoryAbilityRow.isHover) { 67 MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = undefined; 68 } 69 req.context.closePath(); 70 let textMetrics = req.context.measureText(req.maxMemoryByteName); 71 req.context.globalAlpha = 0.8; 72 req.context.fillStyle = '#f0f0f0'; 73 req.context.fillRect(0, 5, textMetrics.width + 8, 18); 74 req.context.globalAlpha = 1; 75 req.context.fillStyle = '#333'; 76 req.context.textBaseline = 'middle'; 77 req.context.fillText(req.maxMemoryByteName, 4, 5 + 9); 78 } 79} 80 81export function memoryAbility( 82 memoryAbilityList: Array<MemoryAbilityMonitorStruct>, 83 res: Array<MemoryAbilityMonitorStruct>, 84 startNS: number, 85 endNS: number, 86 totalNS: number, 87 frame: Rect, 88 use: boolean 89): void { 90 if (use && res.length > 0) { 91 for (let i = 0; i < res.length; i++) { 92 let memoryAbilityItem = res[i] as MemoryAbilityMonitorStruct; 93 if ( 94 (memoryAbilityItem.startNS || 0) + (memoryAbilityItem.dur || 0) > startNS && 95 (memoryAbilityItem.startNS || 0) < endNS 96 ) { 97 MemoryAbilityMonitorStruct.setMemoryFrame(memoryAbilityItem, 5, startNS, endNS, totalNS, frame); 98 } else { 99 memoryAbilityItem.frame = undefined; 100 } 101 } 102 return; 103 } 104 res.length = 0; 105 setMemoryAbility(memoryAbilityList, res, startNS, endNS, totalNS, frame); 106} 107function setMemoryAbility( 108 list: Array<MemoryAbilityMonitorStruct>, 109 res: Array<MemoryAbilityMonitorStruct>, 110 startNS: number, 111 endNS: number, 112 totalNS: number, 113 frame: Rect 114): void { 115 if (list) { 116 for (let index = 0; index < list.length; index++) { 117 let item = list[index] as MemoryAbilityMonitorStruct; 118 item.dur = 119 index === list.length - 1 120 ? (endNS || 0) - (item.startNS || 0) 121 : // @ts-ignore 122 (list[index + 1].startNS || 0) - (item.startNS || 0); 123 if ((item.startNS || 0) + (item.dur || 0) > startNS && (item.startNS || 0) < endNS) { 124 MemoryAbilityMonitorStruct.setMemoryFrame(item, 5, startNS, endNS, totalNS, frame); 125 if ( 126 !( 127 index > 0 && 128 // @ts-ignore 129 (list[index - 1].frame.x || 0) === (item.frame.x || 0) && 130 // @ts-ignore 131 (list[index - 1].frame.width || 0) === (item.frame.width || 0) 132 ) 133 ) { 134 res.push(item); 135 } 136 } 137 } 138 } 139} 140 141export class MemoryAbilityMonitorStruct extends BaseStruct { 142 static maxMemoryByte: number = 0; 143 static maxMemoryByteName: string = '0 MB'; 144 static hoverMemoryAbilityStruct: MemoryAbilityMonitorStruct | undefined; 145 static selectMemoryAbilityStruct: MemoryAbilityMonitorStruct | undefined; 146 cpu: number | undefined; 147 value: number | undefined; 148 startNS: number | undefined; 149 dur: number | undefined; 150 151 static draw( 152 memoryAbilityContext2D: CanvasRenderingContext2D, 153 memoryAbilityData: MemoryAbilityMonitorStruct, 154 maxMemoryByte: number, 155 isHover: boolean 156 ): void { 157 if (memoryAbilityData.frame) { 158 let width = memoryAbilityData.frame.width || 0; 159 let index = 2; 160 memoryAbilityContext2D.fillStyle = ColorUtils.colorForTid(index); 161 memoryAbilityContext2D.strokeStyle = ColorUtils.colorForTid(index); 162 let drawHeight: number = Math.floor( 163 ((memoryAbilityData.value || 0) * (memoryAbilityData.frame.height || 0) * 1.0) / maxMemoryByte 164 ); 165 let y = memoryAbilityData.frame.y + memoryAbilityData.frame.height - drawHeight + 4; 166 if (memoryAbilityData.startNS === MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct?.startNS && isHover) { 167 memoryAbilityContext2D.lineWidth = 1; 168 memoryAbilityContext2D.globalAlpha = 0.6; 169 memoryAbilityContext2D.fillRect(memoryAbilityData.frame.x, y, width, drawHeight); 170 memoryAbilityContext2D.beginPath(); 171 memoryAbilityContext2D.arc(memoryAbilityData.frame.x, y, 3, 0, 2 * Math.PI, true); 172 memoryAbilityContext2D.fill(); 173 memoryAbilityContext2D.globalAlpha = 1.0; 174 memoryAbilityContext2D.stroke(); 175 memoryAbilityContext2D.beginPath(); 176 memoryAbilityContext2D.moveTo(memoryAbilityData.frame.x + 3, y); 177 memoryAbilityContext2D.lineWidth = 3; 178 memoryAbilityContext2D.lineTo(memoryAbilityData.frame.x + width, y); 179 memoryAbilityContext2D.stroke(); 180 } else { 181 memoryAbilityContext2D.globalAlpha = 0.6; 182 memoryAbilityContext2D.lineWidth = 1; 183 let drawHeight: number = Math.floor( 184 ((memoryAbilityData.value || 0) * (memoryAbilityData.frame.height || 0)) / maxMemoryByte 185 ); 186 memoryAbilityContext2D.fillRect(memoryAbilityData.frame.x, y, width, drawHeight); 187 } 188 } 189 memoryAbilityContext2D.globalAlpha = 1.0; 190 memoryAbilityContext2D.lineWidth = 1; 191 } 192 193 static setMemoryFrame( 194 memoryNode: MemoryAbilityMonitorStruct, 195 padding: number, 196 startNS: number, 197 endNS: number, 198 totalNS: number, 199 frame: Rect 200 ): void { 201 let memoryStartPointX: number; 202 let memoryEndPointX: number; 203 204 if ((memoryNode.startNS || 0) < startNS) { 205 memoryStartPointX = 0; 206 } else { 207 memoryStartPointX = ns2x(memoryNode.startNS || 0, startNS, endNS, totalNS, frame); 208 } 209 if ((memoryNode.startNS || 0) + (memoryNode.dur || 0) > endNS) { 210 memoryEndPointX = frame.width; 211 } else { 212 memoryEndPointX = ns2x((memoryNode.startNS || 0) + (memoryNode.dur || 0), startNS, endNS, totalNS, frame); 213 } 214 let frameWidth: number = memoryEndPointX - memoryStartPointX <= 1 ? 1 : memoryEndPointX - memoryStartPointX; 215 if (!memoryNode.frame) { 216 memoryNode.frame = new Rect(0, 0, 0, 0); 217 } 218 memoryNode.frame.x = Math.floor(memoryStartPointX); 219 memoryNode.frame.y = frame.y + padding; 220 memoryNode.frame.width = Math.ceil(frameWidth); 221 memoryNode.frame.height = Math.floor(frame.height - padding * 2); 222 } 223} 224 225const textPadding = 2; 226