From 88023f3ef0acc307007cfbe791ed4f1ea087c3f6 Mon Sep 17 00:00:00 2001 From: "wupoli3@huawei.com" Date: Fri, 15 Dec 2023 12:02:20 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=90=8C=E6=AD=A5binder=E5=92=8C=E5=BC=82?= =?UTF-8?q?=E6=AD=A5binder=E6=95=B0=E7=BB=9F=E8=AE=A1=EF=BC=8C=E6=9F=B1?= =?UTF-8?q?=E7=8A=B6=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wupoli3@huawei.com --- .../base-ui/chart/column/LitChartColumn.ts | 7 +- .../chart/column/LitChartColumnConfig.ts | 2 + ide/src/trace/bean/BinderProcessThread.ts | 82 ++ .../component/trace/base/TraceSheetConfig.ts | 14 +- ide/src/trace/component/trace/base/Utils.ts | 14 + .../sheet/binder/TabPaneBinderDataCut.ts | 773 ++++++++++++++++++ .../trace/sheet/binder/TabPaneBinders.ts | 177 ++++ ide/src/trace/database/SqlLite.ts | 173 +++- 8 files changed, 1233 insertions(+), 9 deletions(-) create mode 100644 ide/src/trace/bean/BinderProcessThread.ts create mode 100644 ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts create mode 100644 ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts diff --git a/ide/src/base-ui/chart/column/LitChartColumn.ts b/ide/src/base-ui/chart/column/LitChartColumn.ts index acf16319..b4231914 100644 --- a/ide/src/base-ui/chart/column/LitChartColumn.ts +++ b/ide/src/base-ui/chart/column/LitChartColumn.ts @@ -207,11 +207,14 @@ export class LitChartColumn extends BaseElement { for (let i = 0; i <= 5; i++) { this.rowLines.push({ y: gap * i, - label: `${getProbablyTime(maxValue - valGap * i)}`, + label: this.litChartColumnCfg.removeUnit === true ? `${maxValue - valGap * i}` : `${getProbablyTime(maxValue - valGap * i)}`, }); } + if (!this.litChartColumnCfg.notSort) { + this.litChartColumnCfg?.data + .sort((a, b) => b[this.litChartColumnCfg!.yField] - a[this.litChartColumnCfg!.yField]); + } this.litChartColumnCfg?.data - .sort((a, b) => b[this.litChartColumnCfg!.yField] - a[this.litChartColumnCfg!.yField]) .forEach((litChartColumnItem, litChartColumnIndex, array) => { this.data.push({ color: this.litChartColumnCfg!.color(litChartColumnItem), diff --git a/ide/src/base-ui/chart/column/LitChartColumnConfig.ts b/ide/src/base-ui/chart/column/LitChartColumnConfig.ts index b508e827..c5a292f0 100644 --- a/ide/src/base-ui/chart/column/LitChartColumnConfig.ts +++ b/ide/src/base-ui/chart/column/LitChartColumnConfig.ts @@ -19,6 +19,8 @@ export interface LitChartColumnConfig { xField: string; yField: string; seriesField: string; + notSort?: boolean; + removeUnit?: boolean; color: (a: any) => string; tip: ((a: any) => string) | undefined; hoverHandler?: (no: number) => void; diff --git a/ide/src/trace/bean/BinderProcessThread.ts b/ide/src/trace/bean/BinderProcessThread.ts new file mode 100644 index 00000000..6b4e66b6 --- /dev/null +++ b/ide/src/trace/bean/BinderProcessThread.ts @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class BinderGroup { + title: string | null | undefined = ''; + count: number = 0; + totalCount: number = 0; + binderAsyncRcvCount?: number = 0; + binderReplyCount?: number = 0; + binderTransactionAsyncCount?: number = 0; + binderTransactionCount?: number = 0; + tid: number = 0; + pid: number = 0; + thread: string = ''; + process: string = ''; + name: string = ''; + cycleStartTime: number = 0; + cycleDur: number = 0; + id: number = 0; + children?: Array; + type?: string = ''; + status?: boolean = false; + idx: number = 0; + isSelected?: boolean; +} + +export class DataSource { + xName: string = ''; + yAverage: number = 0; +} + +export class FuncNameCycle { + funcName: string = ''; + cycleStartTime: number = 0; + cycleDur: number = 0; + startTime: number = 0; + endTime: number = 0; + id: number = 0; + tid: number = 0; + pid: number = 0; +} + +export class BinderDataStruct { + name: string = ''; + count: number = 0; + dur: number = 0; + startNS: number = 0; + idx: number = -1; + depth?: number = 0; +} + +export class BinderItem { + title?: string = ''; + name: string = ''; + count?: number = 0; + ts: number = 0; + dur: number = 0; + startTime: number = 0; + endTime: number = 0; + tid: number = 0; + pid: number = 0; + cycleDur?: number = 0; + cycleStartTime?: number = 0; + funcName?: string = ''; + id?: number = 0; + thread?: string = ''; + process?: string = ''; + totalCount?: number = 0; + idx?: number = 0; +} \ No newline at end of file diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index 52a5a2be..96b78253 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -122,6 +122,8 @@ import { TabPaneFreqUsage } from '../sheet/frequsage/TabPaneFreqUsage'; import { TabPaneFreqDataCut } from '../sheet/frequsage/TabPaneFreqDataCut'; import { TabPaneHisysEvents } from '../sheet/hisysevent/TabPaneHisysEvents'; import { TabPaneHiSysEventSummary } from '../sheet/hisysevent/TabPaneHiSysEventSummary'; +import { TabPaneBinderDataCut } from '../sheet/binder/TabPaneBinderDataCut'; +import { TabPaneBinders } from '../sheet/binder/TabPaneBinders' export let tabConfig: any = { 'current-selection': { @@ -650,4 +652,14 @@ export let tabConfig: any = { type: TabPaneHiSysEventSummary, require: (param: SelectionParam) => param.hiSysEvents.length > 0, }, -}; + 'tabpane-binders': { + title: 'Thread Binders', + type: TabPaneBinders, + require: (param: SelectionParam) => param.threadIds.length > 0, + }, + 'tabpane-binder-datacut': { + title: 'Binder DataCut', + type: TabPaneBinderDataCut, + require: (param: SelectionParam) => param.threadIds.length > 0, + }, +}; \ No newline at end of file diff --git a/ide/src/trace/component/trace/base/Utils.ts b/ide/src/trace/component/trace/base/Utils.ts index 9efd0467..6ba38276 100644 --- a/ide/src/trace/component/trace/base/Utils.ts +++ b/ide/src/trace/component/trace/base/Utils.ts @@ -97,6 +97,20 @@ export class Utils { } } + public static transferBinderTitle(value: any) { + if (value.startsWith('P-')) { + let pid = value.replace('P-', ''); + let process = Utils.PROCESS_MAP.get(parseInt(pid)) || 'Process'; + return `${process} [${pid}]`; + } else if (value.startsWith('T-')) { + let tid = value.replace('T-', ''); + let thread = Utils.THREAD_MAP.get(parseInt(tid)) || 'Thread'; + return `${thread} [${tid}]`; + } else { + return ''; + } + } + public static getStateColor(state: string): string { if (state === 'D-NIO' || state === 'DK-NIO') { return '#795548'; diff --git a/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts b/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts new file mode 100644 index 00000000..6665fbd7 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts @@ -0,0 +1,773 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseElement, element } from '../../../../../base-ui/BaseElement'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; +import { Utils } from '../../base/Utils'; +import { SelectionParam } from '../../../../bean/BoxSelection'; +import { BinderItem, BinderGroup, DataSource, FuncNameCycle, BinderDataStruct } from '../../../../bean/BinderProcessThread'; +import { querySingleFuncNameCycle, queryBinderByThreadId, queryLoopFuncNameCycle } from '../../../../database/SqlLite'; +import { resizeObserver } from '../SheetUtils'; +import { LitChartColumn } from '../../../../../base-ui/chart/column/LitChartColumn'; +import '../../../../../base-ui/chart/column/LitChartColumn'; +// import { SpSegmentationChart } from '../../../chart/SpSegmentationChart'; + +@element('tabpane-binder-datacut') +export class TabPaneBinderDataCut extends BaseElement { + private threadBindersTbl: LitTable | null | undefined; + private currentSelectionParam: SelectionParam | any; + private threadStatesDIV: Element | null | undefined; + private cycleARangeArr: BinderGroup[] | undefined; + private cycleBRangeArr: BinderGroup[] | undefined; + private cycleAStartRangeDIV: HTMLInputElement | null | undefined; + private cycleAEndRangeDIV: HTMLInputElement | null | undefined; + private cycleBStartRangeDIV: HTMLInputElement | null | undefined; + private cycleBEndRangeDIV: HTMLInputElement | null | undefined; + private chartTotal: LitChartColumn | null | undefined; + private dataSource: DataSource[] | undefined; + private rowCycleData: BinderGroup[] | undefined; + private funcNameCycleArr: FuncNameCycle[] | undefined; + private cacheBinderArr: BinderGroup[] | undefined; + private currentThreadId: string | undefined; + + set data(threadStatesParam: SelectionParam | any) { + let threadIdDIV = this.shadowRoot!.querySelector('.thread-id-input') as HTMLElement; + threadIdDIV.style.border = '1px solid rgb(151,151,151)'; + let cycleNameDIV = this.shadowRoot!.querySelector('.cycle-name-input') as HTMLElement; + cycleNameDIV.style.border = '1px solid rgb(151,151,151)'; + if (this.currentSelectionParam === threadStatesParam) { + return; + } + this.dispalyQueryArea(true); + this.clickLoop(false); + this.clickSingle(false); + this.currentSelectionParam = threadStatesParam; + this.threadBindersTbl!.recycleDataSource = []; + this.theadClick(this.threadBindersTbl!.recycleDataSource); + } + + dispalyQueryArea(b: boolean) { + if (b) { + this.setAttribute('dispalyQueryArea', ''); + } else { + this.removeAttribute('dispalyQueryArea'); + } + } + + clickSingle(b: boolean) { + if (b) { + this.setAttribute('clickSingle', ''); + } else { + this.removeAttribute('clickSingle'); + } + } + + clickLoop(b: boolean) { + if (b) { + this.setAttribute('clickLoop', ''); + } else { + this.removeAttribute('clickLoop'); + } + } + + async dataLoopCut(threadId: HTMLInputElement, threadFunc: HTMLInputElement): Promise { + this.currentThreadId = ''; + let threadIds: number[] = this.currentSelectionParam.threadIds; + let processIds: number[] = this.currentSelectionParam.processIds; + let threadIdValue: string = threadId.value.trim(); + let threadFuncName: string = threadFunc.value.trim(); + let leftNS: number = this.currentSelectionParam.leftNs; + let rightNS: number = this.currentSelectionParam.rightNs; + if (threadIdValue !== '' && threadFuncName !== '') { + // SpSegmentationChart.setBinderChartData("BINDER", []); + this.clickLoop(true); + this.clickSingle(false); + this.threadBindersTbl!.loading = true; + threadId.style.border = '1px solid rgb(151,151,151)'; + threadFunc.style.border = '1px solid rgb(151,151,151)'; + this.funcNameCycleArr = await queryLoopFuncNameCycle(threadFuncName, threadIdValue, leftNS, rightNS); + let binderItemArr: BinderItem[] = await queryBinderByThreadId(processIds, threadIds, leftNS, rightNS); + if (this.funcNameCycleArr.length !== 0) { + let binderCutArr: BinderItem[] = []; + for (let j: number = 0; j < this.funcNameCycleArr.length - 1; j++) { + this.funcNameCycleArr[j].cycleDur = this.funcNameCycleArr[j + 1].cycleStartTime - this.funcNameCycleArr[j].cycleStartTime; + for (let i: number = 0; i < binderItemArr.length; i++) { + if (binderItemArr[i].ts > this.funcNameCycleArr[j].cycleStartTime + && binderItemArr[i].ts + binderItemArr[i].dur < this.funcNameCycleArr[j + 1].cycleStartTime) { + // calculate cycle duration + binderItemArr[i].cycleDur = this.funcNameCycleArr[j + 1].cycleStartTime - this.funcNameCycleArr[j].cycleStartTime; + binderItemArr[i].cycleStartTime = this.funcNameCycleArr[j].cycleStartTime; + binderItemArr[i].funcName = this.funcNameCycleArr[j].funcName; + binderItemArr[i].id = this.funcNameCycleArr[j].id; + binderItemArr[i].thread = Utils.THREAD_MAP.get(binderItemArr[i].tid) || 'Thread'; + binderItemArr[i].process = Utils.PROCESS_MAP.get(binderItemArr[i].pid) || 'Process'; + binderCutArr.push(binderItemArr[i]); + } + } + } + let finalBinderCutArr: BinderItem[] = this.completionCycleName(binderCutArr, 'loop'); + this.threadBindersTbl!.recycleDataSource = this.transferToTreeData(finalBinderCutArr); + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource); + } else { + this.threadBindersTbl!.recycleDataSource = []; + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource); + } + } else { + this.verifyInputIsEmpty(threadIdValue, threadFuncName, threadId, threadFunc); + } + } + + async dataSingleCut(threadId: HTMLInputElement, threadFunc: HTMLInputElement): Promise { + this.currentThreadId = ''; + let threadIds: number[] = this.currentSelectionParam.threadIds; + let processIds: number[] = this.currentSelectionParam.processIds; + let threadIdValue: string = threadId.value.trim(); + let threadFuncName: string = threadFunc.value.trim(); + let leftNS: number = this.currentSelectionParam.leftNs; + let rightNS: number = this.currentSelectionParam.rightNs; + if (threadIdValue !== '' && threadFuncName !== '') { + // SpSegmentationChart.setBinderChartData("BINDER", []); + this.clickLoop(false); + this.clickSingle(true); + threadId.style.border = '1px solid rgb(151,151,151)'; + threadFunc.style.border = '1px solid rgb(151,151,151)'; + this.threadBindersTbl!.loading = true; + this.funcNameCycleArr = await querySingleFuncNameCycle(threadFuncName, threadIdValue, leftNS, rightNS); + let binderItemArr: BinderItem[] = await queryBinderByThreadId(processIds, threadIds, leftNS, rightNS); + if (this.funcNameCycleArr.length !== 0) { + let binderCutArr: BinderItem[] = []; + for (let j: number = 0; j < this.funcNameCycleArr.length; j++) { + for (let i: number = 0; i < binderItemArr.length; i++) { + if (binderItemArr[i].ts > this.funcNameCycleArr[j].cycleStartTime + && binderItemArr[i].ts + binderItemArr[i].dur < this.funcNameCycleArr[j].cycleStartTime + this.funcNameCycleArr[j]!.cycleDur) { + binderItemArr[i].cycleDur = this.funcNameCycleArr[j].cycleDur; + binderItemArr[i].cycleStartTime = this.funcNameCycleArr[j].cycleStartTime; + binderItemArr[i].funcName = this.funcNameCycleArr[j].funcName; + binderItemArr[i].id = this.funcNameCycleArr[j].id; + binderItemArr[i].thread = Utils.THREAD_MAP.get(binderItemArr[i].tid) || 'Thread'; + binderItemArr[i].process = Utils.PROCESS_MAP.get(binderItemArr[i].pid) || 'Process'; + binderItemArr[i].count = 1; + binderCutArr.push(binderItemArr[i]); + } + } + } + let finalBinderCutArr: BinderItem[] = this.completionCycleName(binderCutArr, 'single'); + this.threadBindersTbl!.recycleDataSource = this.transferToTreeData(finalBinderCutArr); + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource); + } else { + this.threadBindersTbl!.recycleDataSource = []; + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource); + } + } else { + this.verifyInputIsEmpty(threadIdValue, threadFuncName, threadId, threadFunc); + } + } + + verifyInputIsEmpty(threadIdValue: string, threadFuncName: string, threadId: HTMLInputElement, threadFunc: HTMLInputElement): void { + if (threadIdValue === '') { + threadId.style.border = '1px solid rgb(255,0,0)'; + threadId.setAttribute('placeholder', 'Please input thread id'); + } else { + threadId.style.border = '1px solid rgb(151,151,151)'; + } + + if (threadFuncName === '') { + threadFunc.style.border = '1px solid rgb(255,0,0)'; + threadFunc.setAttribute('placeholder', 'Please input function name'); + } else { + threadFunc.style.border = '1px solid rgb(151,151,151)'; + } + } + + completionCycleName(binderCutArr: BinderItem[], type: string): BinderItem[] { + let threadIds: number[] = this.currentSelectionParam.threadIds; + let threadBinderCutArr: BinderItem[][] = []; + let childThreadbinderCutArr: BinderItem[] = []; + threadIds.forEach((tid: number) => { + childThreadbinderCutArr = []; + binderCutArr.forEach((binder: BinderItem) => { + if (binder.tid === tid) { + childThreadbinderCutArr.push(binder) + } + }) + if (childThreadbinderCutArr.length > 0) { + threadBinderCutArr.push(childThreadbinderCutArr); + } + }) + // loop data cut need delete last function Name cycle data + if (type === 'loop') { + this.funcNameCycleArr?.pop(); + } + let cloneThreadBinderCutArr: BinderItem[][] = JSON.parse(JSON.stringify(threadBinderCutArr)); + let threadBinderContainsFuncIdArr: number[] = []; + threadBinderCutArr.forEach((binderArr: BinderItem[], idx: number) => { + binderArr.forEach((binder: BinderItem) => { + if (!threadBinderContainsFuncIdArr.includes(binder.id!)) { + threadBinderContainsFuncIdArr.push(binder.id!); + } + }) + // When the cycle data is incomplete + if (this.funcNameCycleArr!.length !== threadBinderContainsFuncIdArr.length) { + this.completionAllFname(threadBinderContainsFuncIdArr, idx, cloneThreadBinderCutArr); + } + threadBinderContainsFuncIdArr = []; + }) + cloneThreadBinderCutArr.forEach((arr: BinderItem[]) => arr.sort(this.compare('id'))) + return cloneThreadBinderCutArr.flat(); + } + + completionAllFname(binderContainsFuncIdArr: number[], idx: number, cloneThreadBinderCutArr: BinderItem[][]): void { + this.funcNameCycleArr!.forEach((it: FuncNameCycle) => { + if (!binderContainsFuncIdArr.includes(it.id)) { + let itemData = cloneThreadBinderCutArr[idx][0]; + let item: BinderItem = { + title: '', + count: 0, + totalCount: 0, + cycleDur: it.cycleDur, + cycleStartTime: it.cycleStartTime, + id: it.id, + name: '', + pid: itemData.pid, + process: itemData.process!, + thread: itemData.thread!, + tid: itemData.tid, + idx: 0, + ts: 0, + dur: 0, + startTime: 0, + endTime: 0 + } + cloneThreadBinderCutArr[idx].push(item); + } + }) + } + + compare(prop: string) { + return function (obj1: any, obj2: any) { + let val1 = obj1[prop]; + let val2 = obj2[prop]; + if (val1 < val2) { + return -1; + } else if (val1 > val2) { + return 1; + } else { + return 0; + } + } + } + + transferToTreeData(binderList: Array): Array { + let group: any = {}; + binderList.forEach((it: BinderItem) => { + let cycleItem = { + title: it.thread + ' ' + '[' + it.tid + ']' + '[' + it.id + ']', + totalCount: it.count, + binderTransactionCount: it.name === 'binder transaction' ? it.count : 0, + binderAsyncRcvCount: it.name === 'binder async rcv' ? it.count : 0, + binderReplyCount: it.name === 'binder reply' ? it.count : 0, + binderTransactionAsyncCount: it.name === 'binder transaction async' ? it.count : 0, + tid: it.tid, + pid: it.pid, + thread: it.thread, + cycleDur: it.cycleDur || 0, + cycleStartTime: it.cycleStartTime, + type: 'cycle', + }; + if (group[`${it.pid}`]) { + let process = group[`${it.pid}`]; + process.totalCount += it.count; + let thread = process.children.find((child: BinderGroup) => child.title === it.thread + ' ' + '[' + it.tid + ']'); + if (thread) { + thread.totalCount += it.count; + let cycle = thread.children.find((child: BinderGroup) => child.title === it.thread + ' ' + '[' + it.tid + ']' + '[' + it.id + ']'); + if (cycle) { + cycle.totalCount += it.count; + cycle.binderTransactionCount += it.name === 'binder transaction' ? it.count : 0; + cycle.binderAsyncRcvCount += it.name === 'binder async rcv' ? it.count : 0; + cycle.binderReplyCount += it.name === 'binder reply' ? it.count : 0; + cycle.binderTransactionAsyncCount += it.name === 'binder transaction async' ? it.count : 0; + } else { + thread.children.push(cycleItem); + } + } else { + process.children.push({ + title: it.thread + ' ' + '[' + it.tid + ']', + totalCount: it.count, + tid: it.tid, + pid: it.pid, + type: 'thread', + children: [cycleItem], + }) + } + } else { + group[`${it.pid}`] = { + title: it.process + ' ' + '[' + it.pid + ']', + totalCount: it.count, + tid: it.tid, + pid: it.pid, + type: 'process', + children: [ + { + title: it.thread + ' ' + '[' + it.tid + ']', + totalCount: it.count, + tid: it.tid, + pid: it.pid, + type: 'thread', + children: [cycleItem], + } + ] + } + } + }); + this.cacheBinderArr = JSON.parse(JSON.stringify(this.addCycleNumber(Object.values(group)))); + let groupArr: Array = this.timeUnitConversion(Object.values(group)) + return groupArr; + } + + addCycleNumber(groupArr: Array): Array { + for (let i = 0; i < groupArr.length; i++) { + if (groupArr[i].type === 'cycle') { + groupArr[i].title = 'cycle ' + (i + 1) + '_' + groupArr[i].thread; + groupArr[i].idx = i + 1; + } else { + this.addCycleNumber(groupArr[i].children!) + } + } + return groupArr + } + + timeUnitConversion(groupArr: Array): Array { + for (let i = 0; i < groupArr.length; i++) { + if (groupArr[i].type === 'cycle') { + groupArr[i].cycleDur = Number((groupArr[i].cycleDur / 1000000).toFixed(3)); + groupArr[i].cycleStartTime = Number((groupArr[i].cycleStartTime / 1000000).toFixed(3)); + } else { + this.timeUnitConversion(groupArr[i].children!) + } + } + return groupArr + } + + private theadClick(data: Array): void { + let labels = this.threadBindersTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); + if (labels) { + for (let i = 0; i < labels.length; i++) { + let label = labels[i].innerHTML; + labels[i].addEventListener('click', (e) => { + if (label.includes('Process') && i === 0) { + this.threadBindersTbl!.setStatus(data, false); + this.threadBindersTbl!.recycleDs = this.threadBindersTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Thread') && i === 1) { + for (let item of data) { + item.status = true; + if (item.children != undefined && item.children.length > 0) { + this.threadBindersTbl!.setStatus(item.children, false); + } + } + this.threadBindersTbl!.recycleDs = this.threadBindersTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Cycle') && i === 2) { + this.threadBindersTbl!.setStatus(data, true); + this.threadBindersTbl!.recycleDs = this.threadBindersTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); + } + }); + } + } + } + + binderWithCountList(rowCycleData: BinderGroup[]): Array { + let binderWithCountList: Array = []; + rowCycleData.forEach(it => { + if (it.totalCount !== 0) { + let cycleDataArr: BinderDataStruct[] = []; + if (it.binderTransactionCount !== 0) { + cycleDataArr.push({ + name: 'binder transaction', + count: it.binderTransactionCount!, + dur: it.cycleDur, + startNS: it.cycleStartTime, + idx: it.idx + }) + } + if (it.binderTransactionAsyncCount !== 0) { + cycleDataArr.push({ + name: 'binder transaction async', + count: it.binderTransactionAsyncCount!, + dur: it.cycleDur, + startNS: it.cycleStartTime, + idx: it.idx + }) + } + if (it.binderReplyCount !== 0) { + cycleDataArr.push({ + name: 'binder reply', + count: it.binderReplyCount!, + dur: it.cycleDur, + startNS: it.cycleStartTime, + idx: it.idx + }) + } + if (it.binderAsyncRcvCount !== 0) { + cycleDataArr.push({ + name: 'binder async rcv', + count: it.binderAsyncRcvCount!, + dur: it.cycleDur, + startNS: it.cycleStartTime, + idx: it.idx + }) + } + binderWithCountList.push(cycleDataArr) + } + }) + return binderWithCountList; + } + + findThreadByThreadId(groupArr: Array, threadId: number): BinderGroup[] { + let currentSelectThread: BinderGroup[] = []; + groupArr.forEach(p => { + p.children?.forEach(th => { + if (th.tid === threadId) { + currentSelectThread = th.children! + } + }) + }) + return currentSelectThread + } + + initElements(): void { + this.threadBindersTbl = this.shadowRoot?.querySelector('#tb-binder-count'); + this.chartTotal = this.shadowRoot!.querySelector('#chart_cycle'); + this.cycleAStartRangeDIV = this.shadowRoot?.querySelector('#cycle-a-start-range'); + this.cycleAEndRangeDIV = this.shadowRoot?.querySelector('#cycle-a-end-range'); + this.cycleBStartRangeDIV = this.shadowRoot?.querySelector('#cycle-b-start-range'); + this.cycleBEndRangeDIV = this.shadowRoot?.querySelector('#cycle-b-end-range'); + + this.threadStatesDIV = this.shadowRoot!.querySelector('#dataCut'); + this.threadStatesDIV?.children[2].children[0].addEventListener('click', (e) => { + this.dispalyQueryArea(true); + this.dataSource = []; + // @ts-ignore + this.dataSingleCut(this.threadStatesDIV!.children[0], this.threadStatesDIV?.children[1]); + }) + this.threadStatesDIV?.children[2].children[1].addEventListener('click', (e) => { + this.dispalyQueryArea(true); + this.dataSource = []; + // @ts-ignore + this.dataLoopCut(this.threadStatesDIV?.children[0], this.threadStatesDIV?.children[1]); + }) + + this.threadBindersTbl!.addEventListener('row-click', (evt: any) => { + let currentData: BinderGroup = evt.detail.data; + if (currentData.type === 'thread') { + this.currentThreadId = currentData.tid + '' + currentData.pid; + this.clearCycleRange(); + currentData.isSelected = true; + this.threadBindersTbl!.clearAllSelection(currentData); + this.threadBindersTbl!.setCurrentSelection(currentData); + this.rowCycleData = currentData.children; + this.dispalyQueryArea(false); + let totalCount = currentData.totalCount; + this.dataSource = []; + this.dataSource.push({ + xName: 'Total', + yAverage: totalCount !== 0 ? Math.ceil(totalCount / this.rowCycleData!.length) : 0 + }) + if (this.dataSource!.length !== 0) { + this.drawColumn(); + } + let threaId = currentData.tid; + let rowThreadBinderArr = this.findThreadByThreadId(this.cacheBinderArr!, threaId); + let binderWithCountList: Array = this.binderWithCountList(rowThreadBinderArr!); + // SpSegmentationChart.setBinderChartData('BINDER', binderWithCountList); + } + + if (currentData.type === 'cycle' && currentData.tid + '' + currentData.pid === this.currentThreadId) { + currentData.isSelected = true; + this.threadBindersTbl!.clearAllSelection(currentData); + this.threadBindersTbl!.setCurrentSelection(currentData); + // SpSegmentationChart.tabHover('BINDER', true, currentData.idx); + } + }); + + this.shadowRoot?.querySelector('#query-btn')?.addEventListener('click', () => { + this.cycleARangeArr = this.rowCycleData?.filter((it: BinderGroup) => { + return it.cycleDur >= Number(this.cycleAStartRangeDIV!.value) + && it.cycleDur < Number(this.cycleAEndRangeDIV!.value); + }) + this.cycleBRangeArr = this.rowCycleData?.filter((it: BinderGroup) => { + return it.cycleDur >= Number(this.cycleBStartRangeDIV!.value) + && it.cycleDur < Number(this.cycleBEndRangeDIV!.value); + }) + let cycleACount: number = 0; + this.cycleARangeArr?.forEach((it: BinderGroup) => { + cycleACount += it.totalCount; + }) + let cycleBCount: number = 0; + this.cycleBRangeArr?.forEach((it: BinderGroup) => { + cycleBCount += it.totalCount; + }) + this.dataSource!.length > 1 && this.dataSource?.splice(1); + this.dataSource!.push({ + xName: 'cycleA', + yAverage: cycleACount !== 0 ? Math.ceil(cycleACount / this.cycleARangeArr!.length) : 0 + }) + this.dataSource!.push({ + xName: 'cycleB', + yAverage: cycleBCount !== 0 ? Math.ceil(cycleBCount / this.cycleBRangeArr!.length) : 0 + }) + if (this.dataSource!.length !== 0) { + this.drawColumn(); + } + }) + } + + clearCycleRange(): void { + this.cycleAStartRangeDIV!.value = ''; + this.cycleAEndRangeDIV!.value = ''; + this.cycleBStartRangeDIV!.value = ''; + this.cycleBEndRangeDIV!.value = ''; + } + + drawColumn(): void { + this.chartTotal!.dataSource = this.dataSource!; + this.chartTotal!.config = { + data: this.dataSource!, + appendPadding: 10, + xField: 'xName', + yField: 'yAverage', + seriesField: '', + removeUnit: true, + notSort: true, + color: (a) => { + if (a.xName === 'Total') { + return '#2f72f8'; + } else if (a.xName === 'cycleA') { + return '#ffab67'; + } else if (a.xName === 'cycleB') { + return '#a285d2'; + } else { + return '#0a59f7'; + } + }, + tip: (a) => { + if (a && a[0]) { + let tip: string = ''; + tip = `
+
Average count: ${a[0].obj.yAverage}
+
`; + return tip; + } else { + return ''; + } + }, + label: null, + }; + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.threadBindersTbl!); + } + + initHtml(): string { + return ` + +
+ + +
+ + +
+
+
+ +
+ + + + + + + + + + + + + + + + + + +
+ +
+
+
+ Cycle A: + + ~ + +
+
+
+ Cycle B: + + ~ + +
+
+ +
+
+
+
+
Average Binder Count
+ +
+
Total
+
CycleA
+
CycleB
+
+
+
+
+
+ ` + } +} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts b/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts new file mode 100644 index 00000000..2e11dc85 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseElement, element } from '../../../../../base-ui/BaseElement'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; +import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; +import '../../../StackBar'; +import { getTabRunningPercent, queryCpuFreqUsageData, queryCpuFreqFilterId, queryBinderByThreadId } from '../../../../database/SqlLite'; +import { Utils } from '../../base/Utils'; +import { resizeObserver } from '../SheetUtils'; +import { SliceGroup } from '../../../../bean/StateProcessThread'; +import { BinderGroup, BinderItem } from '../../../../bean/BinderProcessThread'; + +@element('tabpane-binders') +export class TabPaneBinders extends BaseElement { + private threadBindersTbl: LitTable | null | undefined; + private threadStatesTblSource: Array = []; + private currentSelectionParam: Selection | undefined; + + set data(threadStatesParam: SelectionParam | any) { + if (this.currentSelectionParam === threadStatesParam) { + return; + } + this.threadBindersTbl!.loading = true; + this.currentSelectionParam = threadStatesParam; + this.threadStatesTblSource = []; + this.threadBindersTbl!.recycleDataSource = []; + this.initBinderData(threadStatesParam); + } + + initBinderData(threadStatesParam: SelectionParam): void { + this.threadBindersTbl!.recycleDataSource = []; + let binderList: BinderItem[] = []; + let threadIds = threadStatesParam.threadIds; + let processIds: number[] = [...new Set(threadStatesParam.processIds)]; + queryBinderByThreadId(processIds, threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs).then((result) => { + if (result !== null && result.length > 0 && result[0].count !== 0) { + binderList = result; + } + if (binderList.length > 0) { + this.threadBindersTbl!.recycleDataSource = this.transferToTreeData(binderList); + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource); + } else if (binderList.length === 0) { + this.threadBindersTbl!.recycleDataSource = []; + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource); + } + }) + } + + initElements(): void { + this.threadBindersTbl = this.shadowRoot?.querySelector('#tb-binder-count'); + this.threadBindersTbl!.itemTextHandleMap.set('title', Utils.transferBinderTitle); + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.threadBindersTbl!); + } + + transferToTreeData(binderList: BinderItem[]): BinderGroup[] { + let group: any = {}; + binderList.forEach((it: BinderItem) => { + if (group[`${it.pid}`]) { + let process = group[`${it.pid}`]; + process.totalCount += it.count; + let thread = process.children.find((child: BinderGroup) => child.title === `T-${it.tid}`); + if (thread) { + thread.totalCount += it.count; + thread.binderTransactionCount += it.name == 'binder transaction' ? it.count : 0; + thread.binderAsyncRcvCount += it.name == 'binder async rcv' ? it.count : 0; + thread.binderReplyCount += it.name == 'binder reply' ? it.count : 0; + thread.binderTransactionAsyncCount += it.name == 'binder transaction async' ? it.count : 0; + } else { + process.children.push({ + title: `T-${it.tid}`, + totalCount: it.count, + binderTransactionCount: it.name == 'binder transaction' ? it.count : 0, + binderAsyncRcvCount: it.name == 'binder async rcv' ? it.count : 0, + binderReplyCount: it.name == 'binder reply' ? it.count : 0, + binderTransactionAsyncCount: it.name == 'binder transaction async' ? it.count : 0, + tid: it.tid, + pid: it.pid + }) + } + } else { + group[`${it.pid}`] = { + title: `P-${it.pid}`, + totalCount: it.count, + tid: it.tid, + pid: it.pid, + children: [ + { + title: `T-${it.tid}`, + totalCount: it.count, + binderTransactionCount: it.name == 'binder transaction' ? it.count : 0, + binderAsyncRcvCount: it.name == 'binder async rcv' ? it.count : 0, + binderReplyCount: it.name == 'binder reply' ? it.count : 0, + binderTransactionAsyncCount: it.name == 'binder transaction async' ? it.count : 0, + tid: it.tid, + pid: it.pid, + } + ] + } + } + }); + return Object.values(group); + } + + private theadClick(data: Array): void { + let labels = this.threadBindersTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); + if (labels) { + for (let i = 0; i < labels.length; i++) { + let label = labels[i].innerHTML; + labels[i].addEventListener('click', (e) => { + if (label.includes('Process') && i === 0) { + this.threadBindersTbl!.setStatus(data, false); + this.threadBindersTbl!.recycleDs = this.threadBindersTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Thread') && i === 1) { + for (let item of data) { + item.status = true; + if (item.children != undefined && item.children.length > 0) { + this.threadBindersTbl!.setStatus(item.children, false); + } + } + this.threadBindersTbl!.recycleDs = this.threadBindersTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } + }); + } + } + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + ` + } + +} diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts index 28c4e6a7..674b8e02 100644 --- a/ide/src/trace/database/SqlLite.ts +++ b/ide/src/trace/database/SqlLite.ts @@ -83,6 +83,7 @@ import { type MemoryConfig } from '../bean/MemoryConfig'; import { LogStruct } from './ui-worker/ProcedureWorkerLog'; import { HiSysEventStruct } from './ui-worker/ProcedureWorkerHiSysEvent'; import { KeyPathStruct } from '../bean/KeyPathStruct'; +import { FuncNameCycle, BinderItem } from '../bean/BinderProcessThread'; class DataWorkerThread { taskMap: any = {}; @@ -1406,8 +1407,7 @@ export const queryVirtualMemory = (): Promise> => export const queryVirtualMemoryData = (filterId: number): Promise> => query( 'queryVirtualMemoryData', - `select ts-${ - (window as any).recordStartNS + `select ts-${(window as any).recordStartNS } as startTime,value,filter_id as filterID from sys_mem_measure where filter_id=$filter_id`, { $filter_id: filterId } ); @@ -4050,11 +4050,9 @@ export const queryEbpfSamplesCount = (startTime: number, endTime: number, ipids: select fsCount, vmCount from -(select count(1) as fsCount from file_system_sample s,trace_range t where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ - ipids.length > 0 ? `and s.ipid in (${ipids.join(',')})` : '' +(select count(1) as fsCount from file_system_sample s,trace_range t where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ipids.length > 0 ? `and s.ipid in (${ipids.join(',')})` : '' }) -,(select count(1) as vmCount from paged_memory_sample s,trace_range t where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ - ipids.length > 0 ? `and s.ipid in (${ipids.join(',')})` : '' +,(select count(1) as vmCount from paged_memory_sample s,trace_range t where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ipids.length > 0 ? `and s.ipid in (${ipids.join(',')})` : '' }); `, { $startTime: startTime, $endTime: endTime } @@ -5887,3 +5885,166 @@ export const queryCpuKeyPathData = (threads: Array): Promise> => + query( + 'getTabBindersCount', + ` + SELECT + c.name, + c.dur, + 1 AS count, + c.ts, + c.ts - r.start_ts AS startTime, + c.ts -r.start_ts + c.dur AS endTime, + t.tid, + p.pid + FROM + callstack c, trace_range r + LEFT JOIN + thread t + ON + c.callid = t.id + LEFT JOIN + process p + ON + t.ipid = p.id + WHERE + c.name in ('binder transaction', 'binder async rcv', 'binder reply', 'binder transaction async') + AND + t.tid in (${tIds.join(',')}) + AND + p.pid in (${pIds.join(',')}) + AND NOT + ((startTime < ${leftNS}) + OR + (endTime > ${rightNS})); + `, + { + $pIds: pIds, + $tIds: tIds, + $leftNS: leftNS, + $rightNS: rightNS + } + ); + +export const queryBinderByThreadId = (pIds: number[], tIds: Array, leftNS: number, rightNS: number): Promise> => + query( + 'queryBinderByThreadId', + ` + SELECT + c.name, + 1 AS count, + c.ts - r.start_ts AS ts, + c.dur, + c.ts - r.start_ts AS startTime, + c.ts - r.start_ts + c.dur AS endTime, + t.tid, + p.pid + FROM + callstack c, trace_range r + LEFT JOIN + thread t + ON + c.callid = t.id + LEFT JOIN + process p + ON + t.ipid = p.id + WHERE + c.name in ('binder transaction', 'binder async rcv', 'binder reply', 'binder transaction async') + AND + t.tid in (${tIds.join(',')}) + AND + p.pid in (${pIds.join(',')}) + AND NOT + ((startTime < ${leftNS}) + OR + (endTime > ${rightNS})) + `, + { + $pIds: pIds, + $tIds: tIds, + $leftNS: leftNS, + $rightNS: rightNS + } + ); + + +export const querySingleFuncNameCycle = (funcName: string, tIds: string, leftNS: number, rightNS: number): Promise> => + query( + 'querySingleFuncNameCycle', + ` + SELECT + c.name AS funcName, + c.ts - r.start_ts AS cycleStartTime, + c.dur AS cycleDur, + c.id, + t.tid, + p.pid, + c.ts - r.start_ts + c.dur AS endTime + FROM + callstack c, trace_range r + LEFT JOIN + thread t + ON + c.callid = t.id + LEFT JOIN + process p + ON + t.ipid = p.id + WHERE + c.name = '${funcName}' + AND + t.tid = ${tIds} + AND NOT + ((cycleStartTime < ${leftNS}) + OR + (endTime > ${rightNS})) + `, + { + $funcName: funcName, + $tIds: tIds, + $leftNS: leftNS, + $rightNS: rightNS + } + ); + +export const queryLoopFuncNameCycle = (funcName: string, tIds: string, leftNS: number, rightNS: number): Promise> => + query( + 'queryLoopFuncNameCycle', + ` + SELECT + c.name AS funcName, + c.ts - r.start_ts AS cycleStartTime, + 0 AS cycleDur, + c.id, + t.tid, + p.pid + FROM + callstack c, trace_range r + LEFT JOIN + thread t + ON + c.callid = t.id + LEFT JOIN + process p + ON + t.ipid = p.id + WHERE + c.name = '${funcName}' + AND + t.tid = ${tIds} + AND NOT + ((cycleStartTime < ${leftNS}) + OR + (cycleStartTime > ${rightNS})) + `, + { + $funcName: funcName, + $tIds: tIds, + $leftNS: leftNS, + $rightNS: rightNS + } + ); + -- Gitee From a7844d8ac21a9023359dfdd114b6aa0ac8e2ad47 Mon Sep 17 00:00:00 2001 From: "wupoli3@huawei.com" Date: Fri, 15 Dec 2023 15:24:49 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=90=8C=E6=AD=A5binder=E5=92=8C=E5=BC=82?= =?UTF-8?q?=E6=AD=A5binder=E6=95=B0=E7=BB=9F=E8=AE=A1=EF=BC=8C=E7=BB=98?= =?UTF-8?q?=E5=88=B6=E6=9F=B1=E7=8A=B6=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wupoli3@huawei.com --- .../sheet/binder/TabPaneBinderDataCut.ts | 26 ++++++++----- .../trace/sheet/binder/TabPaneBinders.ts | 39 ++++++++++--------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts b/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts index 6665fbd7..095422e6 100644 --- a/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts +++ b/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts @@ -58,7 +58,7 @@ export class TabPaneBinderDataCut extends BaseElement { this.theadClick(this.threadBindersTbl!.recycleDataSource); } - dispalyQueryArea(b: boolean) { + dispalyQueryArea(b: boolean): void { if (b) { this.setAttribute('dispalyQueryArea', ''); } else { @@ -66,7 +66,7 @@ export class TabPaneBinderDataCut extends BaseElement { } } - clickSingle(b: boolean) { + clickSingle(b: boolean): void { if (b) { this.setAttribute('clickSingle', ''); } else { @@ -74,7 +74,7 @@ export class TabPaneBinderDataCut extends BaseElement { } } - clickLoop(b: boolean) { + clickLoop(b: boolean): void { if (b) { this.setAttribute('clickLoop', ''); } else { @@ -85,7 +85,8 @@ export class TabPaneBinderDataCut extends BaseElement { async dataLoopCut(threadId: HTMLInputElement, threadFunc: HTMLInputElement): Promise { this.currentThreadId = ''; let threadIds: number[] = this.currentSelectionParam.threadIds; - let processIds: number[] = this.currentSelectionParam.processIds; + //@ts-ignore + let processIds: number[] = [...new Set(this.currentSelectionParam.processIds)]; let threadIdValue: string = threadId.value.trim(); let threadFuncName: string = threadFunc.value.trim(); let leftNS: number = this.currentSelectionParam.leftNs; @@ -134,7 +135,8 @@ export class TabPaneBinderDataCut extends BaseElement { async dataSingleCut(threadId: HTMLInputElement, threadFunc: HTMLInputElement): Promise { this.currentThreadId = ''; let threadIds: number[] = this.currentSelectionParam.threadIds; - let processIds: number[] = this.currentSelectionParam.processIds; + //@ts-ignore + let processIds: number[] = [...new Set(this.currentSelectionParam.processIds)]; let threadIdValue: string = threadId.value.trim(); let threadFuncName: string = threadFunc.value.trim(); let leftNS: number = this.currentSelectionParam.leftNs; @@ -183,6 +185,9 @@ export class TabPaneBinderDataCut extends BaseElement { if (threadIdValue === '') { threadId.style.border = '1px solid rgb(255,0,0)'; threadId.setAttribute('placeholder', 'Please input thread id'); + this.threadBindersTbl!.recycleDataSource = []; + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource); } else { threadId.style.border = '1px solid rgb(151,151,151)'; } @@ -190,6 +195,9 @@ export class TabPaneBinderDataCut extends BaseElement { if (threadFuncName === '') { threadFunc.style.border = '1px solid rgb(255,0,0)'; threadFunc.setAttribute('placeholder', 'Please input function name'); + this.threadBindersTbl!.recycleDataSource = []; + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource); } else { threadFunc.style.border = '1px solid rgb(151,151,151)'; } @@ -440,8 +448,8 @@ export class TabPaneBinderDataCut extends BaseElement { findThreadByThreadId(groupArr: Array, threadId: number): BinderGroup[] { let currentSelectThread: BinderGroup[] = []; - groupArr.forEach(p => { - p.children?.forEach(th => { + groupArr.forEach((p: BinderGroup) => { + p.children?.forEach((th: BinderGroup) => { if (th.tid === threadId) { currentSelectThread = th.children! } @@ -486,9 +494,9 @@ export class TabPaneBinderDataCut extends BaseElement { this.dataSource = []; this.dataSource.push({ xName: 'Total', - yAverage: totalCount !== 0 ? Math.ceil(totalCount / this.rowCycleData!.length) : 0 + yAverage: totalCount > 0 ? Math.ceil(totalCount / this.rowCycleData!.length) : 0 }) - if (this.dataSource!.length !== 0) { + if (this.dataSource!.length > 0) { this.drawColumn(); } let threaId = currentData.tid; diff --git a/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts b/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts index 2e11dc85..8883ed43 100644 --- a/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts +++ b/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts @@ -17,16 +17,15 @@ import { BaseElement, element } from '../../../../../base-ui/BaseElement'; import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; import '../../../StackBar'; -import { getTabRunningPercent, queryCpuFreqUsageData, queryCpuFreqFilterId, queryBinderByThreadId } from '../../../../database/SqlLite'; +import { queryBinderByThreadId } from '../../../../database/SqlLite'; import { Utils } from '../../base/Utils'; import { resizeObserver } from '../SheetUtils'; -import { SliceGroup } from '../../../../bean/StateProcessThread'; import { BinderGroup, BinderItem } from '../../../../bean/BinderProcessThread'; @element('tabpane-binders') export class TabPaneBinders extends BaseElement { private threadBindersTbl: LitTable | null | undefined; - private threadStatesTblSource: Array = []; + private threadBindersTblSource: Array = []; private currentSelectionParam: Selection | undefined; set data(threadStatesParam: SelectionParam | any) { @@ -35,26 +34,28 @@ export class TabPaneBinders extends BaseElement { } this.threadBindersTbl!.loading = true; this.currentSelectionParam = threadStatesParam; - this.threadStatesTblSource = []; + this.threadBindersTblSource = []; this.threadBindersTbl!.recycleDataSource = []; this.initBinderData(threadStatesParam); } - + initBinderData(threadStatesParam: SelectionParam): void { this.threadBindersTbl!.recycleDataSource = []; let binderList: BinderItem[] = []; let threadIds = threadStatesParam.threadIds; let processIds: number[] = [...new Set(threadStatesParam.processIds)]; queryBinderByThreadId(processIds, threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs).then((result) => { - if (result !== null && result.length > 0 && result[0].count !== 0) { + if (result !== null && result.length > 0) { binderList = result; } if (binderList.length > 0) { this.threadBindersTbl!.recycleDataSource = this.transferToTreeData(binderList); + this.threadBindersTblSource = this.threadBindersTbl!.recycleDataSource; this.threadBindersTbl!.loading = false; this.theadClick(this.threadBindersTbl!.recycleDataSource); } else if (binderList.length === 0) { this.threadBindersTbl!.recycleDataSource = []; + this.threadBindersTblSource = []; this.threadBindersTbl!.loading = false; this.theadClick(this.threadBindersTbl!.recycleDataSource); } @@ -80,18 +81,18 @@ export class TabPaneBinders extends BaseElement { let thread = process.children.find((child: BinderGroup) => child.title === `T-${it.tid}`); if (thread) { thread.totalCount += it.count; - thread.binderTransactionCount += it.name == 'binder transaction' ? it.count : 0; - thread.binderAsyncRcvCount += it.name == 'binder async rcv' ? it.count : 0; - thread.binderReplyCount += it.name == 'binder reply' ? it.count : 0; - thread.binderTransactionAsyncCount += it.name == 'binder transaction async' ? it.count : 0; + thread.binderTransactionCount += it.name === 'binder transaction' ? it.count : 0; + thread.binderAsyncRcvCount += it.name === 'binder async rcv' ? it.count : 0; + thread.binderReplyCount += it.name === 'binder reply' ? it.count : 0; + thread.binderTransactionAsyncCount += it.name === 'binder transaction async' ? it.count : 0; } else { process.children.push({ title: `T-${it.tid}`, totalCount: it.count, - binderTransactionCount: it.name == 'binder transaction' ? it.count : 0, - binderAsyncRcvCount: it.name == 'binder async rcv' ? it.count : 0, - binderReplyCount: it.name == 'binder reply' ? it.count : 0, - binderTransactionAsyncCount: it.name == 'binder transaction async' ? it.count : 0, + binderTransactionCount: it.name === 'binder transaction' ? it.count : 0, + binderAsyncRcvCount: it.name === 'binder async rcv' ? it.count : 0, + binderReplyCount: it.name === 'binder reply' ? it.count : 0, + binderTransactionAsyncCount: it.name === 'binder transaction async' ? it.count : 0, tid: it.tid, pid: it.pid }) @@ -106,10 +107,10 @@ export class TabPaneBinders extends BaseElement { { title: `T-${it.tid}`, totalCount: it.count, - binderTransactionCount: it.name == 'binder transaction' ? it.count : 0, - binderAsyncRcvCount: it.name == 'binder async rcv' ? it.count : 0, - binderReplyCount: it.name == 'binder reply' ? it.count : 0, - binderTransactionAsyncCount: it.name == 'binder transaction async' ? it.count : 0, + binderTransactionCount: it.name === 'binder transaction' ? it.count : 0, + binderAsyncRcvCount: it.name === 'binder async rcv' ? it.count : 0, + binderReplyCount: it.name === 'binder reply' ? it.count : 0, + binderTransactionAsyncCount: it.name === 'binder transaction async' ? it.count : 0, tid: it.tid, pid: it.pid, } @@ -132,7 +133,7 @@ export class TabPaneBinders extends BaseElement { } else if (label.includes('Thread') && i === 1) { for (let item of data) { item.status = true; - if (item.children != undefined && item.children.length > 0) { + if (item.children !== undefined && item.children.length > 0) { this.threadBindersTbl!.setStatus(item.children, false); } } -- Gitee