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 { TraceRow } from '../../component/trace/base/TraceRow'; 18import { 19 BaseStruct, 20 isFrameContainPoint, 21 ns2x, 22 Render, 23 RequestMessage, 24 drawString, 25 drawLoadingFrame, 26 Rect, 27} from './ProcedureWorkerCommon'; 28import { SpSystemTrace } from '../../component/SpSystemTrace'; 29 30export class SoRender extends Render { 31 renderMainThread( 32 req: { 33 useCache: boolean; 34 context: CanvasRenderingContext2D; 35 type: string; 36 }, 37 row: TraceRow<SoStruct> 38 ): void { 39 let soList = row.dataList; 40 let soFilter = row.dataListCache; 41 soDataFilter( 42 soList, 43 soFilter, 44 TraceRow.range!.startNS, 45 TraceRow.range!.endNS, 46 TraceRow.range!.totalNS, 47 row.frame, 48 req.useCache || !TraceRow.range!.refresh 49 ); 50 51 drawLoadingFrame(req.context, row.dataListCache, row); 52 req.context.beginPath(); 53 let soFind = false; 54 for (let so of soFilter) { 55 SoStruct.draw(req.context, so); 56 if (row.isHover) { 57 if (so.dur === 0 || so.dur === null || so.dur === undefined) { 58 if ( 59 so.frame && 60 row.hoverX >= so.frame.x - 5 && 61 row.hoverX <= so.frame.x + 5 && 62 row.hoverY >= so.frame.y && 63 row.hoverY <= so.frame.y + so.frame.height 64 ) { 65 SoStruct.hoverSoStruct = so; 66 soFind = true; 67 } 68 } else { 69 if (so.frame && isFrameContainPoint(so.frame, row.hoverX, row.hoverY)) { 70 SoStruct.hoverSoStruct = so; 71 soFind = true; 72 } 73 } 74 } 75 } 76 if (!soFind && row.isHover) { 77 SoStruct.hoverSoStruct = undefined; 78 } 79 req.context.closePath(); 80 } 81 82 render(req: RequestMessage, list: Array<unknown>, filter: Array<unknown>): void {} 83} 84 85export function soDataFilter( 86 soList: Array<SoStruct>, 87 soFilter: Array<SoStruct>, 88 startNS: number, 89 endNS: number, 90 totalNS: number, 91 frame: Rect, 92 use: boolean 93): void { 94 if (use && soFilter.length > 0) { 95 for (let i = 0, len = soFilter.length; i < len; i++) { 96 if ((soFilter[i].startTs || 0) + (soFilter[i].dur || 0) >= startNS && (soFilter[i].startTs || 0) <= endNS) { 97 SoStruct.setSoFrame(soFilter[i], 0, startNS, endNS, totalNS, frame); 98 } else { 99 soFilter[i].frame = undefined; 100 } 101 } 102 return; 103 } 104 soFilter.length = 0; 105 if (soList) { 106 let groups = soList 107 .filter((it) => (it.startTs ?? 0) + (it.dur ?? 0) >= startNS && (it.startTs ?? 0) <= endNS) 108 .map((it) => { 109 SoStruct.setSoFrame(it, 0, startNS, endNS, totalNS, frame); 110 return it; 111 }) 112 .reduce((pre: unknown, current, index, arr) => { 113 if (current.frame) { 114 //@ts-ignore 115 (pre[`${current.frame.x}-${current.depth}`] = pre[`${current.frame.x}-${current.depth}`] || []).push(current); 116 } 117 return pre; 118 }, {}); 119 //@ts-ignore 120 Reflect.ownKeys(groups).map((kv) => { 121 //@ts-ignore 122 let arr = groups[kv].sort((a: unknown, b: unknown) => b.dur - a.dur); 123 soFilter.push(arr[0]); 124 }); 125 } 126} 127export function SoStructOnClick( 128 clickRowType: string, 129 sp: SpSystemTrace, 130 scrollToFuncHandler: Function, 131 entry?: SoStruct, 132): Promise<unknown> { 133 return new Promise((resolve, reject) => { 134 if (clickRowType === TraceRow.ROW_TYPE_STATIC_INIT && (SoStruct.hoverSoStruct || entry)) { 135 SoStruct.selectSoStruct = entry || SoStruct.hoverSoStruct; 136 sp.traceSheetEL?.displayStaticInitData(SoStruct.selectSoStruct!, scrollToFuncHandler); 137 sp.timerShaftEL?.modifyFlagList(undefined); 138 reject(new Error()); 139 } else { 140 resolve(null); 141 } 142 }); 143} 144export class SoStruct extends BaseStruct { 145 static hoverSoStruct: SoStruct | undefined; 146 static selectSoStruct: SoStruct | undefined; 147 textMetricsWidth: number | undefined; 148 depth: number | undefined; 149 dur: number | undefined; 150 soName: string | undefined; 151 process: string | undefined; 152 startTs: number | undefined; 153 tid: number | undefined; 154 pid: number | undefined; 155 itid: number | undefined; 156 id: number | undefined; 157 158 static setSoFrame( 159 soNode: SoStruct, 160 padding: number, 161 startNS: number, 162 endNS: number, 163 totalNS: number, 164 frame: Rect 165 ): void { 166 let x1: number; 167 let x2: number; 168 if ((soNode.startTs || 0) > startNS && (soNode.startTs || 0) < endNS) { 169 x1 = ns2x(soNode.startTs || 0, startNS, endNS, totalNS, frame); 170 } else { 171 x1 = 0; 172 } 173 if ((soNode.startTs || 0) + (soNode.dur || 0) > startNS && (soNode.startTs || 0) + (soNode.dur || 0) < endNS) { 174 x2 = ns2x((soNode.startTs || 0) + (soNode.dur || 0), startNS, endNS, totalNS, frame); 175 } else { 176 x2 = frame.width; 177 } 178 if (!soNode.frame) { 179 soNode.frame = new Rect(0, 0, 0, 0); 180 } 181 let getV: number = x2 - x1 < 1 ? 1 : x2 - x1; 182 soNode.frame.x = Math.floor(x1); 183 soNode.frame.y = soNode.depth! * 20; 184 soNode.frame.width = Math.ceil(getV); 185 soNode.frame.height = 20; 186 } 187 188 static draw(ctx: CanvasRenderingContext2D, data: SoStruct): void { 189 if (data.frame) { 190 if (data.dur === undefined || data.dur === null) { 191 } else { 192 ctx.globalAlpha = 1; 193 ctx.fillStyle = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.soName || '', 0, ColorUtils.FUNC_COLOR.length)]; 194 let textColor = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.soName || '', 0, ColorUtils.FUNC_COLOR.length)]; 195 let miniHeight = 20; 196 if (SoStruct.hoverSoStruct && data.soName === SoStruct.hoverSoStruct.soName) { 197 ctx.globalAlpha = 0.7; 198 } 199 ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2); 200 if (data.frame.width > 10) { 201 ctx.strokeStyle = '#fff'; 202 ctx.lineWidth = 1; 203 ctx.strokeRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2); 204 ctx.fillStyle = ColorUtils.funcTextColor(textColor); 205 drawString(ctx, `${data.soName || ''}`, 5, data.frame, data); 206 } 207 if (data === SoStruct.selectSoStruct) { 208 ctx.strokeStyle = '#000'; 209 ctx.lineWidth = 2; 210 ctx.strokeRect(data.frame.x, data.frame.y + 1, data.frame.width, miniHeight - padding * 2 - 2); 211 } 212 } 213 } 214 } 215} 216 217const padding = 1; 218