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 {SpSystemTrace} from "../SpSystemTrace.js"; 17import {TraceRow} from "../trace/base/TraceRow.js"; 18import {CounterStruct, SdkSliceStruct} from "../../bean/SdkStruct.js"; 19import {procedurePool} from "../../database/Procedure.js"; 20import {BaseStruct} from "../../bean/BaseStruct.js"; 21import { 22 queryCounterMax, 23 querySdkCount, 24 querySdkCounterData, 25 querySdkSliceData, 26 queryStartTime, 27} from "../../database/SqlLite.js"; 28 29export class SpSdkChart { 30 private trace: SpSystemTrace; 31 32 constructor(trace: SpSystemTrace) { 33 this.trace = trace; 34 } 35 36 parseJson(startTime: number, map: Map<number, string>) { 37 let tablesMap = new Map(); 38 let keys = map.keys(); 39 for (let key of keys) { 40 let table = [] 41 let configStr = map.get(key); 42 if (configStr != undefined) { 43 let json = JSON.parse(configStr); 44 let tableConfig = json.tableConfig 45 let setting = json.settingConfig 46 if (tableConfig != null) { 47 let showTypes = tableConfig.showType; 48 for (let i = 0; i < showTypes.length; i++) { 49 let showType = showTypes[i]; 50 let type = this.getTableType(showType); 51 if (type == "counter") { 52 let chartSql = this.createSql(startTime, showType.tableName, showType.columns, "where counter_id" + 53 " = $counter_id"); 54 let maxValue = this.createMaxValueSql(showType.tableName, "where counter_id = $counter_id"); 55 let innerTable = showType.inner; 56 let countSql = this.createSql(startTime, innerTable.tableName, innerTable.columns); 57 table.push({ 58 countSql: countSql, 59 chartSql: chartSql, 60 maxSql: maxValue, 61 type: "counter", 62 name: setting.name 63 }) 64 } else if (type == "slice") { 65 let chartSql = this.createSliceSql(startTime, showType.tableName, showType.columns, "where" + 66 " slice_id = $column_id and (start_ts - " + startTime + ") between $startNS and $endNS;"); 67 let innerTable = showType.inner; 68 let countSql = this.createSql(startTime, innerTable.tableName, innerTable.columns); 69 table.push({countSql: countSql, chartSql: chartSql, type: "slice", name: setting.name}) 70 } 71 } 72 tablesMap.set(key, table); 73 } 74 } 75 } 76 return tablesMap; 77 } 78 79 private getTableType(showType: any) { 80 let columns = showType.columns; 81 for (let i = 0; i < columns.length; i++) { 82 let column = columns[i]; 83 let showType = column.showType 84 if (showType != null) { 85 if (showType.indexOf(1) != -1) { 86 return "counter" 87 } 88 if (showType.indexOf(2) != -1) { 89 return "slice" 90 } 91 } 92 } 93 return "" 94 } 95 96 private createSliceSql(startTime: number, tableName: string, columns: Array<any>, where?: string): string { 97 let selectSql = "select " 98 for (let i = 0; i < columns.length; i++) { 99 let column = columns[i]; 100 if (column.column == "start_ts") { 101 column.column = "(start_ts - " + startTime + ") AS start_ts" 102 } 103 if (column.column == "end_ts") { 104 column.column = "(end_ts - " + startTime + ") AS end_ts" 105 } 106 if (i == (columns.length - 1)) { 107 selectSql = selectSql + column.column + " " 108 } else { 109 selectSql = selectSql + column.column + ", " 110 } 111 } 112 selectSql = selectSql + "from " + tableName 113 if (where != undefined) { 114 selectSql = selectSql + " " + where 115 } 116 return selectSql; 117 } 118 119 private createMaxValueSql(tableName: string, where?: string): string { 120 let selectSql = "select max(value) as max_value from " + tableName 121 if (where != undefined) { 122 selectSql = selectSql + " " + where 123 } 124 return selectSql; 125 } 126 127 private createSql(startTime: number, tableName: string, columns: Array<any>, where?: string): string { 128 let selectSql = "select " 129 for (let i = 0; i < columns.length; i++) { 130 let column = columns[i]; 131 if (column.column == "ts") { 132 column.column = "ts - " + startTime + " AS ts" 133 } 134 if (i == (columns.length - 1)) { 135 selectSql = selectSql + column.column + " " 136 } else { 137 selectSql = selectSql + column.column + ", " 138 } 139 } 140 selectSql = selectSql + "from " + tableName 141 if (where != undefined) { 142 selectSql = selectSql + " " + where 143 } 144 return selectSql; 145 } 146 147 async init() { 148 let configMap = SpSystemTrace.SDK_CONFIG_MAP 149 if (configMap == undefined) return; 150 let res = await queryStartTime(); 151 let startTime = res[0].start_ts; 152 let tablesMap = this.parseJson(startTime, configMap) 153 let tableKeys = tablesMap.keys(); 154 for (let componentId of tableKeys) { 155 let table = tablesMap.get(componentId); 156 if (table != null) { 157 let nodeRow = this.initNodeRow(componentId, table[0].name); 158 for (let index = 0; index < table.length; index++) { 159 let sqlMap = table[index] 160 if (sqlMap.type == "counter") { 161 let result = await querySdkCount(sqlMap.countSql, componentId); 162 for (let i = 0; i < result.length; i++) { 163 await this.initCounter(nodeRow, i, result[i], sqlMap, componentId); 164 } 165 } else if (sqlMap.type == "slice") { 166 let result = await querySdkCount(sqlMap.countSql, componentId); 167 for (let i = 0; i < result.length; i++) { 168 await this.initSlice(nodeRow, i, result[i], sqlMap, componentId); 169 } 170 } 171 } 172 } 173 } 174 } 175 176 private initNodeRow = (index: number, name: string) => { 177 let traceRow = new TraceRow<BaseStruct>({ 178 canvasNumber: 1, 179 alpha: false, 180 contextId: '2d', 181 isOffScreen: SpSystemTrace.isCanvasOffScreen 182 }); 183 traceRow.rowId = `Sdk-${index}` 184 traceRow.rowParentId = ''; 185 traceRow.folder = true; 186 traceRow.name = `Sdk ${name}`; 187 traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 188 traceRow.selectChangeHandler = this.trace.selectChangeHandler; 189 traceRow.supplier = () => new Promise<Array<any>>((resolve) => resolve([])); 190 traceRow.onThreadHandler = (useCache) => { 191 procedurePool.submitWithName(`process0`, `nodeGroup`, { 192 list: traceRow.must ? traceRow.dataList : undefined, 193 offscreen: traceRow.must ? traceRow.offscreen[0] : undefined, 194 xs: TraceRow.range?.xs, 195 dpr: traceRow.dpr, 196 isHover: traceRow.isHover, 197 hoverX: traceRow.hoverX, 198 hoverY: traceRow.hoverY, 199 flagMoveInfo: this.trace.hoverFlag, 200 flagSelectedInfo: this.trace.selectFlag, 201 canvasWidth: traceRow.canvasWidth, 202 canvasHeight: traceRow.canvasHeight, 203 isRangeSelect: traceRow.rangeSelect, 204 rangeSelectObject: TraceRow.rangeSelectObject, 205 useCache: useCache, 206 lineColor: traceRow.getLineColor(), 207 startNS: TraceRow.range?.startNS || 0, 208 endNS: TraceRow.range?.endNS || 0, 209 totalNS: TraceRow.range?.totalNS || 0, 210 slicesTime: TraceRow.range?.slicesTime, 211 range: TraceRow.range, 212 frame: traceRow.frame, 213 }, traceRow.must && traceRow.args.isOffScreen ? traceRow.offscreen[0] : undefined, (res: any, hover: any) => { 214 traceRow.must = false; 215 } 216 ) 217 } 218 this.trace.rowsEL?.appendChild(traceRow) 219 return traceRow; 220 } 221 222 private initCounter = async (nodeRow: TraceRow<BaseStruct>, index: number, result: any, sqlMap: any, componentId: number) => { 223 let traceRow = new TraceRow<CounterStruct>({ 224 canvasNumber: 1, 225 alpha: false, 226 contextId: '2d', 227 isOffScreen: SpSystemTrace.isCanvasOffScreen 228 }); 229 traceRow.rowParentId = `Sdk-${componentId}` 230 traceRow.rowHidden = !nodeRow.expansion 231 traceRow.rowId = result.counter_id + "-" + componentId 232 traceRow.rowType = TraceRow.ROW_TYPE_SDK_COUNTER 233 traceRow.folderPaddingLeft = 30; 234 traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 235 traceRow.selectChangeHandler = this.trace.selectChangeHandler; 236 traceRow.style.height = '40px' 237 traceRow.style.width = `100%`; 238 traceRow.setAttribute('children', ''); 239 traceRow.name = `${result.counter_name}`; 240 traceRow.supplier = () => querySdkCounterData(sqlMap.chartSql, result.counter_id, componentId) 241 let maxList = await queryCounterMax(sqlMap.maxSql, result.counter_id, componentId); 242 let maxCounter = maxList[0].max_value; 243 traceRow.onThreadHandler = (useCache) => { 244 procedurePool.submitWithName(`process${index % 8}`, `sdkCounter${index}`, { 245 list: traceRow.must ? traceRow.dataList : undefined, 246 offscreen: traceRow.must ? traceRow.offscreen[0] : undefined, 247 xs: TraceRow.range?.xs, 248 dpr: traceRow.dpr, 249 isHover: traceRow.isHover, 250 hoverX: traceRow.hoverX, 251 hoverY: traceRow.hoverY, 252 flagMoveInfo: this.trace.hoverFlag, 253 flagSelectedInfo: this.trace.selectFlag, 254 canvasWidth: traceRow.canvasWidth, 255 canvasHeight: traceRow.canvasHeight, 256 hoverCounterStruct: CounterStruct.hoverCounterStruct, 257 selectCounterStruct: CounterStruct.selectCounterStruct, 258 isRangeSelect: traceRow.rangeSelect, 259 rangeSelectObject: TraceRow.rangeSelectObject, 260 maxCounter: maxCounter + "", 261 maxCounterName: maxCounter + "", 262 useCache: useCache, 263 lineColor: traceRow.getLineColor(), 264 startNS: TraceRow.range?.startNS || 0, 265 endNS: TraceRow.range?.endNS || 0, 266 totalNS: TraceRow.range?.totalNS || 0, 267 slicesTime: TraceRow.range?.slicesTime, 268 range: TraceRow.range, 269 frame: traceRow.frame, 270 }, traceRow.must && traceRow.args.isOffScreen ? traceRow.offscreen[0] : undefined, (res: any, hover: any) => { 271 traceRow.must = false; 272 if (traceRow.args.isOffScreen == true) { 273 if (traceRow.isHover) { 274 CounterStruct.hoverCounterStruct = hover; 275 this.trace.visibleRows.filter(it => it.rowType === TraceRow.ROW_TYPE_SDK_COUNTER && it.name !== traceRow.name).forEach(it => it.draw(true)); 276 } 277 return; 278 } 279 } 280 ) 281 } 282 this.trace.rowsEL?.appendChild(traceRow) 283 } 284 285 private initSlice = async (nodeRow: TraceRow<BaseStruct>, index: number, result: any, sqlMap: any, componentId: number) => { 286 let traceRow = new TraceRow<SdkSliceStruct>({ 287 canvasNumber: 1, 288 alpha: false, 289 contextId: '2d', 290 isOffScreen: SpSystemTrace.isCanvasOffScreen 291 }); 292 traceRow.rowType = TraceRow.ROW_TYPE_SDK_SLICE 293 traceRow.rowHidden = !nodeRow.expansion 294 traceRow.rowParentId = `Sdk-${componentId}` 295 traceRow.folderPaddingLeft = 30; 296 traceRow.style.height = '40px' 297 traceRow.style.width = `100%`; 298 traceRow.name = `${result.slice_name}` 299 traceRow.setAttribute('children', ''); 300 traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 301 traceRow.selectChangeHandler = this.trace.selectChangeHandler; 302 traceRow.rowId = result.slice_id + "-" + componentId 303 traceRow.supplier = () => querySdkSliceData(sqlMap.chartSql, result.slice_id, TraceRow.range?.startNS || 0, TraceRow.range?.endNS || 0, componentId) 304 traceRow.onThreadHandler = ((useCache: boolean, buf: ArrayBuffer | undefined | null) => { 305 procedurePool.submitWithName(`process${index % 8}`, `sdkSlice${index}`, { 306 list: traceRow.must ? traceRow.dataList : undefined, 307 offscreen: !traceRow.isTransferCanvas ? traceRow.offscreen[0] : undefined,//是否离屏 308 dpr: traceRow.dpr,//屏幕dpr值 309 xs: TraceRow.range?.xs,//线条坐标信息 310 isHover: traceRow.isHover, 311 flagMoveInfo: this.trace.hoverFlag, 312 flagSelectedInfo: this.trace.selectFlag, 313 hoverX: traceRow.hoverX, 314 hoverY: traceRow.hoverY, 315 canvasWidth: traceRow.canvasWidth, 316 canvasHeight: traceRow.canvasHeight, 317 hoverSdkSliceStruct: SdkSliceStruct.hoverSdkSliceStruct, 318 selectSdkSliceStruct: SdkSliceStruct.selectSdkSliceStruct, 319 isRangeSelect: traceRow.rangeSelect, 320 rangeSelectObject: TraceRow.rangeSelectObject, 321 useCache: useCache, 322 lineColor: traceRow.getLineColor(), 323 startNS: TraceRow.range?.startNS || 0, 324 endNS: TraceRow.range?.endNS || 0, 325 totalNS: TraceRow.range?.totalNS || 0, 326 slicesTime: TraceRow.range?.slicesTime, 327 range: TraceRow.range, 328 frame: traceRow.frame 329 }, traceRow.getTransferArray(), (res: any, hover: any) => { 330 traceRow.must = false; 331 if (traceRow.isHover) { 332 SdkSliceStruct.hoverSdkSliceStruct = hover; 333 if (TraceRow.range) TraceRow.range.refresh = false; 334 this.trace.visibleRows.filter(it => it.rowType === TraceRow.ROW_TYPE_SDK_SLICE && it.name !== traceRow.name).forEach(it => it.draw(true)); 335 } 336 }) 337 traceRow.isTransferCanvas = true; 338 }) 339 this.trace.rowsEL?.appendChild(traceRow) 340 } 341 342}