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