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 { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; 17import { SelectionParam } from '../../../../bean/BoxSelection'; 18import { LitTable } from '../../../../../base-ui/table/lit-table'; 19import { resizeObserver } from '../SheetUtils.js'; 20import { FuncStruct } from '../../../../database/ui-worker/ProcedureWorkerFunc.js'; 21import { 22 queryConcurrencyTask, 23 queryTaskListByExecuteTaskIds, 24 queryTaskPoolTotalNum 25} from '../../../../database/SqlLite.js'; 26import { BaseStruct } from '../../../../database/ui-worker/ProcedureWorkerCommon.js'; 27import { SpSystemTrace } from '../../../SpSystemTrace.js'; 28import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; 29 30@element('tabpane-task-frames') 31export class TabPaneTaskFrames extends BaseElement { 32 private taskFramesTbl: LitTable | null | undefined; 33 private range: HTMLLabelElement | null | undefined; 34 private taskFramesSource: Array<TaskTabStruct> = []; 35 private progressEL: LitProgressBar | null | undefined; 36 static TaskArray: Array<FuncStruct> = []; 37 static IsShowConcurrency: boolean = false; 38 39 set data(framesParam: SelectionParam) { 40 if (TabPaneTaskFrames.TaskArray && TabPaneTaskFrames.TaskArray.length > 0) { 41 //点选 42 this.setTaskData(TabPaneTaskFrames.TaskArray, framesParam, true); 43 } else { 44 if (!framesParam) { 45 this.taskFramesTbl!!.recycleDataSource = []; 46 return; 47 } 48 //框选 49 this.range!.textContent = `Selected range: 50 ${ parseFloat(((framesParam.rightNs - framesParam.leftNs) / 1000000.0).toFixed(5)) } ms`; 51 this.progressEL!.loading = true; 52 this.queryDataByDB(framesParam, false); 53 } 54 } 55 56 setTaskData(taskArray: Array<FuncStruct>, framesParam: SelectionParam, isClick: boolean) { 57 if (taskArray.length < 3) { 58 this.taskFramesTbl!!.recycleDataSource = []; 59 return; 60 } else { 61 let sTime = 0, eTime = 0, rTime = 0; 62 let aStartTime = 0, pStartTime = 0, rEndTime = 0; 63 let priorityId = 1; 64 let executeId = ''; 65 let executeStruct; 66 taskArray.forEach((item) => { 67 if (item.funName!.indexOf('H:Task Allocation:') >= 0) { 68 aStartTime = item.startTs!; 69 priorityId = TabPaneTaskFrames.getPriorityId(item.funName!); 70 executeId = TabPaneTaskFrames.getExecuteId(item.funName!); 71 } else if (item.funName!.indexOf('H:Task Perform:') >= 0) { 72 executeStruct = item; 73 pStartTime = item.startTs!; 74 eTime = item.dur!; 75 } else if (item.funName!.indexOf('H:Task PerformTask End:') >= 0) { 76 rEndTime = item.startTs! + item.dur!; 77 } 78 }); 79 sTime = pStartTime - aStartTime; 80 rTime = rEndTime - (pStartTime + eTime); 81 if (TabPaneTaskFrames.IsShowConcurrency) { 82 let tableList: TaskTabStruct[] = []; 83 let countConcurrencyPromise = this.countConcurrency(executeStruct, tableList, framesParam, isClick); 84 countConcurrencyPromise.then(result => { 85 let concurrencyColumn: TaskTabStruct = new TaskTabStruct(); 86 concurrencyColumn.executeId = 'Task Concurrency'; 87 concurrencyColumn.taskPriority = `${ result }`; 88 tableList.push(concurrencyColumn); 89 let filterList = []; 90 let map = new Map(); 91 for (const item of tableList) { 92 if (!map.has(item.executeId)) { 93 map.set(item.executeId, true); 94 filterList.push(item); 95 } 96 } 97 this.taskFramesSource = filterList; 98 this.taskFramesTbl!!.recycleDataSource = this.taskFramesSource; 99 }); 100 } else { 101 let task: TaskTabStruct = new TaskTabStruct(); 102 task.executeId = executeId; 103 task.taskPriority = Priority[priorityId]; 104 task.taskST = this.getMsTime(sTime); 105 task.taskET = this.getMsTime(eTime); 106 task.taskRT = this.getMsTime(rTime); 107 this.taskFramesSource = [task]; 108 this.taskFramesTbl!!.recycleDataSource = this.taskFramesSource; 109 } 110 } 111 } 112 113 queryDataByDB(framesParam: SelectionParam, isClick: boolean): void { 114 let tableList: TaskTabStruct[] = []; 115 let executeTaskList: FuncStruct[] = []; 116 let executeTaskIds: number[] = []; 117 this.taskFramesTbl!.recycleDataSource = []; 118 for (let index = 0 ; index < framesParam.taskFramesData.length ; index++) { 119 let data = framesParam.taskFramesData[index]; 120 for (let y = 0 ; y < data.length ; y++) { 121 let executeId = TabPaneTaskFrames.getExecuteId(data[y].funName!); 122 if (data[y].funName!.indexOf('H:Task Perform:') >= 0) { 123 executeTaskList.push(data[y]); 124 } 125 executeTaskIds.push(parseInt(executeId)); 126 } 127 } 128 queryTaskListByExecuteTaskIds(executeTaskIds).then((taskList) => { 129 for (let index = 0 ; index < taskList.length ; index++) { 130 this.pushTaskToList(taskList[index], tableList); 131 } 132 this.handleConcurrency(executeTaskList, tableList, framesParam, isClick); 133 }); 134 } 135 136 137 initElements(): void { 138 this.taskFramesTbl = this.shadowRoot?.querySelector<LitTable>('#tb-frames'); 139 this.range = this.shadowRoot?.querySelector('#task-frames-time-range'); 140 this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar; 141 this.taskFramesTbl!.addEventListener('column-click', (evt) => { 142 // @ts-ignore 143 this.sortByColumn(evt.detail); 144 }); 145 } 146 147 getMsTime(ts: number): number { 148 return parseFloat((ts / 1000000.0).toFixed(6)); 149 } 150 151 connectedCallback(): void { 152 super.connectedCallback(); 153 resizeObserver(this.parentElement!, this.taskFramesTbl!); 154 } 155 156 initHtml(): string { 157 return ` 158 <style> 159 .frames-label{ 160 height: 20px; 161 text-align: end; 162 } 163 :host{ 164 padding: 10px 10px; 165 display: flex; 166 flex-direction: column; 167 } 168 </style> 169 <label id="task-frames-time-range" class="frames-label" style="width: 100%;font-size: 10pt;margin-bottom: 5px"> 170 Selected range:0.0 ms</label> 171 <lit-progress-bar class="progress"></lit-progress-bar> 172 <lit-table id="tb-frames" style="height: auto"> 173 <lit-table-column class="task-frames-column" title="Execute Id" width="1fr" data-index="executeId" 174 key="executeId" align="flex-start" order> 175 </lit-table-column> 176 <lit-table-column class="task-frames-column" title="Task Priority" width="1fr" data-index="taskPriority" 177 key="taskPriority" align="flex-start" order > 178 </lit-table-column> 179 <lit-table-column class="task-frames-column" title="Scheduling Time(ms)" width="1fr" 180 data-index="taskST" key="taskST" align="flex-start" order > 181 </lit-table-column> 182 <lit-table-column class="task-frames-column" title="Execution Time(ms)" width="1fr" data-index="taskET" 183 key="taskET" align="flex-start" order > 184 </lit-table-column> 185 <lit-table-column class="task-frames-column" title="Return Time(ms)" width="1fr" data-index="taskRT" 186 key="taskRT" align="flex-start" order > 187 </lit-table-column> 188 </lit-table> 189 `; 190 } 191 192 sortByColumn(framesDetail: any) { 193 // @ts-ignore 194 let compare = function (property, sort, type) { 195 return function (taskFramesLeftData: TaskTabStruct, taskFramesRightData: TaskTabStruct) { 196 if (taskFramesLeftData.executeId === 'Task Concurrency') { 197 return 0; 198 } 199 if (type === 'number') { 200 // @ts-ignore 201 let forwardNum = parseFloat(taskFramesRightData[property]) - parseFloat(taskFramesLeftData[property]); 202 // @ts-ignore 203 let reserveNum = parseFloat(taskFramesLeftData[property]) - parseFloat(taskFramesRightData[property]); 204 return sort === 2 ? forwardNum : reserveNum; 205 } else { 206 // @ts-ignore 207 if (taskFramesRightData[property] > taskFramesLeftData[property]) { 208 return sort === 2 ? 1 : -1; 209 } else { 210 // @ts-ignore 211 if (taskFramesRightData[property] === taskFramesLeftData[property]) { 212 return 0; 213 } else { 214 return sort === 2 ? -1 : 1; 215 } 216 } 217 } 218 }; 219 }; 220 if (framesDetail.key === 'taskPriority') { 221 this.taskFramesSource.sort(compare(framesDetail.key, framesDetail.sort, 'string')); 222 } else { 223 this.taskFramesSource.sort(compare(framesDetail.key, framesDetail.sort, 'number')); 224 } 225 this.taskFramesTbl!.recycleDataSource = this.taskFramesSource; 226 } 227 228 static getExecuteId(funName: string): string { 229 let strArray = funName.split(','); 230 let executeStr = ''; 231 let executeId = ''; 232 let endStr = ''; 233 if (strArray.length >= 2) { 234 executeStr = strArray[1]; 235 if (funName.indexOf('H:Task Allocation:') >= 0 || funName.indexOf('H:Task Perform:') >= 0) { 236 executeId = executeStr.split(':')[1].trim(); 237 } else if (funName.indexOf('H:Task PerformTask End:') >= 0) { 238 endStr = executeStr.split(':')[1].trim(); 239 if (endStr.indexOf('[') >= 0) { 240 executeId = endStr.substring(0, endStr.indexOf('[')); 241 } else { 242 executeId = endStr; 243 } 244 } 245 } 246 return executeId; 247 } 248 249 static getPriorityId(funName: string): number { 250 let strArray = funName.split(','); 251 let priorityId = ''; 252 if (strArray.length >= 2) { 253 let executeStr = strArray[2]; 254 if (funName.indexOf('H:Task Allocation:') >= 0) { 255 priorityId = executeStr.split(':')[1].trim(); 256 } 257 } 258 return parseInt(priorityId); 259 } 260 261 private async countConcurrency(selectFuncStruct: FuncStruct | undefined, 262 tableList: TaskTabStruct[], framesParam: SelectionParam, isClick: boolean): Promise<number> { 263 let selectStartTime = selectFuncStruct!.startTs! + (window as any).recordStartNS; 264 let selectEndTime = selectFuncStruct!.startTs! + selectFuncStruct!.dur! + (window as any).recordStartNS; 265 if (!isClick) { 266 let startTime = framesParam.recordStartNs + framesParam.leftNs; 267 let endTime = framesParam.recordStartNs + framesParam.rightNs; 268 if ((selectStartTime <= startTime && startTime <= selectEndTime) || 269 (selectStartTime <= endTime && endTime <= selectEndTime)) { 270 selectStartTime = startTime; 271 selectEndTime = endTime; 272 } 273 } 274 let maxConcurrency = 0; 275 await Promise.all([queryTaskPoolTotalNum(selectFuncStruct!.funName!), 276 queryConcurrencyTask(selectFuncStruct!.funName!, selectStartTime, selectEndTime)]).then( 277 (res) => { 278 let currentConcurrency = 0; 279 let tasks:Array<TaskTabStruct> = res[1] 280 for (let i = 0; i < tasks.length; i++) { 281 const task = tasks[i]; 282 // @ts-ignore 283 const endTime = task!.startTs + task!.dur; 284 currentConcurrency++; 285 for (let j = i + 1; j < tasks.length; j++) { 286 const nextTask = tasks[j]; 287 // @ts-ignore 288 if (nextTask.startTs < endTime) { 289 currentConcurrency++; 290 } 291 } 292 // 更新最大并发度 293 if (currentConcurrency > maxConcurrency) { 294 maxConcurrency = currentConcurrency; 295 if (maxConcurrency === res[0].length) { 296 break; 297 } 298 } 299 // 重置当前并发度 300 currentConcurrency = 0; 301 } 302 for (const item of res[1]) { 303 this.pushTaskToList(item, tableList); 304 } 305 } 306 ); 307 return maxConcurrency; 308 } 309 310 private handleConcurrency(executeTaskList: FuncStruct[], tableList: TaskTabStruct[], framesParam: SelectionParam, isClick: boolean): void { 311 let maxNumConcurrency = 0; 312 if (executeTaskList.length > 0) { 313 let handleConcurrency = async (): Promise<void> => { 314 for (let i = 0 ; i < executeTaskList.length ; i++) { 315 let countConcurrencyPromise = await this.countConcurrency(executeTaskList[i], tableList, framesParam, isClick); 316 if (countConcurrencyPromise > maxNumConcurrency) { 317 maxNumConcurrency = countConcurrencyPromise; 318 } 319 } 320 }; 321 handleConcurrency().then(() => { 322 let concurrencyColumn: TaskTabStruct = new TaskTabStruct(); 323 concurrencyColumn.executeId = 'Task Concurrency'; 324 concurrencyColumn.taskPriority = `${ maxNumConcurrency }`; 325 tableList.push(concurrencyColumn); 326 //去重 327 let filterList = []; 328 let map = new Map(); 329 for (const item of tableList) { 330 if (!map.has(item.executeId)) { 331 map.set(item.executeId, true); 332 filterList.push(item); 333 } 334 } 335 this.taskFramesSource = filterList; 336 this.taskFramesTbl!.recycleDataSource = filterList; 337 this.progressEL!.loading = false; 338 }); 339 } else { 340 this.taskFramesSource = tableList; 341 this.taskFramesTbl!.recycleDataSource = tableList; 342 this.progressEL!.loading = false; 343 } 344 } 345 346 private pushTaskToList(value: TaskTabStruct, tableList: TaskTabStruct[]): void { 347 let allocationTask = SpSystemTrace.DATA_TASK_POOL_CALLSTACK.get(value.allocationTaskRow!); 348 let executeTask = SpSystemTrace.DATA_TASK_POOL_CALLSTACK.get(value.executeTaskRow!); 349 let returnTask = SpSystemTrace.DATA_TASK_POOL_CALLSTACK.get(value.returnTaskRow!); 350 let tempTask: TaskTabStruct = new TaskTabStruct(); 351 let executeStartTime = executeTask!.ts!; 352 let executeTime = executeTask!.dur!; 353 let aStartTime = allocationTask!.ts!; 354 let rEndTime = returnTask!.ts! + returnTask!.dur!; 355 tempTask.executeId = value.executeId; 356 tempTask.taskPriority = Priority[value.priority!]; 357 tempTask.taskST = this.getMsTime(executeStartTime - aStartTime); 358 tempTask.taskET = this.getMsTime(executeTime); 359 tempTask.taskRT = this.getMsTime(rEndTime - (executeStartTime + executeTime)); 360 tableList.push(tempTask); 361 } 362} 363 364enum Priority { 365 HIGH, 366 MEDIUM, 367 LOW 368} 369 370export class TaskTabStruct extends BaseStruct { 371 static maxValue: number = 0; 372 static maxName: string = ''; 373 static index = 0; 374 id: number | undefined; 375 tid: number | undefined; 376 ipid: number | undefined; 377 executeId: string | undefined; 378 startTs: number | undefined; 379 funName: string | undefined; 380 dur: number | undefined; 381 taskST: number | undefined; 382 taskET: number | undefined; 383 taskRT: number | undefined; 384 allocationTaskRow: number | undefined; 385 executeTaskRow: number | undefined; 386 returnTaskRow: number | undefined; 387 priority: number | undefined; 388 taskPriority: string | undefined; 389 isUse: boolean = false; 390 isTimeOut: boolean | undefined; 391} 392