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 drawFlagLine, 20 drawLines, 21 drawLoading, 22 drawSelection, 23 drawWakeUp, 24 ns2x, 25 Render, 26 RequestMessage, 27} from './ProcedureWorkerCommon.js'; 28import { CpuStruct } from './ProcedureWorkerCPU.js'; 29import { TraceRow } from '../../component/trace/base/TraceRow.js'; 30 31export class ProcessRender extends Render { 32 renderMainThread(req: any, row: TraceRow<ProcessStruct>) { 33 let list = row.dataList; 34 let filter = row.dataListCache; 35 proc( 36 list, 37 filter, 38 TraceRow.range!.startNS, 39 TraceRow.range!.endNS, 40 TraceRow.range!.totalNS, 41 row.frame, 42 req.useCache || !TraceRow.range!.refresh 43 ); 44 req.context.beginPath(); 45 let path = new Path2D(); 46 let miniHeight: number = 0; 47 miniHeight = Math.round((row.frame.height - CpuStruct.cpuCount * 2) / CpuStruct.cpuCount); 48 req.context.fillStyle = ColorUtils.colorForTid(req.pid || 0); 49 for (let re of filter) { 50 ProcessStruct.draw(req.context, path, re, miniHeight); 51 } 52 req.context.fill(path); 53 req.context.closePath(); 54 } 55 56 render(processReq: RequestMessage, list: Array<any>, filter: Array<any>) { 57 if (processReq.lazyRefresh) { 58 proc( 59 list, 60 filter, 61 processReq.startNS, 62 processReq.endNS, 63 processReq.totalNS, 64 processReq.frame, 65 processReq.useCache || !processReq.range.refresh 66 ); 67 } else { 68 if (!processReq.useCache) { 69 proc(list, filter, processReq.startNS, processReq.endNS, processReq.totalNS, processReq.frame, false); 70 } 71 } 72 if (processReq.canvas) { 73 processReq.context.clearRect(0, 0, processReq.frame.width, processReq.frame.height); 74 let arr = filter; 75 if (arr.length > 0 && !processReq.range.refresh && !processReq.useCache && processReq.lazyRefresh) { 76 drawLoading( 77 processReq.context, 78 processReq.startNS, 79 processReq.endNS, 80 processReq.totalNS, 81 processReq.frame, 82 arr[0].startTime, 83 arr[arr.length - 1].startTime + arr[arr.length - 1].dur 84 ); 85 } 86 processReq.context.beginPath(); 87 CpuStruct.cpuCount = processReq.params.cpuCount; 88 drawLines(processReq.context, processReq.xs, processReq.frame.height, processReq.lineColor); 89 let path = new Path2D(); 90 let miniHeight: number = 0; 91 miniHeight = Math.round((processReq.frame.height - CpuStruct.cpuCount * 2) / CpuStruct.cpuCount); 92 processReq.context.fillStyle = ColorUtils.colorForTid(processReq.params.pid || 0); 93 for (let re of filter) { 94 ProcessStruct.draw(processReq.context, path, re, miniHeight); 95 } 96 processReq.context.fill(path); 97 drawSelection(processReq.context, processReq.params); 98 processReq.context.closePath(); 99 drawFlagLine( 100 processReq.context, 101 processReq.flagMoveInfo, 102 processReq.flagSelectedInfo, 103 processReq.startNS, 104 processReq.endNS, 105 processReq.totalNS, 106 processReq.frame, 107 processReq.slicesTime 108 ); 109 } 110 // @ts-ignore 111 self.postMessage({ 112 id: processReq.id, 113 type: processReq.type, 114 results: processReq.canvas ? undefined : filter, 115 hover: undefined, 116 }); 117 } 118} 119export function proc( 120 processList: Array<any>, 121 res: Array<any>, 122 startNS: number, 123 endNS: number, 124 totalNS: number, 125 frame: any, 126 use: boolean 127) { 128 if (use && res.length > 0) { 129 res.forEach((it) => ProcessStruct.setProcessFrame(it, 5, startNS || 0, endNS || 0, totalNS || 0, frame)); 130 return; 131 } 132 res.length = 0; 133 if (processList) { 134 for (let i = 0, len = processList.length; i < len; i++) { 135 let it = processList[i]; 136 if ((it.startTime || 0) + (it.dur || 0) > (startNS || 0) && (it.startTime || 0) < (endNS || 0)) { 137 ProcessStruct.setProcessFrame(processList[i], 5, startNS || 0, endNS || 0, totalNS || 0, frame); 138 if ( 139 i > 0 && 140 (processList[i - 1].frame?.x || 0) == (processList[i].frame?.x || 0) && 141 (processList[i - 1].frame?.width || 0) == (processList[i].frame?.width || 0) 142 ) { 143 } else { 144 res.push(processList[i]); 145 } 146 } 147 } 148 } 149} 150 151const padding = 1; 152 153export class ProcessStruct extends BaseStruct { 154 cpu: number | undefined; 155 dur: number | undefined; 156 id: number | undefined; 157 pid: number | undefined; 158 process: string | undefined; 159 startTime: number | undefined; 160 state: string | undefined; 161 thread: string | undefined; 162 tid: number | undefined; 163 ts: number | undefined; 164 type: string | undefined; 165 utid: number | undefined; 166 167 static draw(ctx: CanvasRenderingContext2D, path: Path2D, data: ProcessStruct, miniHeight: number) { 168 if (data.frame) { 169 path.rect(data.frame.x, data.frame.y + (data.cpu || 0) * miniHeight + padding, data.frame.width, miniHeight); 170 } 171 } 172 173 static setFrame(processNode: any, pns: number, startNS: number, endNS: number, frame: any) { 174 if ((processNode.startTime || 0) < startNS) { 175 processNode.frame.x = 0; 176 } else { 177 processNode.frame.x = Math.floor(((processNode.startTime || 0) - startNS) / pns); 178 } 179 if ((processNode.startTime || 0) + (processNode.dur || 0) > endNS) { 180 processNode.frame.width = frame.width - processNode.frame.x; 181 } else { 182 processNode.frame.width = Math.ceil( 183 ((processNode.startTime || 0) + (processNode.dur || 0) - startNS) / pns - processNode.frame.x 184 ); 185 } 186 if (processNode.frame.width < 1) { 187 processNode.frame.width = 1; 188 } 189 } 190 191 static setProcessFrame( 192 processNode: any, 193 padding: number, 194 startNS: number, 195 endNS: number, 196 totalNS: number, 197 frame: any 198 ) { 199 let x1: number; 200 let x2: number; 201 if ((processNode.startTime || 0) < startNS) { 202 x1 = 0; 203 } else { 204 x1 = ns2x(processNode.startTime || 0, startNS, endNS, totalNS, frame); 205 } 206 if ((processNode.startTime || 0) + (processNode.dur || 0) > endNS) { 207 x2 = frame.width; 208 } else { 209 x2 = ns2x((processNode.startTime || 0) + (processNode.dur || 0), startNS, endNS, totalNS, frame); 210 } 211 let processGetV: number = x2 - x1 <= 1 ? 1 : x2 - x1; 212 if (!processNode.frame) { 213 processNode.frame = {}; 214 } 215 processNode.frame.x = Math.floor(x1); 216 processNode.frame.y = Math.floor(frame.y + 2); 217 processNode.frame.width = Math.ceil(processGetV); 218 processNode.frame.height = Math.floor(frame.height - padding * 2); 219 } 220} 221