• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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