• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2024 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 { type LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table';
18import { type SelectionParam } from '../../../../bean/BoxSelection';
19import { resizeObserver } from '../SheetUtils';
20import { queryDmaFenceData } from '../../../../database/sql/dmaFence.sql';
21import { DmaFenceDataBean, DmaFenceTreeBean, DmaFenceStringBean } from './DmaFenceBean';
22
23@element('tabpane-dmafrence')
24export class TabPaneDmaFence extends BaseElement {
25    private dmaFenceTbl: LitTable | null | undefined;
26    private currentSelectionParam: SelectionParam | undefined;
27    private timeSelection: HTMLLabelElement | null | undefined;
28    private finaldmaFenceData: Array<DmaFenceStringBean> = [];
29    private sortKey: string = 'name';
30    private sortType: number = 0;
31
32    set data(dmaFenceValue: SelectionParam) {
33        if (this.currentSelectionParam === dmaFenceValue) {
34            return;
35        };
36        this.currentSelectionParam = dmaFenceValue;
37        this.dmaFenceTbl!.recycleDataSource = [];
38        this.dmaFenceTbl!.loading = true;
39        //@ts-ignore
40        this.dmaFenceTbl?.shadowRoot?.querySelector('.table')?.style?.height = this.parentElement!.clientHeight - 45 + 'px';
41        queryDmaFenceData(dmaFenceValue.leftNs, dmaFenceValue.rightNs, dmaFenceValue.dmaFenceNameData).then((result: Array<DmaFenceDataBean>) => {
42            if (result !== null && result.length > 0) {
43                this.dmaFenceTbl!.loading = false;
44                let resultList: Array<DmaFenceDataBean> = JSON.parse(JSON.stringify(result));
45                this.finaldmaFenceData = this.createTree(resultList);
46                this.timeSelection!.innerHTML =
47                    'Selection start: ' + (resultList[0].startTime / 1000000).toFixed(3) + ' ms' + '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' + 'Selection extent: ' + ((resultList[resultList.length - 1].endTime / 1000000) - (resultList[0].startTime / 1000000)).toFixed(3) + ' ms';
48                this.sortByColumn(this.sortKey, this.sortType, false);
49            } else {
50                this.dmaFenceTbl!.recycleDataSource = [];
51                this.dmaFenceTbl!.loading = false;
52                this.timeSelection!.innerHTML =
53                    'Selection start: ' + 0 + ' ms' + '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' + 'Selection extent: ' + 0 + ' ms';
54            }
55        });
56    }
57
58    private createTree(data: Array<DmaFenceDataBean>): Array<DmaFenceStringBean> {
59        const treeMap = new Map<string, { dur: number; occurrences: number; children: Array<DmaFenceTreeBean> }>();
60        data.forEach(item => {
61            const timeline = item.timeline;
62            const nameBase = item.cat.startsWith('dma_fence_signaled') ? 'fence_signal' : item.cat.split('dma_')[1];
63            const name = `${nameBase}(${item.seqno})`;
64            const durValue = item.dur / 1000000;
65
66            let timelineRecord = treeMap.get(timeline);
67            if (!timelineRecord) {
68                timelineRecord = {
69                    dur: 0,
70                    occurrences: 0,
71                    children: []
72                };
73                treeMap.set(timeline, timelineRecord);
74            }
75
76            let node = timelineRecord.children.find(child => child.name === name);
77            if (!node) {
78                node = {
79                    name,
80                    dur: durValue,
81                    occurrences: 1,
82                    average: durValue,
83                    status: item.status,
84                };
85                timelineRecord.children.push(node);
86            } else {
87                node.dur += durValue;
88                node.occurrences += 1;
89                node.average = node.dur / node.occurrences;
90            }
91            timelineRecord.dur += durValue;
92            timelineRecord.occurrences += 1;
93        });
94        const root: DmaFenceTreeBean = {
95            name: 'totals',
96            dur: 0,
97            occurrences: 0,
98            children: [],
99            average: 0,
100            status: false
101        };
102
103        // 遍历treeMap来创建子节点,并按timeline分组
104        treeMap.forEach((timelineRecord, timeline) => {
105            const timelineAverage = timelineRecord.dur / timelineRecord.occurrences;
106            const timelineNode: DmaFenceTreeBean = {
107                name: timeline,
108                dur: timelineRecord.dur,
109                occurrences: timelineRecord.occurrences,
110                average: timelineAverage,
111                children: timelineRecord.children,
112                status: false
113            };
114            root.dur += timelineNode.dur;
115            root.occurrences += timelineNode.occurrences;
116
117            root.children!.push(timelineNode);
118        });
119        root.average = root.occurrences > 0 ? root.dur / root.occurrences : 0;
120        let rootList: Array<DmaFenceStringBean> = this.convertString([root]);
121        return rootList;
122    }
123
124    private convertString(data: Array<DmaFenceTreeBean>): Array<DmaFenceStringBean> {
125        const result: Array<DmaFenceStringBean> = [];
126        data.forEach(item => {
127            const stringBean: DmaFenceStringBean = {
128                name: item.name,
129                dur: item.dur.toFixed(3),
130                average: item.average.toFixed(3),
131                occurrences: String(item.occurrences),
132                children: item.children ? this.convertString(item.children) : undefined,
133                status: item.status
134            };
135            result.push(stringBean);
136        });
137        return result;
138    }
139
140    private sortByColumn(key: string, type: number, isExpand: boolean): void {
141        let sortObject = JSON.parse(JSON.stringify(this.finaldmaFenceData));
142        let sortList: Array<DmaFenceStringBean> = [];
143        sortList.push(sortObject[0]);
144        if (type === 0) {
145            this.dmaFenceTbl!.recycleDataSource = this.finaldmaFenceData;
146            this.expandFunction(isExpand, this.finaldmaFenceData);
147            return;
148        } else {
149            sortList.forEach((item) => {
150                if (item.children) {
151                    item.children.forEach((child) => {
152                        if (child.children) {
153                            child.children.sort((a, b) => {
154                                let aValue: number | string;
155                                let bValue: number | string;
156                                if (key === 'name') {
157                                    aValue = a[key];
158                                    bValue = b[key];
159                                } else {
160                                    // @ts-ignore
161                                    aValue = parseFloat(a[key]);
162                                    // @ts-ignore
163                                    bValue = parseFloat(b[key]);
164                                }
165                                if (typeof aValue === 'string' && typeof bValue === 'string') {
166                                    return type === 1 ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
167                                } else if (typeof aValue === 'number' && typeof bValue === 'number') {
168                                    return type === 1 ? aValue - bValue : bValue - aValue;
169                                } else {
170                                    return 0;
171                                }
172                            });
173                        }
174                    });
175                }
176            });
177            this.dmaFenceTbl!.recycleDataSource = sortList;
178            this.expandFunction(isExpand, sortList);
179        }
180    }
181
182    private expandFunction(isExpand: boolean, list: Array<DmaFenceStringBean>): void {
183        if (isExpand) {
184            this.dmaFenceTbl!.setStatus(list, true);
185            this.dmaFenceTbl!.recycleDs = this.dmaFenceTbl!.meauseTreeRowElement(list, RedrawTreeForm.Expand);
186        }
187    }
188
189    initElements(): void {
190        this.dmaFenceTbl = this.shadowRoot?.querySelector<LitTable>('#tb-dmafence-slices');
191        this.timeSelection = this.shadowRoot?.querySelector('#time-selection');
192        this.dmaFenceTbl!.addEventListener('column-click', (evt) => {
193            // @ts-ignore
194            this.sortKey = evt.detail.key;
195            // @ts-ignore
196            this.sortType = evt.detail.sort;
197            // @ts-ignore
198            this.sortByColumn(evt.detail.key, evt.detail.sort, true);
199        });
200    }
201
202    connectedCallback(): void {
203        super.connectedCallback();
204        resizeObserver(this.parentElement!, this.dmaFenceTbl!);
205    }
206
207    initHtml(): string {
208        return `
209        <style>
210        .dmafence-select-label{
211            margin-bottom: 5px;
212        }
213        :host{
214            padding: 10px 10px;
215            display: flex;
216            flex-direction: column;
217        }
218        </style>
219        <label id="time-selection" class="dmafence-select-label" style="width: 100%;height: 20px;text-align: end;font-size: 10pt;">Selection start:0.0 ms  Selection extent:0.0 ms</label>
220        <lit-table id="tb-dmafence-slices" style="height: auto; overflow-x:auto;width:calc(100vw - 270px)" tree>
221            <lit-table-column order class="dmafence-slices-column" width='25%' title="Name" data-index="name" key="name" align="flex-start" retract>
222            </lit-table-column>
223            <lit-table-column order class="dmafence-slices-column" width='1fr' title="Wall Duration(ms)" data-index="dur" key="dur" align="flex-start">
224            </lit-table-column>
225            <lit-table-column order class="dmafence-slices-column" width='1fr' title="Average Wall Duration(ms)" data-index="average" key="average" align="flex-start">
226            </lit-table-column>
227            <lit-table-column order class="dmafence-slices-column" width='1fr' title="Occurrences" data-index="occurrences" key="occurrences" align="flex-start">
228            </lit-table-column>
229        </lit-table>
230        `;
231    }
232
233}