• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2023 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';
17import '../../../../../base-ui/checkbox/LitCheckBox';
18import { LitTable } from '../../../../../base-ui/table/lit-table';
19import '../../../../../base-ui/popover/LitPopoverV';
20import { LitPopover } from '../../../../../base-ui/popover/LitPopoverV';
21import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection';
22import { queryRunningThread, queryCoreRunningThread } from '../../../../database/sql/ProcessThread.sql';
23import { ClassifyCoreSettingHtml } from '../TabPaneTime.html';
24import { HanldParalLogic, MeterHeaderClick } from './ParallelUtil';
25import { TabPaneFilter } from '../TabPaneFilter';
26import { Utils } from '../../base/Utils';
27
28
29const UNIT: number = 1000000.0;
30const NUM_DIGITS: number = 3;
31const CORE_NUM: number = 12;
32const LITTLE_CPU_NUM: Array<number> = [0, 1, 2, 3];
33const MID_CPU_NUM12: Array<number> = [4, 5, 6, 7, 8, 9];
34const BIG_CPU_NUM12: Array<number> = [10, 11];
35
36@element('tabpane-time-parallel')
37export class TabPaneTimeParallel extends BaseElement {
38    private bottomFilterEl: TabPaneFilter | undefined | null;
39    private parallelTable: LitTable | null | undefined;
40    private coreParallelTable: LitTable | null | undefined;
41    private litPopoverEl: LitPopover | null | undefined;
42    private selectionParam: SelectionParam | undefined;
43    private initMap: Map<string, unknown> = new Map<string, unknown>();
44    private leftStartNs: number = 0;
45    private rightEndNs: number = 0;
46    private midCores: Array<number> = [];
47    private bigCores: Array<number> = [];
48    private littleCores: Array<number> = [];
49    private initStatus: boolean = true;
50
51    set data(threadStatesParam: SelectionParam) {
52        if (this.selectionParam === threadStatesParam) { return; };
53        this.selectionParam = threadStatesParam;
54        this.leftStartNs = this.selectionParam!.leftNs + this.selectionParam!.recordStartNs;
55        this.rightEndNs = this.selectionParam!.rightNs + this.selectionParam!.recordStartNs;
56        //每次新款选线程时清空Map对象
57        this.initMap.clear();
58        this.initStatus = true;
59        this.initDefaultConfig();
60        this.parallelTable!.recycleDataSource = [];
61        this.coreParallelTable!.recycleDataSource = [];
62        this.switchTableInfo();
63    }
64    initElements(): void {
65        this.parallelTable = this.shadowRoot!.querySelector<LitTable>('#tb-parallel');
66        this.coreParallelTable = this.shadowRoot!.querySelector<LitTable>('#tb-core-parallel');
67        this.bottomFilterEl = this.shadowRoot?.querySelector('#filter');
68        this.litPopoverEl = this.bottomFilterEl?.shadowRoot?.querySelector('#data-core-popover');
69        this.litPopoverEl!.querySelector<HTMLDivElement>('#core-mining')!.onclick = (e): void => {
70            if (this.initStatus) {
71                this.initDefaultConfig();
72                this.initStatus = false;
73                this.bottomFilterEl!.setCoreConfigList(Utils.getInstance().getWinCpuCount(), this.littleCores, this.midCores, this.bigCores);
74            }
75        };
76        this.litPopoverEl!.querySelector<HTMLDivElement>('.confirm-button')!.addEventListener('click', (e: unknown) => {
77            this.switchTableInfo();
78        });
79        this.litPopoverEl!.querySelector<HTMLDivElement>('.reset-button')!.addEventListener('click', (e: unknown) => {
80            this.initStatus = true;
81            this.reset();
82        });
83    }
84    switchTableInfo(): void {
85        // @ts-ignore
86        this.litPopoverEl!.visible = false;
87        //当大中小核未分组时,默认查询所有核
88        if (!this.midCores.length && !this.bigCores.length && !this.littleCores.length) {
89            this.assignAllCore();
90        } else {
91            this.assignGroupCore();
92        }
93    }
94
95    reset(): void {
96        // @ts-ignore
97        this.litPopoverEl!.visible = false;
98        if (Utils.getInstance().getWinCpuCount() === CORE_NUM) {
99            this.coreParallelTable!.style.display = 'grid';
100            this.parallelTable!.style.display = 'none';
101            this.coreParallelTable!.loading = true;
102            this.coreParallelTable!.recycleDataSource = [...this.initMap.values()];
103            this.coreParallelTable!.loading = false;
104            MeterHeaderClick(this.coreParallelTable, [...this.initMap.values()]);
105        } else {
106            this.parallelTable!.style.display = 'grid';
107            this.coreParallelTable!.style.display = 'none';
108            this.parallelTable!.loading = true;
109            this.parallelTable!.recycleDataSource = [...this.initMap.values()];
110            this.parallelTable!.loading = false;
111        }
112    }
113
114    assignAllCore(): void {
115        this.parallelTable!.style.display = 'grid';
116        this.coreParallelTable!.style.display = 'none';
117        this.parallelTable!.loading = true;
118        this.getAllCoreData().then((res) => {
119            // @ts-ignore
120            if (this.initMap.size === 0) { this.initMap = res; }
121            // @ts-ignore
122            this.parallelTable!.recycleDataSource = [...res.values()];
123            this.parallelTable!.loading = false;
124        });
125    }
126
127    assignGroupCore(): void {
128        this.coreParallelTable!.style.display = 'grid';
129        this.parallelTable!.style.display = 'none';
130        this.coreParallelTable!.loading = true;
131        this.getCoreGroupData().then((res) => {
132            // @ts-ignore
133            if (this.initMap.size === 0) { this.initMap = res; }
134            // @ts-ignore
135            this.coreParallelTable!.recycleDataSource = [...res.values()];
136            this.coreParallelTable!.loading = false;
137            // @ts-ignore
138            MeterHeaderClick(this.coreParallelTable, [...res.values()]);
139        });
140    }
141
142    initDefaultConfig(): void {
143        if (this.initStatus) {
144            if (Utils.getInstance().getWinCpuCount() === CORE_NUM) {
145                this.littleCores = [...LITTLE_CPU_NUM];
146                this.midCores = [...MID_CPU_NUM12];
147                this.bigCores = [...BIG_CPU_NUM12];
148            } else {
149                this.littleCores = [];
150                this.midCores = [];
151                this.bigCores = [];
152            }
153        }
154    }
155
156    //获取每次被框选线程对应的state数据
157    async getAllCoreData(): Promise<unknown> {
158        let dataSourceMap: Map<string, unknown> = new Map<string, unknown>();
159        let processIds: Array<number> = [...new Set(this.selectionParam!.processIds)];
160        let res: unknown = await queryRunningThread(processIds, this.selectionParam!.threadIds, this.leftStartNs, this.rightEndNs);
161        this.handleAllParallelData(res, dataSourceMap);
162        return dataSourceMap;
163    }
164    //获取核分类数据
165    async getCoreGroupData(): Promise<unknown> {
166        let dataSourceMap: Map<string, unknown> = new Map<string, unknown>();
167        let processIds: Array<number> = [...new Set(this.selectionParam!.processIds)];
168        let cpuObj: Object = {
169            'B': this.bigCores,
170            'M': this.midCores,
171            'L': this.littleCores
172        };
173        for (const [key, val] of Object.entries(cpuObj)) {
174            if (val.length) {
175                let res: unknown = await queryCoreRunningThread(processIds, this.selectionParam!.threadIds, val, this.leftStartNs, this.rightEndNs);
176                this.hanldeGroupParalleData(res, key, dataSourceMap);
177            };
178        }
179        //转换最外层数据单位即保留三位小数
180        for (const [i, item] of dataSourceMap) {
181            // @ts-ignore
182            item.dur = (item.dur / UNIT).toFixed(NUM_DIGITS);
183            // @ts-ignore
184            item.load = item.load.toFixed(NUM_DIGITS);
185        }
186        return dataSourceMap;
187    }
188    //处理未按核分组的数据
189    handleAllParallelData(param: unknown, dataSourceMap: Map<string, unknown>): void {
190        // @ts-ignore
191        for (let i = 0; i < param.length; i++) {
192            // @ts-ignore
193            let stateItem = param[i];
194            if (stateItem.ts < this.leftStartNs) {
195                stateItem.ts = this.leftStartNs;
196            }
197            if (stateItem.endTs > this.rightEndNs) {
198                stateItem.endTs = this.rightEndNs;
199            }
200            let dur = stateItem.endTs - stateItem.ts;
201            if (dataSourceMap.has(`${stateItem.pid}`)) {
202                let obj = dataSourceMap.get(`${stateItem.pid}`);
203                // @ts-ignore
204                let setArr = new Set(obj.tidArr);
205                if (!(setArr.has(stateItem.tid))) {
206                    setArr.add(stateItem.tid);
207                    // @ts-ignore
208                    obj.tidArr.push(stateItem.tid);
209                }
210                // @ts-ignore
211                obj.dur += dur;
212                // @ts-ignore
213                obj!.stateItem.push(stateItem);
214            } else {
215                dataSourceMap.set(`${stateItem.pid}`, {
216                    pid: stateItem.pid,
217                    tid: stateItem.tid,
218                    title: stateItem.pName ? `${stateItem.pName} ${stateItem.pid}` : `[NULL] ${stateItem.pid}`,
219                    tidArr: [stateItem.tid],
220                    dur: dur,
221                    parallelNum: null,
222                    allParallel: null,
223                    stateItem: [stateItem],
224                    tCount: null,
225                    load: null,
226                    pDur: null,
227                    children: []
228                });
229            };
230        };
231        this.showTreeChart(dataSourceMap);
232    }
233    //处理核分组数据
234    hanldeGroupParalleData(val: unknown, key: string, dataSourceMap: Map<string, unknown>): void {
235        let coreMap: Map<string, unknown> = new Map<string, unknown>();
236        // @ts-ignore
237        for (let i = 0; i < val.length; i++) {
238            // @ts-ignore
239            let stateItem = val[i];
240            if (stateItem.ts < this.leftStartNs) {
241                stateItem.ts = this.leftStartNs;
242            }
243            if (stateItem.endTs > this.rightEndNs) {
244                stateItem.endTs = this.rightEndNs;
245            }
246            let dur = stateItem.endTs - stateItem.ts;
247            if (!dataSourceMap.has(`${stateItem.pid}`)) {
248                dataSourceMap.set(`${stateItem.pid}`, {
249                    pid: stateItem.pid,
250                    tid: stateItem.tid,
251                    title: stateItem.pName ? `${stateItem.pName} ${stateItem.pid}` : `[NULL] ${stateItem.pid}`,
252                    dur: null,
253                    parallelNum: null,
254                    parallelDur: null,
255                    allParallel: null,
256                    tCount: null,
257                    load: null,
258                    pDur: null,
259                    children: []
260                });
261            };
262            if (coreMap.has(`${stateItem.pid} ${key}`)) {
263                let obj = coreMap.get(`${stateItem.pid} ${key}`);
264                // @ts-ignore
265                let setArr = new Set(obj.tidArr);
266                if (!(setArr.has(stateItem.tid))) {
267                    setArr.add(stateItem.tid);
268                    // @ts-ignore
269                    obj.tidArr.push(stateItem.tid);
270                }
271                // @ts-ignore
272                obj.dur += dur;
273                // @ts-ignore
274                obj!.stateItem.push(stateItem);
275            } else {
276                coreMap.set(`${stateItem.pid} ${key}`, {
277                    pid: stateItem.pid,
278                    tid: stateItem.tid,
279                    title: `${key}`,
280                    tidArr: [stateItem.tid],
281                    dur: dur,
282                    parallelNum: null,
283                    parallelDur: null,
284                    allParallel: null,
285                    stateItem: [stateItem],
286                    tCount: null,
287                    load: null,
288                    pDur: null,
289                    children: []
290                });
291            };
292        };
293        this.showCoreTreeChart(coreMap, dataSourceMap);
294    }
295
296    showTreeChart(param: Map<string, unknown>): void {
297        for (let [key, value] of param) {
298            let pMap: Map<string, unknown> = new Map<string, unknown>();
299            HanldParalLogic(this.hanldMapLogic, value, pMap);
300            // @ts-ignore
301            value.tCount = value.tidArr.length;
302            // @ts-ignore
303            value.load = (value.dur / ((100 * UNIT) * Utils.getInstance().getWinCpuCount())).toFixed(NUM_DIGITS);
304            // @ts-ignore
305            value.dur = (value.dur / UNIT).toFixed(NUM_DIGITS);
306            if (pMap.size === 0) {
307                // @ts-ignore
308                value.allParallel = 0.000.toFixed(NUM_DIGITS);
309            } else {
310                for (const [i, item] of pMap) {
311                    // @ts-ignore
312                    value.allParallel += item.allParallel;
313                    // @ts-ignore
314                    item.allParallel = item.allParallel.toFixed(NUM_DIGITS);
315                }
316                // @ts-ignore
317                value.allParallel = value.allParallel.toFixed(NUM_DIGITS);
318                // @ts-ignore
319                value.children = [...pMap.values()];
320            }
321        }
322    }
323
324    showCoreTreeChart(param: unknown, dataSourceMap: Map<string, unknown>): void {
325        // @ts-ignore
326        for (let [key, value] of param) {
327            let pMap: Map<string, unknown> = new Map<string, unknown>();
328            // @ts-ignore
329            pMap = HanldParalLogic(this.hanldMapLogic, value, pMap);
330            value.load = (value.dur / ((100 * UNIT) * Utils.getInstance().getWinCpuCount()));
331            if (pMap.size === 0) {
332                value.allParallel = 0.000;
333                value.parallelNum = '-';
334                value.parallelDur = '-';
335            } else {
336                for (const [i, item] of pMap) {
337                    // @ts-ignore
338                    value.allParallel += item.allParallel;
339                    // @ts-ignore
340                    item.allParallel = item.allParallel;
341                    // @ts-ignore
342                    item.allParallel = item.allParallel.toFixed(NUM_DIGITS);
343                }
344                value.children = [...pMap.values()];
345            }
346            if (dataSourceMap.has(`${value.pid}`)) {
347                let obj = dataSourceMap.get(`${value.pid}`);
348                value.tCount = value.tidArr.length;
349                // @ts-ignore
350                obj.dur += value.dur;
351                // @ts-ignore
352                obj.load += value.load;
353                value.allParallel = value.allParallel.toFixed(NUM_DIGITS);
354                value.dur = (value.dur / UNIT).toFixed(NUM_DIGITS);
355                value.load = value.load.toFixed(NUM_DIGITS);
356                // @ts-ignore
357                obj.children.push(value);
358            }
359        }
360    }
361    //每次stateItem计算的的结果,处理对应map的值
362    hanldMapLogic(dumpObj: unknown, value?: unknown, pMap?: unknown): unknown {
363        // @ts-ignore
364        let pDur = dumpObj.endTs - dumpObj.ts;
365        // @ts-ignore
366        let pSlice = ((dumpObj.len * pDur) / value.dur) * 100;
367        // @ts-ignore
368        if (pMap!.has(dumpObj.len.toString())) {
369            // @ts-ignore
370            let pObj = pMap!.get(dumpObj.len.toString());
371            pObj.allParallel += pSlice;
372            pObj.pDur += pDur;
373            pObj.parallelDur = `${((pObj.pDur) / UNIT).toFixed(NUM_DIGITS)}`;
374        } else {
375            // @ts-ignore
376            if (dumpObj.len !== 1) {
377                // @ts-ignore
378                pMap!.set(dumpObj.len.toString(), {
379                    pid: null,
380                    tid: null,
381                    title: '',
382                    // @ts-ignore
383                    tidArr: value.tidArr,
384                    dur: null,
385                    allParallel: pSlice,
386                    // @ts-ignore
387                    parallelNum: dumpObj.len,
388                    parallelDur: ((pDur) / UNIT).toFixed(NUM_DIGITS),
389                    pDur: pDur,
390                    // @ts-ignore
391                    stateItem: value.stateItem,
392                    tCount: null,
393                    load: '-',
394                    children: []
395                });
396            }
397        }
398        return pMap;
399    }
400
401    //回调函数,首次插入DOM时执行的初始化回调
402    connectedCallback(): void {
403        super.connectedCallback();
404        new ResizeObserver(() => {
405            if (this.parentElement?.clientHeight !== 0) {
406                // @ts-ignore
407                this.parallelTable!.shadowRoot!.querySelector('.table')!.style.height = `${this.parentElement!.clientHeight - 31}px`;
408                this.parallelTable?.reMeauseHeight();
409                // @ts-ignore
410                this.coreParallelTable!.shadowRoot!.querySelector('.table')!.style.height = `${this.parentElement!.clientHeight - 31}px`;
411                this.coreParallelTable?.reMeauseHeight();
412                if (this.parentElement!.clientHeight >= 0 && this.parentElement!.clientHeight <= 31) {
413                    this.bottomFilterEl!.style.display = 'none';
414                } else {
415                    this.bottomFilterEl!.style.display = 'flex';
416                }
417            }
418        }).observe(this.parentElement!);
419    }
420    initHtml(): string {
421        return ClassifyCoreSettingHtml;
422    }
423}
424