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 { HiPerfStruct, PerfRender, Rect, type RequestMessage } from '../ProcedureWorkerCommon'; 18 19import { TraceRow } from '../../../component/trace/base/TraceRow'; 20 21export class HiperfReportRender extends PerfRender { 22 renderMainThread(hiPerfReportReq: unknown, row: TraceRow<HiPerfReportStruct>): void { 23 let list = row.dataList; 24 let filter = row.dataListCache; 25 //@ts-ignore 26 let groupBy10MS = hiPerfReportReq.scale > 30_000_000; 27 if (list && row.dataList2.length === 0) { 28 //@ts-ignore 29 row.dataList2 = HiPerfReportStruct.reportGroupBy10MS(list, hiPerfReportReq.intervalPerf); 30 } 31 HiPerfReport( 32 list, 33 row.dataList2, 34 //@ts-ignore 35 hiPerfReportReq.type!, 36 filter, 37 TraceRow.range?.startNS ?? 0, 38 TraceRow.range?.endNS ?? 0, 39 TraceRow.range?.totalNS ?? 0, 40 row.frame, 41 groupBy10MS, 42 //@ts-ignore 43 hiPerfReportReq.intervalPerf, 44 //@ts-ignore 45 hiPerfReportReq.useCache || (TraceRow.range?.refresh ?? false) 46 ); 47 drawHiperfReportRender(hiPerfReportReq, groupBy10MS, filter, row); 48 } 49 50 render( 51 hiPerfReportRequest: RequestMessage, 52 list: Array<unknown>, 53 filter: Array<unknown>, 54 dataList2: Array<unknown> 55 ): void {} 56} 57 58function drawHiperfReportRender( 59 hiPerfReportReq: unknown, 60 groupBy10MS: boolean, 61 filter: HiPerfReportStruct[], 62 row: TraceRow<HiPerfReportStruct> 63): void { 64 //@ts-ignore 65 const ctx = hiPerfReportReq.context as CanvasRenderingContext2D; 66 ctx.beginPath(); 67 ctx.fillStyle = ColorUtils.FUNC_COLOR[0]; 68 ctx.strokeStyle = ColorUtils.FUNC_COLOR[0]; 69 let normalPath = new Path2D(); 70 let specPath = new Path2D(); 71 let offset = groupBy10MS ? 0 : 3; 72 let find = false; 73 for (let re of filter) { 74 HiPerfReportStruct.draw(ctx, normalPath, specPath, re, groupBy10MS); 75 if (row.isHover) { 76 if (re.frame && row.hoverX >= re.frame.x - offset && row.hoverX <= re.frame.x + re.frame.width + offset) { 77 HiPerfReportStruct.hoverStruct = re; 78 find = true; 79 } 80 } 81 } 82 if (!find && row.isHover) { 83 HiPerfReportStruct.hoverStruct = undefined; 84 } 85 if (groupBy10MS) { 86 ctx.fill(normalPath); 87 } else { 88 ctx.stroke(normalPath); 89 HiPerfStruct.drawSpecialPath(ctx, specPath); 90 } 91 ctx.closePath(); 92} 93 94function setFrameByfilter(startNS: number, endNS: number, frame: Rect, hiPerfFilters: Array<HiPerfReportStruct>): void { 95 let pns = (endNS - startNS) / frame.width; 96 let y = frame.y; 97 for (let i = 0; i < hiPerfFilters.length; i++) { 98 let hiPerfData = hiPerfFilters[i]; 99 if ((hiPerfData.startNS || 0) + (hiPerfData.dur || 0) > startNS && (hiPerfData.startNS || 0) < endNS) { 100 if (!hiPerfData.frame) { 101 hiPerfData.frame = new Rect(0, 0, 0, 0); 102 hiPerfData.frame.y = y; 103 } 104 hiPerfData.frame.height = hiPerfData.height!; 105 HiPerfReportStruct.setFrame(hiPerfData, pns, startNS, endNS, frame); 106 } else { 107 hiPerfData.frame = undefined; 108 } 109 } 110} 111 112function setFrameByArr( 113 groupBy10MS: boolean, 114 arr2: unknown, 115 arr: Array<HiPerfReportStruct>, 116 hiPerfFilters: Array<HiPerfReportStruct>, 117 startNS: number, 118 endNS: number, 119 frame: Rect 120): void { 121 //@ts-ignore 122 let list: Array<HiPerfReportStruct> = groupBy10MS ? arr2 : arr; 123 let pns = (endNS - startNS) / frame.width; 124 let y = frame.y; 125 list 126 127 .filter((it) => (it.startNS || 0) + (it.dur || 0) > startNS && (it.startNS || 0) < endNS) 128 .map((it) => { 129 if (!it.frame) { 130 it.frame = new Rect(0, 0, 0, 0); 131 it.frame.y = y; 132 } 133 it.frame.height = it.height!; 134 HiPerfReportStruct.setFrame(it, pns, startNS, endNS, frame); 135 return it; 136 }) 137 .reduce((pre, current, index, arr) => { 138 //@ts-ignore 139 if (!pre[`${current.frame.x}`]) { 140 //@ts-ignore 141 pre[`${current.frame.x}`] = []; 142 //@ts-ignore 143 pre[`${current.frame.x}`].push(current); 144 if (groupBy10MS) { 145 hiPerfFilters.push(current); 146 } else { 147 if (hiPerfFilters.length === 0) { 148 hiPerfFilters.push(current); 149 } 150 if ( 151 hiPerfFilters[hiPerfFilters.length - 1] && 152 Math.abs(current.frame!.x - hiPerfFilters[hiPerfFilters.length - 1].frame!.x) > 4 153 ) { 154 hiPerfFilters.push(current); 155 } 156 } 157 } 158 return pre; 159 }, {}); 160} 161 162export function HiPerfReport( 163 arr: Array<HiPerfReportStruct>, 164 arr2: unknown, 165 type: string, 166 hiPerfFilters: Array<HiPerfReportStruct>, 167 startNS: number, 168 endNS: number, 169 totalNS: number, 170 frame: Rect, 171 groupBy10MS: boolean, 172 intervalPerf: number, 173 use: boolean 174): void { 175 if (use && hiPerfFilters.length > 0) { 176 //@ts-ignore 177 setFrameByfilter(endNS, startNS, frame, hiPerfFilters); 178 return; 179 } 180 hiPerfFilters.length = 0; 181 if (arr) { 182 setFrameByArr(groupBy10MS, arr2, arr, hiPerfFilters, startNS, endNS, frame); 183 } 184} 185 186export class HiPerfReportStruct extends HiPerfStruct { 187 static hoverStruct: HiPerfReportStruct | undefined; 188 static selectStruct: HiPerfReportStruct | undefined; 189 190 static reportGroupBy10MS(array: Array<unknown>, intervalPerf: number): Array<unknown> { 191 let obj = array 192 .map((it) => { 193 //@ts-ignore 194 it.timestamp_group = Math.trunc(it.startNS / 1_000_000_0) * 1_000_000_0; 195 return it; 196 }) 197 .reduce((pre, current) => { 198 //@ts-ignore 199 (pre[current.timestamp_group] = pre[current.timestamp_group] || []).push(current); 200 return pre; 201 }, {}); 202 let reportArr: unknown[] = []; 203 let max = 0; 204 //@ts-ignore 205 for (let aKey in obj) { 206 //@ts-ignore 207 let sum = obj[aKey].reduce((pre: unknown, cur: unknown) => { 208 //@ts-ignore 209 return pre + cur.event_count; 210 }, 0); 211 if (sum > max) { 212 max = sum; 213 } 214 let ns = parseInt(aKey); 215 reportArr.push({ 216 startNS: ns, 217 dur: 1_000_000_0, 218 height: 0, 219 sum: sum, 220 }); 221 } 222 reportArr.map((it) => { 223 //@ts-ignore 224 it.height = Math.floor((40 * it.sum) / max); 225 return it; 226 }); 227 return reportArr; 228 } 229} 230