From ff642595f8562311a87cad9b284211c13671bd54 Mon Sep 17 00:00:00 2001 From: wangyujie Date: Fri, 1 Dec 2023 15:13:04 +0800 Subject: [PATCH] =?UTF-8?q?gpufreq=20=E7=AE=97=E5=8A=9B=E6=B6=88=E8=80=97?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangyujie --- .../component/chart/SpSegmentationChart.ts | 21 +- .../component/trace/base/TraceSheetConfig.ts | 12 + .../sheet/gpufreq/tabPaneGpufreqDataCut.ts | 456 ++++++++++++++++++ .../sheet/gpufreq/tabPaneGpufreqUsage.ts | 221 +++++++++ ide/src/trace/database/SqlLite.ts | 105 ++++ .../ui-worker/ProcedureWorkerFreqExtend.ts | 5 +- 6 files changed, 810 insertions(+), 10 deletions(-) create mode 100644 ide/src/trace/component/trace/sheet/gpufreq/tabPaneGpufreqDataCut.ts create mode 100644 ide/src/trace/component/trace/sheet/gpufreq/tabPaneGpufreqUsage.ts diff --git a/ide/src/trace/component/chart/SpSegmentationChart.ts b/ide/src/trace/component/chart/SpSegmentationChart.ts index be34e952..d8ee1496 100644 --- a/ide/src/trace/component/chart/SpSegmentationChart.ts +++ b/ide/src/trace/component/chart/SpSegmentationChart.ts @@ -34,6 +34,7 @@ export class SegMenTaTion { static chartData: any; // 数据切割联动 static setChartData(type: string, data: any) { + this.tabHover(type, false) let currentMaxValue = 0; if (type === 'CPU-FREQ') { let chartData = data.map((v: any) => { @@ -58,16 +59,17 @@ export class SegMenTaTion { } else if (type === 'GPU-FREQ') { let chartData = data.map((v: any) => { - - if (v.count > currentMaxValue) { - currentMaxValue = v.count + let _count = Number(v.count) + if (_count > currentMaxValue) { + currentMaxValue = _count } return { cpu: 7, - dur: v.dur * 1000000, - value: v.count, + dur: Number(v.dur * 1000000), + value: _count, startNS: v.startNS, cycle: v.cycle, + type } }) CpuFreqExtendStruct.maxValue = currentMaxValue; @@ -76,6 +78,7 @@ export class SegMenTaTion { SegMenTaTion.GpuRow!.isComplete = false; SegMenTaTion.GpuRow!.supplier = (): Promise> => new Promise>((resolve) => resolve(chartData)); + SegMenTaTion.trace.refreshCanvas(true) } else if (type === 'SCHED-SWITCH') { let chartData = data.map((v: any) => { if (v.count > currentMaxValue) { @@ -87,6 +90,7 @@ export class SegMenTaTion { value: v.count, startNS: Number(v.cycleStartTime) * 1000 * 1000, cycle: v.cycle, + type } }) CpuFreqExtendStruct.maxValue = currentMaxValue; @@ -171,10 +175,11 @@ export class SegMenTaTion { } // 悬浮联动 - static tabHover(type: String, tableIsHover: any = false, cycle: any) { + static tabHover(type: String, tableIsHover: any = false, cycle: number = -1) { CpuFreqExtendStruct.isTabHover = tableIsHover; if (type === 'CPU-FREQ' || type === 'GPU-FREQ' || type === 'SCHED-SWITCH') { if (tableIsHover) { + SegMenTaTion.GpuRow!.isHover = false; CpuFreqExtendStruct.cycle = cycle } else { CpuFreqExtendStruct.cycle = -1 @@ -266,7 +271,7 @@ export class SegMenTaTion { SegMenTaTion.trace?.displayTip( SegMenTaTion.jsonRow!, CpuFreqExtendStruct.hoverCpuFreqStruct, - `${ColorUtils.formatNumberComma(CpuFreqExtendStruct.hoverCpuFreqStruct!.value || 0)}` + `${ColorUtils.formatNumberComma(CpuFreqExtendStruct.hoverCpuFreqStruct === undefined ? 0 : CpuFreqExtendStruct.hoverCpuFreqStruct.value! || 0)}` ); }; SegMenTaTion.jsonRow.findHoverStruct = () => { @@ -309,7 +314,7 @@ export class SegMenTaTion { SegMenTaTion.trace?.displayTip( SegMenTaTion.GpuRow!, CpuFreqExtendStruct.hoverCpuFreqStruct, - `${ColorUtils.formatNumberComma(CpuFreqExtendStruct.hoverCpuFreqStruct?.value!)} Hz·ms` + `${ColorUtils.formatNumberComma(CpuFreqExtendStruct.hoverCpuFreqStruct === undefined ? 0 : CpuFreqExtendStruct.hoverCpuFreqStruct.value!)} Hz·ms` ); }; SegMenTaTion.GpuRow.findHoverStruct = () => { diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index ff0f3522..797d136b 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.js'; import { TabPaneFreqDataCut } from '../sheet/frequsage/TabPaneFreqDataCut.js'; import { TabPaneHisysEvents } from '../sheet/hisysevent/TabPaneHisysEvents.js'; import { TabPaneHiSysEventSummary } from '../sheet/hisysevent/TabPaneHiSysEventSummary.js'; +import {TabPaneGpufreq} from '../sheet/gpufreq/tabPaneGpufreqUsage.js' +import {TabPaneGpufreqDataCut} from '../sheet/gpufreq/tabPaneGpufreqDataCut.js' export let tabConfig: any = { 'current-selection': { @@ -650,4 +652,14 @@ export let tabConfig: any = { type: TabPaneHiSysEventSummary, require: (param: SelectionParam) => param.hiSysEvents.length > 0, }, + 'tabpane-Gpufreq':{ + title: 'Gpufreq Usage', + type: TabPaneGpufreq, + require: (param: SelectionParam) => param.clockMapData.size > 0 && param.clockMapData.size < 2, + }, + 'tabpane-FreqDataCut':{ + title: 'Gpufreq DataCut', + type: TabPaneGpufreqDataCut, + require: (param: SelectionParam) => param.clockMapData.size > 0 && param.clockMapData.size < 2, + } }; diff --git a/ide/src/trace/component/trace/sheet/gpufreq/tabPaneGpufreqDataCut.ts b/ide/src/trace/component/trace/sheet/gpufreq/tabPaneGpufreqDataCut.ts new file mode 100644 index 00000000..d5032561 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/gpufreq/tabPaneGpufreqDataCut.ts @@ -0,0 +1,456 @@ +/* + * 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.js'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table.js'; +import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection.js'; +import { getGpufreqData, getGpufreqDataCut } from '../../../../database/SqlLite.js'; +import { resizeObserver } from '../SheetUtils.js'; +import { SliceGroup } from '../../../../bean/StateProcessThread.js'; +import { SegMenTaTion } from '../../../chart/SpSegmentationChart.js'; + +@element('tabpane-gpufreqdatacut') +export class TabPaneGpufreqDataCut extends BaseElement { + private threadStatesTbl: LitTable | null | undefined; + private currentSelectionParam: SelectionParam | any; + private _single: Element | null | undefined; + private _loop: Element | null | undefined; + private _threadId: HTMLInputElement | null | undefined; + private _threadFunc: HTMLInputElement | null | undefined; + private threadIdValue: string = ''; + private threadFuncName: string = ''; + private initData: Array = []; + + set data(threadStatesParam: SelectionParam | any) { + if (this.currentSelectionParam === threadStatesParam) { + return; + } + this.currentSelectionParam = threadStatesParam; + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = true; + getGpufreqData(threadStatesParam.leftNs, threadStatesParam.rightNs, false).then((result) => { + if (result != null && result.length > 0) { + let resultList = JSON.parse(JSON.stringify(result)) + if (result.length == 1) { + resultList[0].dur = threadStatesParam.rightNs - threadStatesParam.leftNs + resultList[0].count = resultList[0].dur * resultList[0].value + } else { + resultList[0].dur = resultList[1].startNS - threadStatesParam.leftNs + resultList[0].count = resultList[0].dur * resultList[0].value + + resultList[resultList.length - 1].dur = threadStatesParam.rightNs - resultList[resultList.length - 1].startNS + resultList[resultList.length - 1].count = resultList[resultList.length - 1].dur * resultList[resultList.length - 1].value + } + + this.initData = resultList + this.threadStatesTbl!.loading = false; + + } else { + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = false; + } + + }) + } + + initElements(): void { + this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-gpufreq-percent'); + this._single = this.shadowRoot?.querySelector('#single'); + this._loop = this.shadowRoot?.querySelector('#loop'); + this._threadId = this.shadowRoot?.querySelector('#dataCutThreadId'); + this._threadFunc = this.shadowRoot?.querySelector('#dataCutThreadFunc'); + this.threadIdValue = this._threadId!.value.trim(); + this.threadFuncName = this._threadFunc!.value.trim(); + const originalThreadIdStyle = this._threadId!.style.border; + const originalThreadFuncStyle = this._threadId!.style.border; + const originalThreadIdPlaceholder = String(this._threadId!.getAttribute('placeholder')); + const originalThreadFuncPlaceholder = String(this._threadId!.getAttribute('placeholder')); + + //点击single + this._single?.addEventListener('click', (e) => { + this.threadIdValue = this._threadId!.value.trim(); + this.threadFuncName = this._threadFunc!.value.trim(); + this.threadStatesTbl!.loading = true; + + this.validationFun(this.threadIdValue, this.threadFuncName, originalThreadIdStyle, originalThreadFuncStyle, originalThreadIdPlaceholder, originalThreadFuncPlaceholder, 'single') + + }) + + //点击loop + this._loop?.addEventListener('click', (e) => { + this.threadIdValue = this._threadId!.value.trim(); + this.threadFuncName = this._threadFunc!.value.trim(); + this.threadStatesTbl!.loading = true; + + this.validationFun(this.threadIdValue, this.threadFuncName, originalThreadIdStyle, originalThreadFuncStyle, originalThreadIdPlaceholder, originalThreadFuncPlaceholder, 'loop') + + }) + + this.threadStatesTbl?.addEventListener('row-click', (event: any) => { + if (event.detail.level == 2 && event.detail.thread.includes('cycle')) { + console.log(event.detail.thread) + SegMenTaTion.tabHover('GPU-FREQ', true, event.detail.data.cycle) + } + }) + } + connectedCallback() { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.threadStatesTbl!); + } + + initHtml(): string { + return ` + +
+ + +
+ + +
+
+ + + + + + + + + + + + + + + ` + } + + private validationFun(threadIdValue: string, threadFuncName: string, originalThreadIdStyle: string, originalThreadFuncStyle: string, originalThreadIdPlaceholder: string, originalThreadFuncPlaceholder: string, fun: string) { + if (threadIdValue == '') { + this.threadStatesTbl!.loading = false; + this._threadId!.style.border = '1px solid rgb(255,0,0)'; + this._threadId!.setAttribute('placeholder', 'Please input thread id'); + this.threadStatesTbl!.recycleDataSource = []; + } else if (threadFuncName == '') { + this.threadStatesTbl!.loading = false; + this._threadFunc!.style.border = '1px solid rgb(255,0,0)'; + this._threadFunc!.setAttribute('placeholder', 'Please input function name'); + this.threadStatesTbl!.recycleDataSource = []; + } else { + this._threadId!.style.border = originalThreadIdStyle; + this._threadFunc!.style.border = originalThreadFuncStyle; + this._threadId!.setAttribute('placeholder', originalThreadIdPlaceholder); + this._threadFunc!.setAttribute('placeholder', originalThreadFuncPlaceholder); + if (fun == 'single') { + getGpufreqDataCut(threadIdValue, threadFuncName, this.currentSelectionParam.leftNs, this.currentSelectionParam.rightNs, true, false).then((result) => { + let _initData = JSON.parse(JSON.stringify(this.initData)) + this.dataCutFun(_initData, result) + }) + } + if (fun == 'loop') { + getGpufreqDataCut(threadIdValue, threadFuncName, this.currentSelectionParam.leftNs, this.currentSelectionParam.rightNs, false, true).then((result) => { + let _initData = JSON.parse(JSON.stringify(this.initData)) + this.dataCutFun(_initData, result) + }) + } + + } + } + + private dataCutFun(initData: Array, dataCut: Array) { + let earliest: number = 0 + let selectGpufreqData = new Array(); + if (initData.length > 0 && dataCut.length > 0) { + let lastList = [] + getGpufreqData(this.currentSelectionParam.leftNs, this.currentSelectionParam.rightNs, true).then((result) => { + if (result.length > 0) { + earliest = result[0].startNS + let _dataCut = dataCut.filter(i => i.startTime >= earliest); + for (let i = 0; i < _dataCut.length; i++) { + let e = _dataCut[i]; + for (let j of initData) { + if (e.startTime >= j.startNS && e.startTime <= j.endTime) { + if (e.endTime <= j.endTime) { + let obj = { + 'startNS': e.startTime, + 'endTime': e.endTime, + 'dur': e.endTime - e.startTime, + 'count': (e.endTime - e.startTime) * j.value, + 'ts': e.startTime + this.currentSelectionParam.recordStartNs, + 'parentIndex': i, + 'thread': j.thread, + 'filterId': j.filterId, + 'freq': j.freq, + 'value': j.value + } + lastList.push(obj) + } else { + let obj = { + 'startNS': e.startTime, + 'endTime': j.endTime, + 'dur': j.endTime - e.startTime, + 'count': (j.endTime - e.startTime) * j.value, + 'ts': e.startTime + this.currentSelectionParam.recordStartNs, + 'parentIndex': i, + 'thread': j.thread, + 'filterId': j.filterId, + 'freq': j.freq, + 'value': j.value + } + lastList.push(obj) + } + } else if (e.startTime <= j.startNS && j.endTime <= e.endTime) { + let obj = { + 'startNS': j.startNS, + 'endTime': j.endTime, + 'dur': j.endTime - j.startNS, + 'count': (j.endTime - j.startNS) * j.value, + 'ts': j.startNS + this.currentSelectionParam.recordStartNs, + 'parentIndex': i, + 'thread': j.thread, + 'filterId': j.filterId, + 'freq': j.freq, + 'value': j.value + } + lastList.push(obj) + } + else if (j.startNS <= e.endTime && e.endTime <= j.endTime) { + let obj = { + 'startNS': j.startNS, + 'endTime': e.endTime, + 'dur': e.endTime - j.startNS, + 'count': (e.endTime - j.startNS) * j.value, + 'ts': j.startNS + this.currentSelectionParam.recordStartNs, + 'parentIndex': i, + 'thread': j.thread, + 'filterId': j.filterId, + 'freq': j.freq, + 'value': j.value + } + lastList.push(obj) + } + } + } + let tree = this.createTree(lastList) + selectGpufreqData.push(tree) + this.threadStatesTbl!.recycleDataSource = selectGpufreqData; + this.threadStatesTbl!.loading = false; + this.theadClick(selectGpufreqData) + } else { + this.threadStatesTbl!.recycleDataSource = [] + this.threadStatesTbl!.loading = false; + } + + }) + + + } else { + this.threadStatesTbl!.recycleDataSource = [] + this.threadStatesTbl!.loading = false; + } + } + + private createTree(data: Array) { + if (data.length > 0) { + const root = { + thread: "gpufreq Frequency", + count: '0', + freq: '', + dur: '0', + percent: '100', + level: 1, + children: [], + }; + + const valueMap = {}; + data.forEach((item: any) => { + const parentIndex = item.parentIndex; + const freq = item.freq; + const unit = 1000000 + const kunit= 1000000000000 + item.thread = `${item.thread} Frequency`; + item.level = 4 + item.dur = (item.dur / unit).toFixed(3) + item.count = (item.count / kunit).toFixed(3) + item.freq = (item.freq).toFixed(3) + if (!valueMap[parentIndex]) { + valueMap[parentIndex] = { + thread: `cycle ${parentIndex + 1} ${item.thread}`, + count: item.count, + dur: item.dur, + ts: item.ts, + startTime: (item.startNS / unit).toFixed(3), + startNS: item.startNS, + percent: '100', + level: 2, + cycle: parentIndex + 1, + children: [], + }; + } else { + let fdur = Number(valueMap[parentIndex].dur) + let fcount = Number(valueMap[parentIndex].count) + let idur = Number(item.dur) + let icount = Number(item.count) + fdur += idur; + valueMap[parentIndex].dur = fdur.toFixed(3); + fcount += icount; + valueMap[parentIndex].count = fcount.toFixed(3); + } + + if (!valueMap[parentIndex].children[freq]) { + valueMap[parentIndex].children[freq] = { + thread: item.thread, + count: item.count, + gpufreq: item.freq, + dur: item.dur, + percent: '100', + level: 3, + children: [], + }; + } else { + let zdur = Number(valueMap[parentIndex].children[freq].dur) + let zcount = Number(valueMap[parentIndex].children[freq].count) + let idur = Number(item.dur) + let icount = Number(item.count) + zdur += idur; + valueMap[parentIndex].children[freq].dur = zdur.toFixed(3); + zcount += icount; + valueMap[parentIndex].children[freq].count = zcount.toFixed(3); + } + valueMap[parentIndex].children[freq].children.push(item); + + }) + Object.values(valueMap).forEach((node: any) => { + const parentNode = valueMap[node.value - 1]; + if (parentNode) { + parentNode.children.push(node); + let pdur = Number(parentNode.dur) + let pcount = Number(parentNode.count) + let ndur = Number(node.dur) + let ncount = Number(node.count) + pdur += ndur; + parentNode.dur = pdur.toFixed(3); + pcount += ncount; + parentNode.count += pcount.toFixed(3); + } else { + root.children.push(node); + let rdur = Number(root.dur) + let rcount = Number(root.count) + let ndur = Number(node.dur) + let ncount = Number(node.count) + rdur += ndur; + root.dur = rdur.toFixed(3); + rcount += ncount; + root.count = rcount.toFixed(3); + } + + }); + // 移除 key 值 + root.children.forEach((item: any) => { + item.children = Object.values(item.children); + }) + function calculatePercent(node: any) { + if (node.count === 0 || node.count === undefined) { + return; + } + node.percent = (Number(node.count) / Number(root.count) * 100).toFixed(2); + + if (node.children && node.children.length > 0) { + node.children.forEach(calculatePercent); + } else { + return; + } + } + calculatePercent(root); + + SegMenTaTion.setChartData('GPU-FREQ', root.children) + return root; + + } else { + return {} + } + } + + private theadClick(data: Array) { + let labels = this.threadStatesTbl?.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('All') && i === 0) { + this.threadStatesTbl!.setStatus(data, false); + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + + } else if (label.includes('Cycle') && i === 1) { + for (let item of data) { + item.status = true; + if (item.children != undefined && item.children.length > 0) { + this.threadStatesTbl!.setStatus(item.children, false); + } + } + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + + } else if (label.includes('Freq') && i === 2) { + for (let item of data) { + item.status = true; + for (let e of item.children ? item.children : []) { + e.status = true; + if (e.children != undefined && e.children.length > 0) { + this.threadStatesTbl!.setStatus(e.children, false, 0); + } + } + } + + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + + } else if (label.includes('Thread') && i === 3) { + this.threadStatesTbl!.setStatus(data, true); + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); + + } + }); + } + } + + } + +} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/gpufreq/tabPaneGpufreqUsage.ts b/ide/src/trace/component/trace/sheet/gpufreq/tabPaneGpufreqUsage.ts new file mode 100644 index 00000000..eac6a133 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/gpufreq/tabPaneGpufreqUsage.ts @@ -0,0 +1,221 @@ +/* + * 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.js'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table.js'; +import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection.js'; +import { getGpufreqData } from '../../../../database/SqlLite.js'; +import { resizeObserver } from '../SheetUtils.js'; +import { SliceGroup } from '../../../../bean/StateProcessThread.js'; + +@element('tabpane-gpufreq') +export class TabPaneGpufreq extends BaseElement { + private threadStatesTbl: LitTable | null | undefined; + private currentSelectionParam: Selection | undefined; + + set data(clockCounterValue: SelectionParam | any) { + let dataSource: Array = []; + if (this.currentSelectionParam === clockCounterValue) { + return; + } + this.currentSelectionParam = clockCounterValue; + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = true; + getGpufreqData(clockCounterValue.leftNs, clockCounterValue.rightNs, false).then((result) => { + if (result != null && result.length > 0) { + let resultList = JSON.parse(JSON.stringify(result)) + if (result.length == 1) { + resultList[0].dur = clockCounterValue.rightNs - clockCounterValue.leftNs + resultList[0].count = resultList[0].dur * resultList[0].value + } else { + resultList[0].dur = resultList[1].startNS - clockCounterValue.leftNs + resultList[0].count = resultList[0].dur * resultList[0].value + + resultList[resultList.length - 1].dur = clockCounterValue.rightNs - resultList[resultList.length - 1].startNS + resultList[resultList.length - 1].count = resultList[resultList.length - 1].dur * resultList[resultList.length - 1].value + } + let sd: any = this.createTree(resultList); + dataSource = sd; + this.threadStatesTbl!.recycleDataSource = dataSource; + this.threadStatesTbl!.loading = false; + let List = new Array(); + List.push(...dataSource) + this.theadClick(List) + } else { + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = false; + } + + }) + + } + + initElements(): void { + this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-gpufreq-percent'); + } + + connectedCallback() { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.threadStatesTbl!); + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + ` + } + + private createTree(sourceList: Array) { + let selectGpufreqData = new Array(); + if (sourceList.length > 0) { + function createTree(data: Array) { + const root = { + thread: "gpufreq Frequency", + count: '0', + freq: '', + dur: '0', + percent: '100', + children: [], + }; + + const valueMap = {}; + data.forEach((item: any) => { + const freq = item.freq; + const unit = 1000000 + const kunit= 1000000000000 + item.dur = (item.dur / unit).toFixed(3) + item.count = (item.count / kunit).toFixed(3) + item.freq = (item.freq).toFixed(3) + item.thread = `${item.thread} Frequency` + if (!valueMap[freq]) { + valueMap[freq] = { + thread: "gpufreq Frequency", + count: item.count, + gpufreq: item.freq, + dur: item.dur, + percent: '100', + children: [], + }; + } else { + let fdur = Number(valueMap[freq].dur) + let fcount = Number(valueMap[freq].count) + let idur = Number(item.dur) + let icount = Number(item.count) + fdur += idur; + valueMap[freq].dur = fdur.toFixed(3); + fcount += icount; + valueMap[freq].count = fcount.toFixed(3); + } + valueMap[freq].children.push(item); + }); + + function calculatePercent(node: any) { + if (node.count === 0 || node.count === undefined) { + return; + } + node.percent = (Number(node.count) / Number(root.count) * 100).toFixed(2); + + if (node.children && node.children.length > 0) { + node.children.forEach(calculatePercent); + } else { + return + } + } + + Object.values(valueMap).forEach((node: any) => { + const parentNode = valueMap[node.value - 1]; + if (parentNode) { + parentNode.children.push(node); + let pdur = Number(parentNode.dur) + let pcount = Number(parentNode.count) + let ndur = Number(node.dur) + let ncount = Number(node.count) + pdur += ndur; + parentNode.dur = pdur.toFixed(3); + pcount += ncount; + parentNode.count += pcount.toFixed(3); + } else { + root.children.push(node); + let rdur = Number(root.dur) + let rcount = Number(root.count) + let ndur = Number(node.dur) + let ncount = Number(node.count) + rdur += ndur; + root.dur = rdur.toFixed(3); + rcount += ncount; + root.count = rcount.toFixed(3); + } + + }); + calculatePercent(root); + + return root; + } + const tree = createTree(sourceList); + selectGpufreqData.push(tree) + + } + return selectGpufreqData + } + + private theadClick(data: Array) { + let labels = this.threadStatesTbl?.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('All') && i === 0) { + this.threadStatesTbl!.setStatus(data, false); + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + + } else if (label.includes('Freq') && i === 1) { + + for (let item of data) { + item.status = true; + if (item.children != undefined && item.children.length > 0) { + this.threadStatesTbl!.setStatus(item.children, false); + } + } + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + + } else if (label.includes('Thread') && i === 2) { + this.threadStatesTbl!.setStatus(data, true); + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); + } + }); + } + } + } +} \ No newline at end of file diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts index 772df4a2..04d1a2b8 100644 --- a/ide/src/trace/database/SqlLite.ts +++ b/ide/src/trace/database/SqlLite.ts @@ -5816,3 +5816,108 @@ export const queryHiSysEventData = (): Promise> => `, { $search: funcName } ); + + export const getGpufreqData = (leftNS: number, rightNS: number, earliest: boolean): Promise> => { + let queryCondition = ''; + if (!earliest) { + queryCondition += ` where not ((s.ts - r.start_ts + ifnull(s.dur,0) < ${leftNS}) or (s.ts - r.start_ts > ${rightNS}))` + } + return query( + 'getGpufreqData', + ` + with state as + (select + name, + filter_id, + ts, + endts, + endts-ts as dur, + type, + value + from + (select + measure.filter_id, + clock_event_filter.name, + measure.ts, + lead(ts, 1, null) over( order by measure.ts) endts, + measure.type, + measure.value + from + clock_event_filter, + trace_range + left join + measure + where + clock_event_filter.name = 'gpufreq' + and + clock_event_filter.type = 'clock_set_rate' + and + clock_event_filter.id = measure.filter_id + order by measure.ts) + where endts is not null + ) + select + s.name as thread, + s.filter_id as filterId, + s.value/1000000 as freq, + s.value*s.dur as count, + s.value, + s.ts, + s.ts-r.start_ts as startNS, + s.dur, + s.endts- r.start_ts as endTime + from + state s, + trace_range r + ${queryCondition} + order by ts + `, + { $leftNS: leftNS, $rightNS: rightNS } + ); + } + + export const getGpufreqDataCut = (tIds: string, funcName: string, leftNS: number, rightNS: number, single: boolean, loop: boolean): Promise> => { + let queryCondition = ''; + if (single) { + queryCondition += `select s.funName,s.startTime,s.dur,s.startTime+s.dur as endTime,s.depth,s.tid,s.threadName,s.pid from state s + where endTime between ${leftNS} and ${rightNS}`; + } + if (loop) { + queryCondition += `select s.funName,s.startTime,s.loopEndTime-s.startTime as dur,s.loopEndTime as endTime,s.depth,s.tid,s.threadName,s.pid from state s + where endTime between ${leftNS} and ${rightNS} `; + } + return query( + 'getGpufreqDataCut', + ` + with state as + (select + * + from + (select + c.name as funName, + c.ts - r.start_ts as startTime, + c.dur, + lead(c.ts - r.start_ts, 1, null) over( order by c.ts - r.start_ts) loopEndTime, + c.depth, + t.tid, + t.name as threadName, + p.pid + 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 like '%${funcName}%' + and + tid = '${tIds}' + and + startTime between ${leftNS} and ${rightNS})) + ${queryCondition} + `, + { $search: funcName } + ); + } \ No newline at end of file diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts index 93759b2f..3faaf857 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts @@ -41,6 +41,7 @@ export class FreqExtendRender extends Render { if (row.isHover) { CpuFreqExtendStruct.cycle = -1; + CpuFreqExtendStruct.isTabHover = false; } freqReq.context.beginPath(); for (let re of freqFilter) { @@ -74,8 +75,8 @@ export class CpuFreqExtendStruct extends BaseStruct { index += 2; freqContext.fillStyle = ColorUtils.colorForTid(index); freqContext.strokeStyle = ColorUtils.colorForTid(index); - if (data === CpuFreqExtendStruct.hoverCpuFreqStruct - || data === CpuFreqExtendStruct.selectCpuFreqStruct + if (data === CpuFreqExtendStruct.hoverCpuFreqStruct + || data === CpuFreqExtendStruct.selectCpuFreqStruct || data === CpuFreqExtendStruct.selectCpuFreqStruct || (data.cycle === CpuFreqExtendStruct.cycle && CpuFreqExtendStruct.cycle !== -1)) { -- Gitee