diff --git a/ide/src/trace/bean/SchedSwitchStruet.ts b/ide/src/trace/bean/SchedSwitchStruet.ts new file mode 100644 index 0000000000000000000000000000000000000000..4f27423b1c477cc00ebebada319813a087950c30 --- /dev/null +++ b/ide/src/trace/bean/SchedSwitchStruet.ts @@ -0,0 +1,51 @@ +/* + * 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 { AnyAaaaRecord } from "dns"; + +export class SchedSwitchStack { + count: number = 0; + cycleNum: number = 1; + duration: number | any; + isHover: boolean = false; + isSelected: boolean = false; + cycle: number = 0; + level: string = ''; + pid: number = -1; + process: string = ''; + state: string = ''; + status: boolean = false; + thread: string = ''; + tid: number = -1; + title: string = ''; + ts: string = ''; + cycleStartTime: number | any; + children: Array = []; +} +export class schedThreadInitData { + cycleEndTime: number = 0; + cycleStartTime: number = 0; + funId: number = 0; + name: string = '' + pid: number = -1; + runningCnt: number = 0; + state: string = ''; + tid: number = -1; + process: string = ''; + thread: string = ''; + dur: number = 0; + leftNS: number = 0 +} + diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index 3bfbb6853aba3d1137c94f77051c71eefa64e18d..dd7810ba89e91f0526035f2cba60f7dc8273d6fc 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -122,6 +122,7 @@ import { TabPaneFreqUsage } from '../sheet/frequsage/TabPaneFreqUsage.js'; import { TabPaneFreqDataCut } from '../sheet/frequsage/TabPaneFreqDataCut.js'; import { TabPaneHisysEvents } from '../sheet/hisysevent/TabPaneHisysEvents.js'; import { TabPaneHiSysEventSummary } from '../sheet/hisysevent/TabPaneHiSysEventSummary.js'; +import {TabPaneSchedSwitch} from '../sheet/schedswitch/TabPaneSchedSwitch.js'; import { TabPaneThreadBinders } from '../sheet/binder/TabPaneThreadBinders.js'; import { TabPaneBinderDataCut } from '../sheet/binder/TabPaneBinderDataCut.js'; import {TabPaneGpufreq} from '../sheet/gpufreq/tabPaneGpufreqUsage.js' @@ -654,6 +655,10 @@ export let tabConfig: any = { type: TabPaneHiSysEventSummary, require: (param: SelectionParam) => param.hiSysEvents.length > 0, }, + 'tabpane-schedswitch': { + title: 'Sched Switch', + type: TabPaneSchedSwitch, + require: (param: SelectionParam) => param.threadIds.length > 0, 'tabpane-Thrbinders': { title: 'Thread Binders', type: TabPaneThreadBinders, diff --git a/ide/src/trace/component/trace/sheet/schedswitch/TabPaneSchedSwitch.ts b/ide/src/trace/component/trace/sheet/schedswitch/TabPaneSchedSwitch.ts new file mode 100644 index 0000000000000000000000000000000000000000..6436ad996c608d7b76e53ea90a36907d2a745d9f --- /dev/null +++ b/ide/src/trace/component/trace/sheet/schedswitch/TabPaneSchedSwitch.ts @@ -0,0 +1,736 @@ +/* + * 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 { log } from 'console'; +import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; +import { LitButton } from '../../../../../base-ui/button/LitButton.js'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table.js'; +import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; +import { querySchedThreadStates, querySingleCutData, queryLoopCutData } from '../../../../database/SqlLite.js'; +import { Utils } from '../../base/Utils.js'; +import { resizeObserver } from '../SheetUtils.js'; +import { LitChartColumn } from '../../../../../base-ui/chart/column/LitChartColumn.js'; +import { TableNoData } from '../../../schedulingAnalysis/TableNoData.js'; +import { getProbablyTime } from '../../../../database/logic-worker/ProcedureLogicWorkerCommon.js'; +import { SchedSwitchStack, schedThreadInitData } from '../../../../bean/SchedSwitchStruet.js'; +import { SegMenTaTion } from '../../../../../trace/component/chart/SpSegmentationChart.js' + + +@element('tabpane-schedswitch') +export class TabPaneSchedSwitch extends BaseElement { + private schedSwitchTbl: LitTable | null | undefined; + private threadQueryDIV: Element | null | undefined; + private rightDIV: HTMLDivElement | null | undefined; + private threadIdInput: HTMLInputElement | null | undefined; + private funcNameInput: HTMLInputElement | null | undefined; + private singleBtn: LitButton | null | undefined; + private loopBtn: LitButton | null | undefined; + private cycleALeftInput: HTMLInputElement | null | undefined; + private cycleARightInput: HTMLInputElement | null | undefined; + private cycleBLeftInput: HTMLInputElement | null | undefined; + private cycleBRightInput: HTMLInputElement | null | undefined; + private queryButton: LitButton | null | undefined; + private threadFlag: string = ''; + private selectionParam: SelectionParam | undefined; + private canvansName: HTMLDivElement | null | undefined; + private singleSourceData: Array = []; + private loopSourceData: Array = []; + private chartTotal: LitChartColumn | null | undefined; + private histogramSource: Array = []; + private rangeA: object = {}; + private rangeB: object = {}; + private rangeTotal: object = {}; + private clickThreadChildren: Array = []; + private isThreadStatesData: boolean = false; + private clickHighlightCondition: string = ''; + + + set data(threadStatesParam: SelectionParam | any) { + if (this.selectionParam === threadStatesParam) return; + let tblVal: any = this.schedSwitchTbl; + let threadIdInput: any = this.threadIdInput; + let funcNameInput: any = this.funcNameInput; + this.schedSwitchTbl!.recycleDataSource = []; + this.queryButton!.style.pointerEvents = 'none'; + this.schedSwitchTbl!.loading = false; + this.isThreadStatesData = false; + tblVal.value = []; + threadIdInput.value = ''; + funcNameInput.value = ''; + funcNameInput.style.border = '1px solid rgb(151,151,151)'; + threadIdInput.style.border = '1px solid rgb(151,151,151)'; + this.selectionParam = threadStatesParam; + this.canvansName!.textContent = 'sched switch平均分布图'; + this.isQueryButtonClick(false); + this.isSingleButtonFn(false); + this.isLoopButtonFn(false); + this.isCanvansDisplayFn(false); + } + initElements(): void { + this.schedSwitchTbl = this.shadowRoot!.querySelector('#tb-running'); + this.threadQueryDIV = this.shadowRoot?.querySelector('#data-cut'); + this.rightDIV = this.shadowRoot?.querySelector('#right'); + this.canvansName = this.shadowRoot!.querySelector('.sched-subheading'); + this.chartTotal = this.shadowRoot!.querySelector('#chart_total'); + this.threadIdInput = this.shadowRoot?.getElementById('cut-threadid') as HTMLInputElement; + this.funcNameInput = this.shadowRoot?.querySelector('#cut-thread-func') as HTMLInputElement; + this.singleBtn = this.shadowRoot?.querySelector('.single-btn'); + this.loopBtn = this.shadowRoot?.querySelector('.loop-btn'); + this.cycleALeftInput = this.shadowRoot?.getElementById('leftA') as HTMLInputElement; + this.cycleARightInput = this.shadowRoot?.getElementById('rightA') as HTMLInputElement; + this.cycleBLeftInput = this.shadowRoot?.getElementById('leftB') as HTMLInputElement; + this.cycleBRightInput = this.shadowRoot?.getElementById('rightB') as HTMLInputElement; + this.queryButton = this.shadowRoot?.querySelector('.query-btn'); + this.singleBtn?.addEventListener('click', (e) => { this.queryCutInfoFn(this.singleBtn!.innerHTML) }); + this.loopBtn?.addEventListener('click', (e) => { this.queryCutInfoFn(this.loopBtn!.innerHTML) }); + this.queryButton!.addEventListener('click', (e) => { this.queryCycleRangeData() }); + this.schedSwitchTbl!.addEventListener('row-click', (evt: any) => { + let data = evt.detail.data as SchedSwitchStack; + if (data.level == 'process') { + this.isCanvansDisplayFn(false); + this.threadFlag = ''; + } else if (data.level == 'thread') { + this.cycleALeftInput!.value = ''; + this.cycleARightInput!.value = ''; + this.cycleBLeftInput!.value = ''; + this.cycleBRightInput!.value = ''; + this.histogramSource = []; + this.clickThreadChildren = data.children; + this.queryButton!.style.pointerEvents = 'none'; + this.isCanvansDisplayFn(true); + this.isQueryButtonClick(false); + this.threadFlag = 'thread'; + this.clickHighlightCondition = `${data.process} - ${data.pid} - ${data.thread} - ${data.tid}`; + this.rangeTotal = { + count: evt.detail.count, + cycleNum: evt.detail.cycleNum, + average: evt.detail.cycleNum ? Math.ceil(evt.detail.count / evt.detail.cycleNum) : 0, + size: 'Total', + isHover: false, + color: '#2f72f8' + }; + this.histogramSource.push(this.rangeTotal); + data.isSelected = true; + this.schedSwitchTbl!.clearAllSelection(data); + this.schedSwitchTbl!.setCurrentSelection(data); + // SegMenTaTion.setChartData('SCHED-SWITCH', evt.detail.children); + this.queryHistogramData() + } else if (data.level == 'cycle') { + if (this.threadFlag == 'thread') { + this.isCanvansDisplayFn(true); + } + if (this.clickHighlightCondition == `${data.process} - ${data.pid} - ${data.thread} - ${data.tid}`) { + data.isSelected = true; + this.schedSwitchTbl!.clearAllSelection(data); + this.schedSwitchTbl!.setCurrentSelection(data); + // SegMenTaTion.tabHover('SCHED-SWITCH', true, data!.cycle); + } + } + }) + this.cycleALeftInput!.addEventListener('input', (evt: any) => { + this.checkInputRangeFn(this.cycleALeftInput, this.cycleARightInput, this.cycleBLeftInput, this.cycleBRightInput, this.cycleALeftInput!.value, this.cycleARightInput!.value) + }) + this.cycleARightInput!.addEventListener('input', (evt: any) => { + this.checkInputRangeFn(this.cycleARightInput, this.cycleALeftInput, this.cycleBLeftInput, this.cycleBRightInput, this.cycleALeftInput!.value, this.cycleARightInput!.value) + }) + this.cycleBLeftInput!.addEventListener('input', (evt: any) => { + this.checkInputRangeFn(this.cycleBLeftInput, this.cycleBRightInput, this.cycleALeftInput, this.cycleARightInput, this.cycleBLeftInput!.value, this.cycleBRightInput!.value) + }) + this.cycleBRightInput!.addEventListener('input', (evt: any) => { + this.checkInputRangeFn(this.cycleBRightInput, this.cycleBLeftInput, this.cycleALeftInput, this.cycleARightInput, this.cycleBLeftInput!.value, this.cycleBRightInput!.value) + }) + } + + checkInputRangeFn(firstInput: any, secondInput: any, thirdInput: any, fourInput: any, lVal: string, rVal: string): void { + let leftVal = Number(lVal); + let rightVal = Number(rVal); + if (firstInput!.value != '' && secondInput!.value != '') { + if (firstInput!.value != '' && secondInput!.value != '') { + if (leftVal >= rightVal) { + firstInput!.style.color = 'red'; + this.queryButton!.style.pointerEvents = 'none'; + this.isQueryButtonClick(false); + } else if (leftVal < rightVal) { + firstInput!.style.color = 'black'; + secondInput!.style.color = 'black'; + this.queryButton!.style.pointerEvents = 'auto'; + this.isQueryButtonClick(true); + } + } + } else if ((firstInput.value == '' && secondInput!.value != '') || (firstInput!.value != '' && secondInput!.value == '')) { + this.queryButton!.style.pointerEvents = 'none'; + this.isQueryButtonClick(false); + } else if (firstInput!.value == '' && secondInput!.value == '' && thirdInput!.value != '' && fourInput!.value != '') { + this.queryButton!.style.pointerEvents = 'auto'; + this.isQueryButtonClick(true); + } + } + + async initThreadStateData(threadParam: SelectionParam | null | undefined): Promise { + let leftStartNs = threadParam!.leftNs + threadParam!.recordStartNs; + let rightEndNs = threadParam!.rightNs + threadParam!.recordStartNs; + let res = await querySchedThreadStates(threadParam!.threadIds, leftStartNs, rightEndNs); + if (res.length == 0) { + this.schedSwitchTbl!.recycleDataSource = []; + this.schedSwitchTbl!.loading = false; + this.clickTreeTitleFn(this.schedSwitchTbl!.recycleDataSource); + return + } + this.singleSourceData = JSON.parse(JSON.stringify(res)); + this.loopSourceData = JSON.parse(JSON.stringify(res)); + this.isThreadStatesData = true; + } + + async queryCutInfoFn(btnHtml: string): Promise { + let threadId = this.threadIdInput!.value.trim(); + let threadFunName = this.funcNameInput!.value.trim(); + let leftStartNs = this.selectionParam!.leftNs + this.selectionParam!.recordStartNs; + let rightEndNs = this.selectionParam!.rightNs + this.selectionParam!.recordStartNs; + let cutData: Array = []; + let tblVal: any = this.schedSwitchTbl; + this.threadFlag = ''; + if (threadId != "" && threadFunName != "") { + this.threadIdInput!.style.border = '1px solid rgb(151,151,151)'; + this.funcNameInput!.style.border = '1px solid rgb(151,151,151)'; + tblVal!.value = []; + this.isCanvansDisplayFn(false); + this.schedSwitchTbl!.loading = true; + if (!this.isThreadStatesData) this.initThreadStateData(this.selectionParam); + if (btnHtml == 'Single') { + this.isSingleButtonFn(true); + this.isLoopButtonFn(false); + let res = await querySingleCutData(threadFunName, threadId, leftStartNs, rightEndNs); + if (res.length == 0) { + this.schedSwitchTbl!.recycleDataSource = []; + this.schedSwitchTbl!.loading = false; + this.clickTreeTitleFn(this.schedSwitchTbl!.recycleDataSource); + return + }; + for (let idx = 0; idx < res.length; idx++) { + for (let i = 0; i < this.singleSourceData.length; i++) { + let singleItem = this.singleSourceData[i] + if (!(singleItem.endTs < res[idx].cycleStartTime || singleItem.ts > res[idx].cycleEndTime)) { + let info = { + pid: singleItem.pid, + tid: singleItem.tid, + state: singleItem.state, + cycleStartTime: res[idx].cycleStartTime, + cycleEndTime: res[idx].cycleEndTime, + name: res[idx].name, + funId: res[idx].id, + runningCnt: singleItem.state == 'Running' ? 1 : 0, + } + cutData.push(info) + } + } + } + }; + if (btnHtml == 'Loop') { + this.isLoopButtonFn(true); + this.isSingleButtonFn(false); + this.schedSwitchTbl!.loading = true; + let res = await queryLoopCutData(threadFunName, threadId, leftStartNs, rightEndNs); + if (res.length == 0) { + this.schedSwitchTbl!.recycleDataSource = []; + this.schedSwitchTbl!.loading = false; + this.clickTreeTitleFn(this.schedSwitchTbl!.recycleDataSource); + return + }; + for (let idx = 0; idx < res.length - 1; idx++) { + res[idx].cycleEndTime = res[idx + 1].cycleStartTime; + for (let i = 0; i < this.loopSourceData.length; i++) { + let loopItem = this.loopSourceData[i] + if (!(loopItem.endTs < res[idx].cycleStartTime || loopItem.ts > res[idx].cycleEndTime)) { + let info = { + pid: loopItem.pid, + tid: loopItem.tid, + state: loopItem.state, + cycleStartTime: res[idx].cycleStartTime, + cycleEndTime: res[idx + 1].cycleStartTime, + name: res[idx].name, + funId: res[idx].id, + runningCnt: loopItem.state == 'Running' ? 1 : 0, + } + cutData.push(info) + } + } + } + }; + this.handleSchedThreadData(cutData) + } else { + if (threadId == "") { + this.threadIdInput!.style.border = '2px solid rgb(255,0,0)'; + this.threadIdInput!.setAttribute('placeholder', 'Please input thread id'); + } else { + this.threadIdInput!.style.border = '1px solid rgb(151,151,151)'; + }; + if (threadFunName == '') { + this.funcNameInput!.style.border = '2px solid rgb(255,0,0)'; + this.funcNameInput!.setAttribute('placeholder', 'Please input function name'); + } else { + this.funcNameInput!.style.border = '1px solid rgb(151,151,151)'; + } + } + } + + handleSchedThreadData(result: Array): void { + let resultData: Array = []; + if (result != null && result.length > 0) { + for (let e of result) { + if (this.selectionParam!.processIds.includes(e.pid)) { + let process = Utils.PROCESS_MAP.get(e.pid); + let thread = Utils.THREAD_MAP.get(e.tid); + e.process = process == null || process.length == 0 ? '[NULL]' : process; + e.thread = thread == null || thread.length == 0 ? '[NULL]' : thread; + e.dur = e.cycleEndTime - e.cycleStartTime; + e.leftNS = e.cycleStartTime - this.selectionParam!.recordStartNs; + resultData.push(e); + } + } + this.translateIntoTreeData(resultData); + } + } + + translateIntoTreeData(data: Array): void { + let group: any = {}; + if (data != null && data.length > 0) { + data.forEach((slice: any) => { + let item = { + title: `${slice.thread}`, + count: slice.runningCnt, + cycleNum: 1, + state: slice.state, + tid: slice.tid, + pid: slice.pid, + thread: slice.thread, + process: slice.process, + cycleStartTime: slice.leftNS, + duration: slice.dur, + level: 'cycle', + }; + if (group[`${slice.pid}`]) { + let process = group[`${slice.pid}`]; + process.count += slice.runningCnt; + let thread = process.children.find((child: any) => child.title === `${slice.thread}` + `[${slice.tid}]`); + if (thread) { + thread.count += slice.runningCnt; + let cycle = thread.children.find((child: any) => child.cycleStartTime === slice.leftNS); + if (cycle) { + cycle.count += slice.runningCnt; + } else { + thread.cycleNum += 1; + process.cycleNum += 1; + thread.duration += slice.dur; + process.duration += slice.dur; + thread.children.push(item); + } + } else { + process.cycleNum += 1; + process.duration += slice.dur; + process.children.push({ + title: `${slice.thread}` + `[${slice.tid}]`, + count: slice.runningCnt, + cycleNum: 1, + pid: slice.pid, + tid: slice.tid, + thread: slice.thread, + process: slice.process, + duration: slice.dur, + level: 'thread', + cycleStartTime: '', + children: [item] + }); + } + } else { + group[`${slice.pid}`] = { + title: `${slice.process}` + `[${slice.pid}]`, + count: slice.runningCnt, + cycleNum: 1, + tid: slice.tid, + pid: slice.pid, + thread: slice.thread, + process: slice.process, + duration: slice.dur, + level: 'process', + cycleStartTime: '', + children: [ + { + title: `${slice.thread}` + `[${slice.tid}]`, + count: slice.runningCnt, + cycleNum: 1, + tid: slice.tid, + pid: slice.pid, + thread: slice.thread, + process: slice.process, + duration: slice.dur, + level: 'thread', + cycleStartTime: '', + children: [item] + }, + ], + }; + } + }); + group = Object.values(group); + for (let i = 0; i < group.length; i++) { + this.addCycleNumber([group[i]]); + } + this.schedSwitchTbl!.recycleDataSource = group; + this.schedSwitchTbl!.loading = false; + this.clickTreeTitleFn(this.schedSwitchTbl!.recycleDataSource); + } + } + addCycleNumber(groupItem: Array): void { + let flagNumber = 0; + for (let idx = 0; idx < groupItem.length; idx++) { + groupItem[idx].duration = (groupItem[idx].duration / 1000000.0).toFixed(3); + if (!(groupItem[idx].children)) { + flagNumber += 1; + groupItem[idx].cycle = flagNumber; + groupItem[idx].title = `cycle ${flagNumber}-` + groupItem[idx].title; + groupItem[idx].cycleStartTime = (groupItem[idx].cycleStartTime / 1000000.0).toFixed(3); + } else { + this.addCycleNumber(groupItem[idx].children) + } + } + } + + clickTreeTitleFn(data: Array): void { + let labelList = this.schedSwitchTbl!.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); + if (labelList) { + for (let i = 0; i < labelList.length; i++) { + let lable = labelList[i].innerHTML; + labelList[i].addEventListener('click', (e) => { + if (lable.includes('Process') && i == 0) { + this.schedSwitchTbl!.setStatus(data, false); + this.schedSwitchTbl!.recycleDs = this.schedSwitchTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (lable.includes('Thread') && i == 1) { + for (let item of data) { + item.status = true; + if (item.children != undefined && item.children.length > 0) { + this.schedSwitchTbl!.setStatus(item.children, false); + } + } + this.schedSwitchTbl!.recycleDs = this.schedSwitchTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (lable.includes('Cycle') && i == 2) { + this.schedSwitchTbl!.setStatus(data, true); + this.schedSwitchTbl!.recycleDs = this.schedSwitchTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand) + } + }) + + } + } + + } + + queryCycleRangeData(): void { + let cycleALeft = this.cycleALeftInput!.value.trim(); + let cycleARight = this.cycleARightInput!.value.trim(); + let cycleBLeft = this.cycleBLeftInput!.value.trim(); + let cycleBRight = this.cycleBRightInput!.value.trim(); + this.histogramSource = []; + this.histogramSource.push(this.rangeTotal) + if (cycleALeft != '' && cycleARight != '' && cycleALeft != cycleARight) { + let countA = 0; + let rangeFilterA = this.clickThreadChildren.filter((it: any) => Number(it.duration) >= Number(cycleALeft) && Number(it.duration) < Number(cycleARight)); + rangeFilterA.forEach((item: any) => { + countA += item.count + }) + this.rangeA = { + count: countA, + cycleNum: rangeFilterA.length, + average: rangeFilterA.length ? Math.ceil(countA / rangeFilterA.length) : 0, + size: 'Cycle A', + isHover: false, + color: '#ffab67' + } + this.histogramSource.push(this.rangeA); + } + + if (cycleBLeft != '' && cycleBRight != '' && cycleBLeft != cycleBRight) { + let countB = 0; + let rangeFilterB = this.clickThreadChildren.filter((it: any) => Number(it.duration) >= Number(cycleBLeft) && Number(it.duration) < Number(cycleBRight)) + rangeFilterB.forEach((item: any) => { + countB += item.count + }) + this.rangeB = { + count: countB, + cycleNum: rangeFilterB.length, + average: rangeFilterB.length ? Math.ceil(countB / rangeFilterB.length) : 0, + size: 'Cycle B', + isHover: false, + color: '#a285d2' + } + this.histogramSource.push(this.rangeB) + } + this.queryHistogramData(); + } + + queryHistogramData(): void { + let source = []; + source = this.histogramSource.map((it: any, index: number) => { + let data: any = { + cycle: it.size, + average: it.average, + visible: 1, + color: it.color, + }; + return data; + }); + this.chartTotal!.config = { + data: source, + appendPadding: 10, + xField: 'cycle', + yField: 'average', + notSort: true, + removeUnit: true, + seriesField: '', + color: (a) => { + if (a.cycle === 'Total') { + return '#2f72f8'; + } else if (a.cycle === 'Cycle A') { + return '#ffab67'; + } else if (a.cycle === 'Cycle B') { + return '#a285d2'; + } else { + return '#0a59f7'; + } + }, + tip: (a) => { + if (a && a[0]) { + let tip = ''; + for (let obj of a) { + tip = + `${tip} +
+
+
${obj.xLabel}:${obj.obj.average}
+
+ `; + } + return tip; + } else { + return ''; + } + }, + label: null, + }; + } + + isCanvansDisplayFn(flag: boolean): void { + if (!flag) { + this.setAttribute('isCanvansDisplay', '') + } else { + this.removeAttribute('isCanvansDisplay') + } + } + + isSingleButtonFn(flag: boolean): void { + if (flag) { + this.setAttribute('isSingleButton', '') + } else { + this.removeAttribute('isSingleButton') + } + } + + isLoopButtonFn(flag: boolean): void { + if (flag) { + this.setAttribute('isLoopButton', '') + } else { + this.removeAttribute('isLoopButton') + } + } + + isQueryButtonClick(flag: boolean): void { + if (flag) { + this.setAttribute('isQueryButton', '') + } else { + this.removeAttribute('isQueryButton') + } + } + + connectedCallback() { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.schedSwitchTbl!); + } + initHtml(): string { + return ` + +
+ + +
+ + +
+
+
+
+ + + + + + + + + + +
+ + +
+ + ` + } +} diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts index 1f87d94e6c677eb0c95a9ce0fb98f4c7d332a66b..878d8f637ba1914939483e5ae6fb0db0c42fdf62 100644 --- a/ide/src/trace/database/SqlLite.ts +++ b/ide/src/trace/database/SqlLite.ts @@ -5975,6 +5975,90 @@ export const queryLoopFuncNameCycle = (funcName: string, tIds: string, leftNS: n } ); + + export const querySchedThreadStates = (tIds: Array, leftStartNs: number, rightEndNs: number): Promise> => + query( + 'getTabThreadStates', + ` + select + B.id, + B.pid, + B.tid, + B.state, + B.type, + B.dur, + B.ts, + B.dur + B.ts as endTs + from + thread_state AS B + where + B.tid in (${tIds.join(',')}) + and + not ((B.ts + ifnull(B.dur,0) < $leftStartNs) or (B.ts > $rightEndNs)) + order by + B.pid; + `, + { $leftStartNs: leftStartNs, $rightEndNs: rightEndNs } + ); + + export const querySingleCutData = (funcName: string, tIds: string, leftStartNs: number, rightEndNs: number): Promise> => + query( + 'querySingleCutData', + ` + select + c.id, + c.name, + c.ts as cycleStartTime, + c.ts + c.dur as cycleEndTime, + c.depth, + t.tid, + p.pid, + c.dur + from + callstack c + left join + thread t on c.callid = t.id + left join + process p on t.ipid = p.id + left join + trace_range r + where + c.name = '${funcName}' + and + t.tid = '${tIds}' + and + not ((c.ts < $leftStartNs) or (c.ts + ifnull(c.dur, 0) > $rightEndNs)) + `, + {$leftStartNs: leftStartNs, $rightEndNs: rightEndNs} + ) + + export const queryLoopCutData = ( funcName: string, tIds: string, leftStartNs: number, rightEndNs: number): Promise> => + query ( + 'queryLoopCutData', + ` + select + c.id, + c.name, + c.ts as cycleStartTime, + c.depth, + t.tid, + p.pid + from callstack c + 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 ((c.ts < $leftStartNs) or (c.ts > $rightEndNs)) + order by + c.ts + `, + { $leftStartNs: leftStartNs, $rightEndNs: rightEndNs } + ) export const getGpufreqData = (leftNS: number, rightNS: number, earliest: boolean): Promise> => { let queryCondition = ''; if (!earliest) {