diff --git a/ide/src/doc/quickstart_animation.html b/ide/src/doc/quickstart_animation.html index 29ab5dfdf607f674b7366e6639629fe835b55f49..f6cfb8db7ba59caedc8301bcc82e6945435b9e1d 100644 --- a/ide/src/doc/quickstart_animation.html +++ b/ide/src/doc/quickstart_animation.html @@ -801,7 +801,7 @@ diff --git a/ide/src/doc/quickstart_bio.html b/ide/src/doc/quickstart_bio.html index d5e7d09bc1bd0df43cbc8e634bf13c77631decc8..b2277c98b372d67dc70cdb01b03669ae1155c796 100644 --- a/ide/src/doc/quickstart_bio.html +++ b/ide/src/doc/quickstart_bio.html @@ -1070,9 +1070,9 @@ Hide System so:隐藏系统库文件 。

点击Disk I/O Latency Calltree左下角的柱状图的图标,会切换到火焰图页面。
GitHub Logo
- 进入到火焰图页面,火焰图的展示跟Callinfo的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称和Duration时长。
+ 进入到火焰图页面,火焰图的展示跟 Disk I/O Latency Calltree 的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称和Duration时长。
GitHub Logo
- 鼠标左键火焰图,会进入下一级界面,右键回到上一级。
+ 鼠标点击火焰图,会进入下一级界面,点击上级则返回上一级界面。
GitHub Logo

diff --git a/ide/src/doc/quickstart_filesystem.html b/ide/src/doc/quickstart_filesystem.html index 9dca4092c99c46be6514c7ae1dcfd222e410d0cf..9a781585a26f3130d57f71b373b1eb8e7ffcdfb6 100644 --- a/ide/src/doc/quickstart_filesystem.html +++ b/ide/src/doc/quickstart_filesystem.html @@ -1172,9 +1172,9 @@ Hide System so:隐藏系统库文件。

点击FileSystem Calltre左下角的柱状图的图标,会切换到火焰图页面。
GitHub Logo
- 进入到火焰图页面,火焰图的展示跟Callinfo的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称和Duration时长。
+ 进入到火焰图页面,火焰图的展示跟 Filesystem Calltree 的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称和Duration时长。
GitHub Logo
- 鼠标左键火焰图,会进入下一级界面,右键回到上一级。
+ 鼠标点击火焰图,会进入下一级界面,点击上级则返回上一级界面。
GitHub Logo

diff --git a/ide/src/doc/quickstart_hiperf.html b/ide/src/doc/quickstart_hiperf.html index 7598edcbc75b669b7f7399909ae226eac0944d05..abe212d4e63ea747b3c39e1c35b66f78bf44f086 100644 --- a/ide/src/doc/quickstart_hiperf.html +++ b/ide/src/doc/quickstart_hiperf.html @@ -1013,7 +1013,7 @@ Hide System so:隐藏系统库文件。

点击Perf Profile左下角的柱状图的图标,会切换到火焰图页面。
GitHub Logo
- 进入到火焰图页面,火焰图的展示跟Callinfo的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称,lib,addr,Count,%in + 进入到火焰图页面,火焰图的展示跟 Perf Profile 的tab页的调用栈显示一致,鼠标放到色块上,悬浮框可以显示调用栈名称,lib,addr,Count,%in current thread,%in current process,&in all process。
GitHub Logo

diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index eeef49272035fbe8f43387d936d41cdb66b167e4..248a4b6ba185e2219a66c14fe5a262207e6c571e 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -1986,9 +1986,6 @@ export class SpSystemTrace extends BaseElement { this.hoverFlag = null; } this.timerShaftEL!.documentOnKeyPress(ev, this.currentSlicesTime); - if (keyPress === 'f') { - this.verticalScrollToRow(); - } } else { this.stopWASD(); } @@ -4743,12 +4740,15 @@ export class SpSystemTrace extends BaseElement { } if (this.tipEL) { this.tipEL.innerHTML = html; - if (row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER || row.rowType === TraceRow.ROW_TYPE_PERF_CALLCHART) { + if (row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER || row.rowType === TraceRow.ROW_TYPE_PERF_CALLCHART || row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT) { this.tipEL.style.maxWidth = row.clientWidth / 3 + 'px'; this.tipEL.style.wordBreak = ' break-all'; this.tipEL.style.height = 'unset'; this.tipEL.style.display = 'block'; y = y + struct.depth * 20; + if (row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT) { + y = row.hoverY + row.getBoundingClientRect().top - this.getBoundingClientRect().top; + } } else { this.tipEL.style.display = 'flex'; this.tipEL.style.height = row.style.height; diff --git a/ide/src/trace/component/chart/SpProcessChart.ts b/ide/src/trace/component/chart/SpProcessChart.ts index f940b2a992d9bdca0d614f7ad2707c7710f8ffbb..f9616d2055322e7673de80330c96020a35d9df3a 100644 --- a/ide/src/trace/component/chart/SpProcessChart.ts +++ b/ide/src/trace/component/chart/SpProcessChart.ts @@ -79,6 +79,21 @@ export class SpProcessChart { this.processAsyncFuncMap = Utils.groupBy(asyncFuncList, 'pid'); }; + /** + * 更新无end方法的持续时间 + * @param it 被更新的方法 + * @param i 索引位置 + * @param arr 被更新的方法集合 + */ + modifyNofinishDur(it: FuncStruct, i: number, arr: Array): void { + if (it.dur === -1) { + it.dur = TraceRow.range!.endNS - it.startTs!; + it.flag = 'Did not end'; + it.nofinish = true; + } + } + + initDeliverInputEvent = async (): Promise => { let row = TraceRow.skeleton(); row.setAttribute('disabled-check', ''); @@ -114,11 +129,8 @@ export class SpProcessChart { createDepth(++currentDepth, index); } }; - asyncFuncGroups.forEach((it, i) => { - if (it.dur == -1) { - it.dur = (TraceRow.range?.endNS || 0) - it.startTs; - it.flag = 'Did not end'; - } + asyncFuncGroups.forEach((it, i, arr) => { + this.modifyNofinishDur(it, i, arr); createDepth(0, i); }); let max = Math.max(...asyncFuncGroups.map((it) => it.depth || 0)) + 1; @@ -600,11 +612,8 @@ export class SpProcessChart { let isIntersect = (a: any, b: any): boolean => Math.max(a.startTs + a.dur, b.startTs + b.dur) - Math.min(a.startTs, b.startTs) < a.dur + b.dur; let depthArray: any = []; - asyncFunctions.forEach((it, i) => { - if (it.dur === -1) { - it.dur = (TraceRow.range?.endNS || 0) - it.startTs; - it.flag = 'Did not end'; - } + asyncFunctions.forEach((it, i, arr) => { + this.modifyNofinishDur(it, i, arr); let currentDepth = 0; let index = i; while ( @@ -805,13 +814,10 @@ export class SpProcessChart { data.funName.toLowerCase().startsWith('binder reply')) ); }; - funs.forEach((fun) => { + funs.forEach((fun, i, arr) => { if (isBinder(fun)) { } else { - if (fun.dur === -1) { - fun.dur = (TraceRow.range?.totalNS || 0) - (fun.startTs || 0); - fun.flag = 'Did not end'; - } + this.modifyNofinishDur(fun, i, arr); } }); } else { diff --git a/ide/src/trace/component/chart/SpSegmentationChart.ts b/ide/src/trace/component/chart/SpSegmentationChart.ts index 37b93513b854c7bb5c56f8fa0880642b4499c518..e50d6777540650f9da9a26fe7b50141cf926b30e 100644 --- a/ide/src/trace/component/chart/SpSegmentationChart.ts +++ b/ide/src/trace/component/chart/SpSegmentationChart.ts @@ -94,7 +94,7 @@ export class SpSegmentationChart { BinderStruct.hoverCycle = -1; } } - SpSegmentationChart.trace.refreshCanvas(true, 'flagChange') + SpSegmentationChart.trace.refreshCanvas(false); } constructor(trace: SpSystemTrace) { diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index 58e521477c2b6768aa867d201e472dd2a6da897b..7cef081caba6f35314336a213194ffd45042066b 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -675,7 +675,7 @@ export let tabConfig: any = { type: TabPaneGpufreq, require: (param: SelectionParam) => param.clockMapData.size > 0 && param.clockMapData.size < 2, }, - 'tabpane-freqDataCut': { + 'tabpane-gpufreqDataCut': { 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/binder/TabPaneBinderDataCut.ts b/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts index 7201b9f204f75d4a152ff41d02db05c651e4427b..8f57f9c060afe0c9fbbd546805901b3fb6c50b94 100644 --- a/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts +++ b/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts @@ -28,7 +28,7 @@ import { querySingleFuncNameCycle, queryBinderByThreadId, queryLoopFuncNameCycle import { resizeObserver } from '../SheetUtils'; import { LitChartColumn } from '../../../../../base-ui/chart/column/LitChartColumn'; import '../../../../../base-ui/chart/column/LitChartColumn'; -// import { SpSegmentationChart } from '../../../chart/SpSegmentationChart'; +import { SpSegmentationChart } from '../../../chart/SpSegmentationChart'; @element('tabpane-binder-datacut') export class TabPaneBinderDataCut extends BaseElement { @@ -47,8 +47,10 @@ export class TabPaneBinderDataCut extends BaseElement { private funcNameCycleArr: FuncNameCycle[] | undefined; private cacheBinderArr: BinderGroup[] | undefined; private currentThreadId: string | undefined; + private cycleColumn: HTMLDivElement | null | undefined; set data(threadStatesParam: SelectionParam | any) { + this.parentElement!.style.overflow = 'hidden'; 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; @@ -62,6 +64,14 @@ export class TabPaneBinderDataCut extends BaseElement { this.currentSelectionParam = threadStatesParam; this.threadBindersTbl!.recycleDataSource = []; this.theadClick(this.threadBindersTbl!.recycleDataSource); + let flag = null; + if (!flag) { + flag = new ResizeObserver((entries) => { + // @ts-ignore + let lastHeight = this.threadBindersTbl.tableElement!.offsetHeight; + this.cycleColumn!.style.height = String(lastHeight) + 'px'; + }).observe(this.parentElement!); + } } dispalyQueryArea(b: boolean): void { @@ -98,7 +108,7 @@ export class TabPaneBinderDataCut extends BaseElement { let leftNS: number = this.currentSelectionParam.leftNs; let rightNS: number = this.currentSelectionParam.rightNs; if (threadIdValue !== '' && threadFuncName !== '') { - // SpSegmentationChart.setBinderChartData("BINDER", []); + SpSegmentationChart.setBinderChartData("BINDER", []); this.clickLoop(true); this.clickSingle(false); this.threadBindersTbl!.loading = true; @@ -152,7 +162,7 @@ export class TabPaneBinderDataCut extends BaseElement { let leftNS: number = this.currentSelectionParam.leftNs; let rightNS: number = this.currentSelectionParam.rightNs; if (threadIdValue !== '' && threadFuncName !== '') { - // SpSegmentationChart.setBinderChartData("BINDER", []); + SpSegmentationChart.setBinderChartData("BINDER", []); this.clickLoop(false); this.clickSingle(true); threadId.style.border = '1px solid rgb(151,151,151)'; @@ -493,6 +503,7 @@ export class TabPaneBinderDataCut extends BaseElement { 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.cycleColumn = this.shadowRoot?.querySelector('#cycleColumn'); this.threadStatesDIV = this.shadowRoot!.querySelector('#dataCut'); this.threadStatesDIV?.children[2].children[0].addEventListener('click', (e) => { @@ -530,14 +541,14 @@ export class TabPaneBinderDataCut extends BaseElement { let threaId = currentData.tid; let rowThreadBinderArr = this.findThreadByThreadId(this.cacheBinderArr!, threaId); let binderWithCountList: Array = this.binderWithCountList(rowThreadBinderArr!); - // SpSegmentationChart.setBinderChartData('BINDER', binderWithCountList); + 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); + SpSegmentationChart.tabHover('BINDER', true, currentData.idx); } }); @@ -641,6 +652,7 @@ export class TabPaneBinderDataCut extends BaseElement { } button{ width:40%; + min-width:90px; height:100%; border: solid 1px #666666; background-color: rgba(0,0,0,0); @@ -695,7 +707,7 @@ export class TabPaneBinderDataCut extends BaseElement { width:90px; } .cycle-range-input { - width: 120px; + width: 24%; height: 18px; padding: 1px 5px; border-radius: 12px; @@ -718,6 +730,7 @@ export class TabPaneBinderDataCut extends BaseElement { align-items: center; justify-content: center; margin-top:12px; + margin-bottom:20px; } .labels{ display: flex; @@ -734,7 +747,7 @@ export class TabPaneBinderDataCut extends BaseElement { margin-right: 5px; } .chart_area{ - margin-top:40px; + margin-top:20px; } .chart_title{ line-height: 40px; @@ -774,24 +787,22 @@ export class TabPaneBinderDataCut extends BaseElement { -
-
-
- Cycle A: - +
+
+ Cycle A: + + ~ + +
+
+
+ Cycle B: + ~ - +
-
-
- Cycle B: - - ~ - -
-
- -
+
+
diff --git a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts index d254dc4138650d4b64561097e1b4d7f1e4fe5cfd..1a44c571dc5b10d566d99507fcdb234a0007ec43 100644 --- a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts +++ b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts @@ -26,892 +26,1154 @@ import { LitChartScatter } from '../../../../../base-ui/chart/scatter/LitChartSc @element('tabpane-freqdatacut') export class TabPaneFreqDataCut extends BaseElement { - private threadStatesTbl: LitTable | null | undefined; - private threadStatesTblSource: Array = []; - private currentSelectionParam: SelectionParam | any; - private threadStatesDIV: HTMLDivElement | null | undefined; - private scatterInput: HTMLInputElement | null | undefined; - private initData: Map> = new Map(); - private processArr: Array = []; - private threadArr: Array = []; - private statisticsScatter: LitChartScatter | null | undefined; + private threadStatesTbl: LitTable | null | undefined; + private threadStatesTblSource: Array = []; + private currentSelectionParam: SelectionParam | any; + private threadStatesDIV: HTMLDivElement | null | undefined; + private scatterInput: HTMLInputElement | null | undefined; + private initData: Map> = new Map(); + private processArr: Array = []; + private threadArr: Array = []; + private statisticsScatter: LitChartScatter | null | undefined; - set data(threadStatesParam: SelectionParam | any) { - if (this.currentSelectionParam === threadStatesParam) { - return; - } - this.currentSelectionParam = threadStatesParam; - this.initData = new Map(); - this.threadArr = []; - this.initUI(); - this.init(threadStatesParam); - let pidArr: Array = []; - // 整理进程级的数组信息 - let processArr: Array = threadStatesParam.processIds.length > 1 ? [...new Set(threadStatesParam.processIds)] : threadStatesParam.processIds; - for (let i of processArr) { - pidArr.push(new TabPaneFreqUsageConfig(Utils.PROCESS_MAP.get(i) === null ? 'Process ' + i : Utils.PROCESS_MAP.get(i) + ' ' + i, '', i, '', 0, '', '', 0, '', 0, 'process', -1, [])); - } - // 拷贝给私有属性,以便后续进行数据切割时免除整理进程层级数据 - this.processArr = pidArr; + set data(threadStatesParam: SelectionParam) { + if (this.currentSelectionParam === threadStatesParam) { + return; } - /** - * 初始化数据 - */ - async init(threadStatesParam: SelectionParam | any): Promise { - let [runningData, sum]: Array = await this.queryRunningData(threadStatesParam); - let cpuFreqData: Array = await this.queryCpuFreqData(threadStatesParam); - if (runningData.size > 0) { - // 将cpu频点数据与running状态数据整合,保证其上该段时长内有对应的cpu频点数据 - this.mergeFreqData(runningData, cpuFreqData, sum); - this.threadStatesTbl!.loading = false; - } else { - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; - this.threadStatesTbl!.loading = false; - } + this.currentSelectionParam = threadStatesParam; + this.initData = new Map(); + this.threadArr = []; + this.initUI(); + this.init(threadStatesParam); + let pidArr: Array = []; + // 整理进程级的数组信息 + let processArr: Array = + threadStatesParam.processIds.length > 1 + ? [...new Set(threadStatesParam.processIds)] + : threadStatesParam.processIds; + for (let i of processArr) { + pidArr.push( + new TabPaneFreqUsageConfig( + Utils.PROCESS_MAP.get(i) === null ? 'Process ' + i : Utils.PROCESS_MAP.get(i) + ' ' + i, + '', i, '', 0, '', '', 0, '', 0, 'process', -1, []) + ); } - /** - * 重置UI输入框等组件为默认状态 - */ - initUI(): void { - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; - this.threadStatesTbl!.loading = true; - let tableValue: any = this.threadStatesTbl; - tableValue.value = []; - let divRoot1: any = this.shadowRoot?.querySelector('#dataCutThreadId'); - divRoot1.value = ''; - divRoot1.style.border = '1px solid rgb(151,151,151)'; - let divRoot2: any = this.shadowRoot?.querySelector('#dataCutThreadFunc'); - divRoot2.value = ''; - divRoot2.style.border = '1px solid rgb(151,151,151)'; - let divRoot3: any = this.shadowRoot?.querySelector('#maxFreq'); - divRoot3.style.border = '1px solid rgb(151,151,151)'; - let divRoot4: any = this.shadowRoot?.querySelector('#maxHz'); - divRoot4.style.border = '1px solid rgb(151,151,151)'; - let divRoot5: any = this.shadowRoot?.querySelector('#cycle-a-start-range'); - divRoot5.value = '' - let divRoot6: any = this.shadowRoot?.querySelector('#cycle-a-end-range'); - divRoot6.value = ''; - let divRoot7: any = this.shadowRoot?.querySelector('#cycle-b-start-range'); - divRoot7.value = ''; - let divRoot8: any = this.shadowRoot?.querySelector('#cycle-b-end-range'); - divRoot8.value = ''; - // @ts-ignore - this.shadowRoot?.querySelector('#cycleQuery')!.style.display = 'none'; - // @ts-ignore - this.statisticsScatter!.config = undefined; + // 拷贝给私有属性,以便后续进行数据切割时免除整理进程层级数据 + this.processArr = pidArr; + } + /** + * 初始化数据 + */ + async init(threadStatesParam: SelectionParam): Promise { + let {runningMap, sum}: { + runningMap: Map>, + sum: number + } + = await this.queryRunningData(threadStatesParam); + let cpuFreqData: Array = await this.queryCpuFreqData( + threadStatesParam + ); + if (runningMap.size > 0) { + // 将cpu频点数据与running状态数据整合,保证其上该段时长内有对应的cpu频点数据 + this.mergeFreqData(runningMap, cpuFreqData, sum); + this.threadStatesTbl!.loading = false; + } else { + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = false; } - /** - * 查询cpu频点信息 - */ - async queryCpuFreqData(threadStatesParam: SelectionParam | any): Promise> { - // 查询cpu及id信息 - let result: Array = await queryCpuFreqFilterId(); - // 以键值对形式将cpu及id进行对应,后续会将频点数据与其对应cpu进行整合 - let IdMap: Map = new Map(); - let queryId: Array = []; - for (let i = 0; i < result.length; i++) { - queryId.push(result[i].id); - IdMap.set(result[i].id, result[i].cpu); - } - let dealArr: Array = []; - // 通过id去查询频点数据 - let res: Array = await queryCpuFreqUsageData(queryId); - for (let i of res) { - let obj = new TabPaneCpuFreqConfig(i.startNS + threadStatesParam.recordStartNs, IdMap.get(i.filter_id)!, i.value, i.dur) - dealArr.push(obj); - } - return dealArr; + } + /** + * 重置UI输入框等组件为默认状态 + */ + initUI(): void { + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = true; + // @ts-ignore + this.threadStatesTbl.value = []; + // @ts-ignore + this.shadowRoot?.querySelector('#dataCutThreadId').style.border = '1px solid rgb(151,151,151)'; + // @ts-ignore + this.shadowRoot?.querySelector('#dataCutThreadFunc').style.border = '1px solid rgb(151,151,151)'; + // @ts-ignore + this.shadowRoot?.querySelector('#maxFreq').style.border = '1px solid rgb(151,151,151)'; + // @ts-ignore + this.shadowRoot?.querySelector('#maxHz').style.border = '1px solid rgb(151,151,151)'; + // @ts-ignore + this.shadowRoot?.querySelector('#cycle-a-start-range').value = ''; + // @ts-ignore + this.shadowRoot?.querySelector('#cycle-a-end-range').value = ''; + // @ts-ignore + this.shadowRoot?.querySelector('#cycle-b-start-range').value = ''; + // @ts-ignore + this.shadowRoot?.querySelector('#cycle-b-end-range').value = ''; + // @ts-ignore + this.shadowRoot?.querySelector('#cycleQuery')!.style.display = 'none'; + // @ts-ignore + this.statisticsScatter!.config = undefined; + this.parentElement!.style.overflow = 'hidden'; + } + /** + * 查询cpu频点信息 + */ + async queryCpuFreqData(threadStatesParam: SelectionParam): Promise> { + // 查询cpu及id信息 + let result: Array<{ id: number; cpu: number }> = await queryCpuFreqFilterId(); + // 以键值对形式将cpu及id进行对应,后续会将频点数据与其对应cpu进行整合 + let idMap: Map = new Map(); + let queryId: Array = []; + for (let i = 0; i < result.length; i++) { + queryId.push(result[i].id); + idMap.set(result[i].id, result[i].cpu); } + let dealArr: Array = []; + // 通过id去查询频点数据 + let res: Array<{ + startNS: number; + filter_id: number; + value: number; + dur: number} + > = await queryCpuFreqUsageData(queryId); + for (let i of res) { + dealArr.push( + new TabPaneCpuFreqConfig( + i.startNS + threadStatesParam.recordStartNs, + idMap.get(i.filter_id)!, + i.value, + i.dur + )); + } + return dealArr; + } - /** - * 查询框选区域内的所有running状态数据 - */ - async queryRunningData(threadStatesParam: SelectionParam | any): Promise> { - let result: Array = await getTabRunningPercent(threadStatesParam.threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs); - let needDeal: Map> = new Map(), sum: number = 0; - if (result != null && result.length > 0) { - let processArr: Array = threadStatesParam.processIds.length > 1 ? [...new Set(threadStatesParam.processIds)] : threadStatesParam.processIds; - for (let e of result) { - if (processArr.includes(e.pid)) { - if (needDeal.get(e.pid + '_' + e.tid) === undefined) { - this.threadArr.push(new TabPaneFreqUsageConfig(Utils.THREAD_MAP.get(e.tid) + ' ' + e.tid, '', e.pid, e.tid, 0, '', '', 0, '', 0, 'thread', -1, [])); - needDeal.set(e.pid + '_' + e.tid, new Array()); - } - if ((e.ts < (threadStatesParam.leftNs + threadStatesParam.recordStartNs)) && ((e.ts + e.dur) > (threadStatesParam.leftNs + threadStatesParam.recordStartNs))) { - const ts = e.ts; - e.ts = threadStatesParam.leftNs + threadStatesParam.recordStartNs; - e.dur = ts + e.dur - (threadStatesParam.leftNs + threadStatesParam.recordStartNs); - } - if ((e.ts + e.dur) > (threadStatesParam.rightNs + threadStatesParam.recordStartNs)) { - e.dur = threadStatesParam.rightNs + threadStatesParam.recordStartNs - e.ts; - } - 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; - let arr: any = needDeal.get(e.pid + '_' + e.tid); - sum += e.dur; - arr.push(e); - } - } + /** + * 查询框选区域内的所有running状态数据 + */ + async queryRunningData(threadStatesParam: SelectionParam): + Promise<{runningMap: Map>; sum: number}> { + let result: Array<{ + pid: number; + tid: number; + cpu: number; + dur: number; + ts: number; + process: string; + thread: string; + }> = await getTabRunningPercent(threadStatesParam.threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs); + let needDeal: Map> = new Map(); + let sum: number = 0; + if (result !== null && result.length > 0) { + let processArr: Array = threadStatesParam.processIds.length > 1 + ? [...new Set(threadStatesParam.processIds)] : threadStatesParam.processIds; + for (let e of result) { + if (processArr.includes(e.pid)) { + if (needDeal.get(e.pid + '_' + e.tid) === undefined) { + this.threadArr.push( + new TabPaneFreqUsageConfig(Utils.THREAD_MAP.get(e.tid) + ' ' + e.tid, + '', e.pid, e.tid, 0, '', '', 0, '', 0, 'thread', -1, []) + ); + needDeal.set(e.pid + '_' + e.tid, new Array()); + } + if (e.ts < threadStatesParam.leftNs + threadStatesParam.recordStartNs && + e.ts + e.dur > threadStatesParam.leftNs + threadStatesParam.recordStartNs) { + const ts = e.ts; + e.ts = threadStatesParam.leftNs + threadStatesParam.recordStartNs; + e.dur = ts + e.dur - (threadStatesParam.leftNs + threadStatesParam.recordStartNs); + } + if (e.ts + e.dur > threadStatesParam.rightNs + threadStatesParam.recordStartNs) { + e.dur = threadStatesParam.rightNs + threadStatesParam.recordStartNs - e.ts; + } + e.process = Utils.PROCESS_MAP.get(e.pid) === null ? '[NULL]' : Utils.PROCESS_MAP.get(e.pid)!; + e.thread = Utils.THREAD_MAP.get(e.tid) === null ? '[NULL]' : Utils.THREAD_MAP.get(e.tid)!; + let arr: Array<{ + pid: number; + tid: number; + cpu: number; + dur: number; + ts: number; + process: string; + thread: string; + }> | undefined = needDeal.get(e.pid + '_' + e.tid); + sum += e.dur; + arr?.push(e); } - return [needDeal, sum]; + } } + return {'runningMap': needDeal, 'sum': sum}; + } - /** - * 将cpu频点数据与running状态数据整合,保证其上该段时长内有对应的cpu频点数据 - */ - mergeFreqData(needDeal: Map>, dealArr: Array, sum: number): void { - needDeal.forEach((value: Array, key: string) => { - let resultList: Array = []; - for (let i = 0; i < value.length; i++) { - for (let j = 0; j < dealArr.length; j++) { - // 只需要判断running状态数据与频点数据cpu相同的情况 - if (value[i].cpu === dealArr[j].cpu) { - // running状态数据的开始时间大于频点数据开始时间,小于频点结束时间。且running状态数据的持续时间小于频点结束时间减去running状态数据开始时间的情况 - if (value[i].ts > dealArr[j].startNS && value[i].ts < (dealArr[j].startNS + dealArr[j].dur) && value[i].dur < (dealArr[j].startNS + dealArr[j].dur - value[i].ts)) { - resultList.push(new TabPaneFreqUsageConfig(value[i].thread, value[i].ts, value[i].pid, value[i].tid, 0, value[i].cpu, dealArr[j].value, value[i].dur, '', value[i].dur / sum * 100, 'freqdata', -1, undefined)); - break; - } - // running状态数据的开始时间大于频点数据开始时间,小于频点结束时间。且running状态数据的持续时间大于频点结束时间减去running状态数据开始时间的情况 - if (value[i].ts > dealArr[j].startNS && value[i].ts < (dealArr[j].startNS + dealArr[j].dur) && value[i].dur > (dealArr[j].startNS + dealArr[j].dur - value[i].ts)) { - resultList.push(new TabPaneFreqUsageConfig(value[i].thread, value[i].ts, value[i].pid, value[i].tid, 0, value[i].cpu, dealArr[j].value, (dealArr[j].startNS + dealArr[j].dur - value[i].ts), '', (dealArr[j].startNS + dealArr[j].dur - value[i].ts) / sum * 100, 'freqdata', -1, undefined)); - } - // running状态数据的开始时间小于频点数据开始时间,running状态数据的结束时间大于频点数据开始时间。且running状态数据在频点数据开始时间后的持续时间小于频点数据持续时间的情况 - if (value[i].ts < dealArr[j].startNS && (value[i].ts + value[i].dur) > dealArr[j].startNS && (value[i].dur + value[i].ts - dealArr[j].startNS) < dealArr[j].dur) { - resultList.push(new TabPaneFreqUsageConfig(value[i].thread, dealArr[j].startNS, value[i].pid, value[i].tid, 0, value[i].cpu, dealArr[j].value, (value[i].dur + value[i].ts - dealArr[j].startNS), '', (value[i].dur + value[i].ts - dealArr[j].startNS) / sum * 100, 'freqdata', -1, undefined)); - break; - } - // running状态数据的开始时间小于频点数据开始时间,running状态数据的结束时间大于频点数据开始时间。且running状态数据在频点数据开始时间后的持续时间大于频点数据持续时间的情况 - if (value[i].ts < dealArr[j].startNS && (value[i].ts + value[i].dur) > dealArr[j].startNS && (value[i].dur + value[i].ts - dealArr[j].startNS) > dealArr[j].dur) { - resultList.push(new TabPaneFreqUsageConfig(value[i].thread, dealArr[j].startNS, value[i].pid, value[i].tid, 0, value[i].cpu, dealArr[j].value, dealArr[j].dur, '', dealArr[j].dur / sum * 100, 'freqdata', -1, undefined)); - } - // running状态数据的开始时间小于频点数据开始时间,running状态数据的持续时间小于频点数据开始时间的情况 - if (value[i].ts < dealArr[j].startNS && (value[i].ts + value[i].dur) < dealArr[j].startNS) { - resultList.push(new TabPaneFreqUsageConfig(value[i].thread, value[i].ts, value[i].pid, value[i].tid, 0, value[i].cpu, 'unknown', value[i].dur, '', value[i].dur / sum * 100, 'freqdata', -1, undefined)); - break; - } - } - } + /** + * 将cpu频点数据与running状态数据整合,保证其上该段时长内有对应的cpu频点数据 + */ + mergeFreqData( + needDeal: Map>, + dealArr: Array, + sum: number + ): void { + needDeal.forEach((value: Array, key: string) => { + let resultList: Array = []; + for (let i = 0; i < value.length; i++) { + for (let j = 0; j < dealArr.length; j++) { + // 只需要判断running状态数据与频点数据cpu相同的情况 + if (value[i].cpu === dealArr[j].cpu) { + // running状态数据的开始时间大于频点数据开始时间,小于频点结束时间。且running状态数据的持续时间小于频点结束时间减去running状态数据开始时间的情况 + if (value[i].ts > dealArr[j].startNS && + value[i].ts < dealArr[j].startNS + dealArr[j].dur && + value[i].dur < dealArr[j].startNS + dealArr[j].dur - value[i].ts) { + resultList.push(new TabPaneFreqUsageConfig(value[i].thread, value[i].ts, value[i].pid, + value[i].tid, 0, value[i].cpu,dealArr[j].value, value[i].dur, '', (value[i].dur / sum) * 100, + 'freqdata', -1, undefined)); + break; } - this.initData.set(key, resultList); - }) - } - /** - * single方式切割数据功能 - */ - dataSingleCut(threadId: HTMLInputElement, threadFunc: HTMLInputElement, resultList: Map>): void { - threadId.style.border = '1px solid rgb(151,151,151)'; - threadFunc.style.border = '1px solid rgb(151,151,151)'; - let threadIdValue = threadId.value.trim(); - let threadFuncName = threadFunc.value.trim(); - let leftNS = this.currentSelectionParam.leftNs; - let rightNS = this.currentSelectionParam.rightNs; - let tableValue: any = this.threadStatesTbl; - tableValue.value = []; - if (threadIdValue != '' && threadFuncName != '') { - // 根据用户输入的线程ID,方法名去查询数据库,得到对应的方法起始时间,持续时间等数据,以便作为依据进行后续数据切割 - querySearchFuncData(threadFuncName, Number(threadIdValue), leftNS, rightNS).then(result => { - if (result != null && result.length > 0) { - // targetMap为全局initData的拷贝对象,dealArr数组用来存放周期切割依据数据 - let targetMap: Map> = new Map(), dealArr: Array = []; - // 新创建map对象接收传过来的实参map - resultList.forEach((item: Array, key: string) => { - targetMap.set(key, JSON.parse(JSON.stringify(item))); - }) - // 整理周期切割依据的数据 - for (let i of result) { - if (i.startTime + this.currentSelectionParam.recordStartNs + i.dur < this.currentSelectionParam.rightNs + this.currentSelectionParam.recordStartNs) { - dealArr.push({ 'ts': i.startTime + this.currentSelectionParam.recordStartNs, 'dur': i.dur }); - } - } - let cycleMap: Map> = new Map(), totalList: Map> = new Map(); - this.mergeSingleData(dealArr, targetMap, cycleMap, totalList); - // 拷贝线程数组,防止数据污染 - let threadArr = JSON.parse(JSON.stringify(this.threadArr)); - // 拷贝进程数组,防止数据污染 - let processArr = JSON.parse(JSON.stringify(this.processArr)); - // 将周期层级防止到线程层级下 - this.mergeThreadData(threadArr, cycleMap); - // 将原始数据放置到对应的线程层级下,周期数据前 - let totalData = this.merge(totalList); - this.mergeTotalData(threadArr, totalData); - // 合并数据到进程层级下 - this.mergePidData(processArr, threadArr); - this.fixedDeal(processArr); - this.threadStatesTblSource = processArr; - this.threadStatesTbl!.recycleDataSource = processArr; - this.threadStatesTbl!.loading = false; - this.threadClick(processArr); - } else { - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; - this.threadStatesTbl!.loading = false; - } - }) - } else { - this.threadStatesTbl!.loading = false; - if (threadIdValue == '') { - threadId.style.border = '2px solid rgb(255,0,0)'; + // running状态数据的开始时间大于频点数据开始时间,小于频点结束时间。且running状态数据的持续时间大于频点结束时间减去running状态数据开始时间的情况 + if (value[i].ts > dealArr[j].startNS && + value[i].ts < dealArr[j].startNS + dealArr[j].dur && + value[i].dur > dealArr[j].startNS + dealArr[j].dur - value[i].ts) { + resultList.push(new TabPaneFreqUsageConfig(value[i].thread, value[i].ts, value[i].pid, + value[i].tid, 0, value[i].cpu, dealArr[j].value, dealArr[j].startNS + dealArr[j].dur - value[i].ts, '', + ((dealArr[j].startNS + dealArr[j].dur - value[i].ts) / sum) * 100, 'freqdata', -1, undefined)); + } + // running状态数据的开始时间小于频点数据开始时间,running状态数据的结束时间大于频点数据开始时间。且running状态数据在频点数据开始时间后的持续时间小于频点数据持续时间的情况 + if (value[i].ts < dealArr[j].startNS && + value[i].ts + value[i].dur > dealArr[j].startNS && + value[i].dur + value[i].ts - dealArr[j].startNS < dealArr[j].dur) { + resultList.push(new TabPaneFreqUsageConfig(value[i].thread, dealArr[j].startNS, value[i].pid, + value[i].tid, 0, value[i].cpu, dealArr[j].value, value[i].dur + value[i].ts - dealArr[j].startNS, '', + ((value[i].dur + value[i].ts - dealArr[j].startNS) / sum) * 100, 'freqdata', -1, undefined )); + break; + } + // running状态数据的开始时间小于频点数据开始时间,running状态数据的结束时间大于频点数据开始时间。且running状态数据在频点数据开始时间后的持续时间大于频点数据持续时间的情况 + if (value[i].ts < dealArr[j].startNS && + value[i].ts + value[i].dur > dealArr[j].startNS && + value[i].dur + value[i].ts - dealArr[j].startNS > dealArr[j].dur) { + resultList.push(new TabPaneFreqUsageConfig( value[i].thread, dealArr[j].startNS, value[i].pid, value[i].tid, + 0, value[i].cpu, dealArr[j].value, dealArr[j].dur, '', (dealArr[j].dur / sum) * 100, 'freqdata', -1, undefined)); } - if (threadFuncName == '') { - threadFunc.style.border = '2px solid rgb(255,0,0)'; + // running状态数据的开始时间小于频点数据开始时间,running状态数据的持续时间小于频点数据开始时间的情况 + if (value[i].ts < dealArr[j].startNS && value[i].ts + value[i].dur < dealArr[j].startNS) { + resultList.push(new TabPaneFreqUsageConfig(value[i].thread, value[i].ts, value[i].pid, value[i].tid, + 0, value[i].cpu, 'unknown', value[i].dur, '', (value[i].dur / sum) * 100, 'freqdata', -1, undefined)); + break; } + } } - } - /** - * 整合Single切割方式中的频点数据与方法周期数据 - */ - mergeSingleData(dealArr: Array, targetMap: Map>, cycleMap: Map>, totalList: Map>): void { - let timeDur = this.currentSelectionParam.recordStartNs; - targetMap.forEach((value, key) => { - cycleMap.set(key, new Array()); - totalList.set(key, new Array()); - for (let i = 0; i < dealArr.length; i++) { - let cpuArr: Array = [], resList: Array = [], cpuMap: Map> = new Map(); - // 时间倍数值 - const countMutiple = 1000000; - cpuMap.set(key, new Array()); - cycleMap.get(key)?.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[0].thread, ((dealArr[i].ts - timeDur) / 1000000).toFixed(3), '', '', 0, '', '', 0, (dealArr[i].dur / 1000000).toFixed(3), 0, 'cycle', i + 1, [])); - for (let j = 0; j < value.length; j++) { - // 判断若用户导入json文件,则替换为对应cpu下的对应频点的算力值进行算力消耗计算 - let consumptionMap: Map | undefined ; - if (SpSegmentationChart.freqInfoMapData.size > 0 ) { - consumptionMap = SpSegmentationChart.freqInfoMapData.get(value[j].cpu); - } - - // 若存在算力值,则直接取值做计算。若不存在算力值,且频点值不为unknown的情况,则取频点值做计算,若为unknown,则取0做兼容 - const consumption = (consumptionMap && consumptionMap.get(value[j].freq)) ? consumptionMap.get(value[j].freq) : (value[j].freq == 'unknown' ? 0 : value[j].freq); - if (!cpuArr.includes(value[j].cpu)) { - cpuArr.push(value[j].cpu); - cpuMap.get(key)?.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, 0, value[j].cpu, '', 0, '', 0, 'cpu', -1, [])); - } - // 以下为频点数据按Single周期切割数据如何取舍的判断条件,dealArr为周期切割依据,value为某一线程下的频点汇总数据 - // 如果频点数据开始时间大于某一周期起始时间,小于该周期的结束时间。且频点数据结束时间小于周期结束时间的情况 - if (dealArr[i].ts < value[j].ts && dealArr[i].ts + dealArr[i].dur > value[j].ts && dealArr[i].ts + dealArr[i].dur > value[j].ts + value[j].dur) { - resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, (consumption * value[j].dur) / countMutiple, value[j].cpu, value[j].freq, value[j].dur, '', value[j].percent, 'freqdata', i, undefined)); - totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, (consumption * value[j].dur) / countMutiple, value[j].cpu, value[j].freq, value[j].dur, '', value[j].percent, 'freqdata', i, undefined)); - } - // 如果频点数据开始时间大于某一周期起始时间,小于该周期的结束时间。且频点数据结束时间大于等于周期结束时间的情况 - if (dealArr[i].ts < value[j].ts && dealArr[i].ts + dealArr[i].dur > value[j].ts && dealArr[i].ts + dealArr[i].dur <= value[j].ts + value[j].dur) { - resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, (dealArr[i].ts + dealArr[i].dur - value[j].ts) * consumption / countMutiple, value[j].cpu, value[j].freq, dealArr[i].ts + dealArr[i].dur - value[j].ts, '', (dealArr[i].ts + dealArr[i].dur - value[j].ts) / value[j].dur * value[j].percent, 'freqdata', i, undefined)); - totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, (dealArr[i].ts + dealArr[i].dur - value[j].ts) * consumption / countMutiple, value[j].cpu, value[j].freq, dealArr[i].ts + dealArr[i].dur - value[j].ts, '', (dealArr[i].ts + dealArr[i].dur - value[j].ts) / value[j].dur * value[j].percent, 'freqdata', i, undefined)); - break; - } - // 如果频点数据开始时间小于某一周期起始时间,结束时间大于该周期的开始时间。且频点数据结束时间大于周期结束时间的情况 - if (dealArr[i].ts > value[j].ts && value[j].ts + value[j].dur > dealArr[i].ts && value[j].ts + value[j].dur > dealArr[i].ts + dealArr[i].dur) { - resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, dealArr[i].dur * consumption / countMutiple, value[j].cpu, value[j].freq, dealArr[i].dur, '', dealArr[i].dur / value[j].dur * value[j].percent, 'freqdata', i, undefined)); - totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, dealArr[i].dur * consumption / countMutiple, value[j].cpu, value[j].freq, dealArr[i].dur, '', dealArr[i].dur / value[j].dur * value[j].percent, 'freqdata', i, undefined)); - break; - } - // 如果频点数据开始时间小于某一周期起始时间,结束时间大于该周期的开始时间。且频点数据结束时间小于等于周期结束时间的情况 - if (dealArr[i].ts > value[j].ts && value[j].ts + value[j].dur > dealArr[i].ts && value[j].ts + value[j].dur <= dealArr[i].ts + dealArr[i].dur) { - resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, (value[j].ts + value[j].dur - dealArr[i].ts) * consumption / countMutiple, value[j].cpu, value[j].freq, value[j].ts + value[j].dur - dealArr[i].ts, '', (value[j].ts + value[j].dur - dealArr[i].ts) / value[j].dur * value[j].percent, 'freqdata', i, undefined)); - totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, (value[j].ts + value[j].dur - dealArr[i].ts) * consumption / countMutiple, value[j].cpu, value[j].freq, value[j].ts + value[j].dur - dealArr[i].ts, '', (value[j].ts + value[j].dur - dealArr[i].ts) / value[j].dur * value[j].percent, 'freqdata', i, undefined)); - } - } - this.mergeData(resList); - // 整理排序相同周期下的数据 - this.mergeCpuData(cpuMap.get(key)!, resList); - // 将cpu数据放置到对应周期层级下 - this.mergeCycleData(cycleMap.get(key)![i], cpuMap.get(key)); + } + this.initData.set(key, resultList); + }); + } + /** + * single方式切割数据功能 + */ + dataSingleCut( + threadId: HTMLInputElement, + threadFunc: HTMLInputElement, + resultList: Map> + ): void { + let threadIdValue: string = threadId.value.trim(); + let threadFuncName: string = threadFunc.value.trim(); + let leftNS: number = this.currentSelectionParam.leftNs; + let rightNS: number = this.currentSelectionParam.rightNs; + // @ts-ignore + this.threadStatesTbl.value = []; + if (threadIdValue !== '' && threadFuncName !== '') { + // 根据用户输入的线程ID,方法名去查询数据库,得到对应的方法起始时间,持续时间等数据,以便作为依据进行后续数据切割 + querySearchFuncData(threadFuncName, Number(threadIdValue), leftNS, rightNS).then((result) => { + if (result !== null && result.length > 0) { + // targetMap为全局initData的拷贝对象,dealArr数组用来存放周期切割依据数据 + let targetMap: Map> = new Map(); + let dealArr: Array = []; + // 新创建map对象接收传过来的实参map + resultList.forEach((item: Array, key: string) => { + targetMap.set(key, JSON.parse(JSON.stringify(item))); + }); + // 整理周期切割依据的数据 + for (let i of result) { + if ( + i.startTime + this.currentSelectionParam.recordStartNs + i.dur < + this.currentSelectionParam.rightNs + this.currentSelectionParam.recordStartNs) { + dealArr.push({ts: i.startTime + this.currentSelectionParam.recordStartNs, dur: i.dur}); } - }); + } + let cycleMap: Map> = new Map(); + let totalList: Map> = new Map(); + this.mergeSingleData(dealArr, targetMap, cycleMap, totalList); + // 拷贝线程数组,防止数据污染 + let threadArr: Array = JSON.parse(JSON.stringify(this.threadArr)); + // 拷贝进程数组,防止数据污染 + let processArr: Array = JSON.parse(JSON.stringify(this.processArr)); + // 将周期层级防止到线程层级下 + this.mergeThreadData(threadArr, cycleMap); + // 将原始数据放置到对应的线程层级下,周期数据前 + let totalData = this.merge(totalList); + this.mergeTotalData(threadArr, totalData); + // 合并数据到进程层级下 + this.mergePidData(processArr, threadArr); + this.fixedDeal(processArr); + this.threadStatesTblSource = processArr; + this.threadStatesTbl!.recycleDataSource = processArr; + this.threadStatesTbl!.loading = false; + this.threadClick(processArr); + } else { + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = false; + } + }); + } else { + this.threadStatesTbl!.loading = false; + if (threadIdValue === '') { + threadId.style.border = '2px solid rgb(255,0,0)'; + } + if (threadFuncName === '') { + threadFunc.style.border = '2px solid rgb(255,0,0)'; + } } - /** - * Loop方式切割数据功能 - */ - dataLoopCut(threadId: HTMLInputElement, threadFunc: HTMLInputElement, resultList: Map>): void { - threadId.style.border = '1px solid rgb(151,151,151)'; - threadFunc.style.border = '1px solid rgb(151,151,151)'; - let threadIdValue = threadId!.value.trim(); - let threadFuncName = threadFunc.value.trim(); - let leftNS = this.currentSelectionParam.leftNs; - let rightNS = this.currentSelectionParam.rightNs; - let tableValue: any = this.threadStatesTbl; - tableValue.value = []; - if (threadIdValue !== '' && threadFuncName !== '') { - querySearchFuncData(threadFuncName, Number(threadIdValue), leftNS, rightNS).then(res => { - if (res !== null && res.length > 0) { - // targetMap为全局initData的拷贝对象,cutArr数组用来存放周期切割依据数据 - let targetMap: Map> = new Map(), cutArr: Array = []; - // 新创建map对象接收传过来的实参map - resultList.forEach((item: Array, key: string) => { - targetMap.set(key, JSON.parse(JSON.stringify(item))); - }) - // 根据线程id及方法名获取的数据,处理后用作切割时间依据,时间跨度为整个方法开始时间到末个方法开始时间 - for (let i of res) { - cutArr[cutArr.length - 1] && (cutArr[cutArr.length - 1].dur = i.startTime ? i.startTime + this.currentSelectionParam.recordStartNs - cutArr[cutArr.length - 1].ts : 0); - cutArr.push({ 'ts': i.startTime + this.currentSelectionParam.recordStartNs }); - } - let cycleMap: Map> = new Map(); - let totalList: Map> = new Map(); - this.mergeLoopData(cutArr, targetMap, cycleMap, totalList); - let threadArr: Array = JSON.parse(JSON.stringify(this.threadArr)); - let processArr: Array = JSON.parse(JSON.stringify(this.processArr)); - this.mergeThreadData(threadArr, cycleMap); - let totalData = this.merge(totalList); - this.mergeTotalData(threadArr, totalData); - this.mergePidData(processArr, threadArr); - this.fixedDeal(processArr); - this.threadStatesTblSource = processArr; - this.threadStatesTbl!.recycleDataSource = processArr; - this.threadStatesTbl!.loading = false; - this.threadClick(processArr); - } else { - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; - this.threadStatesTbl!.loading = false; - } - }) + } + /** + * 整合Single切割方式中的频点数据与方法周期数据 + */ + mergeSingleData( + dealArr: Array<{ts: number, dur: number}>, + targetMap: Map>, + cycleMap: Map>, + totalList: Map> + ): void { + let timeDur = this.currentSelectionParam.recordStartNs; + targetMap.forEach((value: any, key) => { + cycleMap.set(key, new Array()); + totalList.set(key, new Array()); + for (let i = 0; i < dealArr.length; i++) { + let cpuArr: Array = []; + let resList: Array = []; + let cpuMap: Map> = new Map(); + // 时间倍数值 + const countMutiple: number = 1000000; + cpuMap.set(key, new Array()); + cycleMap.get(key)?.push( + new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[0].thread, + ((dealArr[i].ts - timeDur) / 1000000).toFixed(3), key.split('_')[0], key.split('_')[1], + 0, '', '', 0, (dealArr[i].dur / 1000000).toFixed(3), 0, 'cycle', i + 1, [] )); + for (let j = 0; j < value.length; j++) { + // 判断若用户导入json文件,则替换为对应cpu下的对应频点的算力值进行算力消耗计算 + // @ts-ignore + let consumptionMap: Map = + SpSegmentationChart.freqInfoMapData.size > 0 && SpSegmentationChart.freqInfoMapData.get(value[j].cpu); + // 若存在算力值,则直接取值做计算。若不存在算力值,且频点值不为unknown的情况,则取频点值做计算,若为unknown,则取0做兼容 + const consumption: number = consumptionMap && consumptionMap.get(value[j].freq) + ? consumptionMap.get(value[j].freq) : (value[j].freq === 'unknown' ? 0 : value[j].freq); + if (!cpuArr.includes(value[j].cpu)) { + cpuArr.push(value[j].cpu); + cpuMap.get(key)?.push( + new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', + value[j].pid, value[j].tid, 0, value[j].cpu, '', 0, '', 0, 'cpu', -1, [])); + } + // 以下为频点数据按Single周期切割数据如何取舍的判断条件,dealArr为周期切割依据,value为某一线程下的频点汇总数据 + // 如果频点数据开始时间大于某一周期起始时间,小于该周期的结束时间。且频点数据结束时间小于周期结束时间的情况 + if (dealArr[i].ts < value[j].ts && + dealArr[i].ts + dealArr[i].dur > value[j].ts && + dealArr[i].ts + dealArr[i].dur > value[j].ts + value[j].dur) { + resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', + value[j].pid, value[j].tid, (consumption * value[j].dur) / countMutiple, value[j].cpu, + value[j].freq, value[j].dur, '', value[j].percent, 'freqdata', i, undefined)); + totalList.get(key)?.push(new TabPaneFreqUsageConfig( + value[j].thread, '', value[j].pid, value[j].tid, (consumption * value[j].dur) / countMutiple, + value[j].cpu, value[j].freq, value[j].dur, '', value[j].percent, 'freqdata', i, undefined)); + } + // 如果频点数据开始时间大于某一周期起始时间,小于该周期的结束时间。且频点数据结束时间大于等于周期结束时间的情况 + if (dealArr[i].ts < value[j].ts && + dealArr[i].ts + dealArr[i].dur > value[j].ts && + dealArr[i].ts + dealArr[i].dur <= value[j].ts + value[j].dur) { + resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread,'', + value[j].pid, value[j].tid, ((dealArr[i].ts + dealArr[i].dur - value[j].ts) * consumption) / countMutiple, + value[j].cpu, value[j].freq, dealArr[i].ts + dealArr[i].dur - value[j].ts, '', + ((dealArr[i].ts + dealArr[i].dur - value[j].ts) / value[j].dur) * value[j].percent, + 'freqdata', i, undefined)); + totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, + ((dealArr[i].ts + dealArr[i].dur - value[j].ts) * consumption) / countMutiple, value[j].cpu, + value[j].freq, dealArr[i].ts + dealArr[i].dur - value[j].ts, '', + ((dealArr[i].ts + dealArr[i].dur - value[j].ts) / value[j].dur) * value[j].percent, + 'freqdata', i, undefined)); + break; + } + // 如果频点数据开始时间小于某一周期起始时间,结束时间大于该周期的开始时间。且频点数据结束时间大于周期结束时间的情况 + if (dealArr[i].ts > value[j].ts && + value[j].ts + value[j].dur > dealArr[i].ts && + value[j].ts + value[j].dur > dealArr[i].ts + dealArr[i].dur) { + resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, + '', value[j].pid, value[j].tid, (dealArr[i].dur * consumption) / countMutiple, value[j].cpu, + value[j].freq, dealArr[i].dur, '', (dealArr[i].dur / value[j].dur) * value[j].percent, + 'freqdata', i, undefined)); + totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, + (dealArr[i].dur * consumption) / countMutiple, value[j].cpu, value[j].freq, dealArr[i].dur, '', + (dealArr[i].dur / value[j].dur) * value[j].percent, 'freqdata', i, undefined)); + break; + } + // 如果频点数据开始时间小于某一周期起始时间,结束时间大于该周期的开始时间。且频点数据结束时间小于等于周期结束时间的情况 + if (dealArr[i].ts > value[j].ts && + value[j].ts + value[j].dur > dealArr[i].ts && + value[j].ts + value[j].dur <= dealArr[i].ts + dealArr[i].dur) { + resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread,'', + value[j].pid, value[j].tid, ((value[j].ts + value[j].dur - dealArr[i].ts) * consumption) / countMutiple, + value[j].cpu, value[j].freq, value[j].ts + value[j].dur - dealArr[i].ts, '', + ((value[j].ts + value[j].dur - dealArr[i].ts) / value[j].dur) * value[j].percent, 'freqdata', i, undefined)); + totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, + ((value[j].ts + value[j].dur - dealArr[i].ts) * consumption) / countMutiple, value[j].cpu, value[j].freq, + value[j].ts + value[j].dur - dealArr[i].ts, '', ((value[j].ts + value[j].dur - dealArr[i].ts) / value[j].dur) * + value[j].percent, 'freqdata', i, undefined)); + } + } + this.mergeData(resList); + // 整理排序相同周期下的数据 + this.mergeCpuData(cpuMap.get(key)!, resList); + // 将cpu数据放置到对应周期层级下 + this.mergeCycleData(cycleMap.get(key)![i], cpuMap.get(key)!); + } + }); + } + + /** + * Loop方式切割数据功能 + */ + dataLoopCut( + threadId: HTMLInputElement, + threadFunc: HTMLInputElement, + resultList: Map> + ): void { + let threadIdValue = threadId.value.trim(); + let threadFuncName = threadFunc.value.trim(); + let leftNS = this.currentSelectionParam.leftNs; + let rightNS = this.currentSelectionParam.rightNs; + // @ts-ignore + this.threadStatesTbl.value = []; + if (threadIdValue !== '' && threadFuncName !== '') { + querySearchFuncData(threadFuncName, Number(threadIdValue), leftNS, rightNS).then((res) => { + if (res !== null && res.length > 0) { + // targetMap为全局initData的拷贝对象,cutArr数组用来存放周期切割依据数据 + let targetMap: Map> = new Map(); + let cutArr: Array = []; + // 新创建map对象接收传过来的实参map + resultList.forEach((item: Array, key: string) => { + targetMap.set(key, JSON.parse(JSON.stringify(item))); + }); + // 根据线程id及方法名获取的数据,处理后用作切割时间依据,时间跨度为整个方法开始时间到末个方法开始时间 + for (let i of res) { + cutArr[cutArr.length - 1] && (cutArr[cutArr.length - 1].dur = i.startTime ? i.startTime + + this.currentSelectionParam.recordStartNs - cutArr[cutArr.length - 1].ts : 0); + cutArr.push({ts: i.startTime + this.currentSelectionParam.recordStartNs}); + } + let cycleMap: Map> = new Map(); + let totalList: Map> = new Map(); + this.mergeLoopData(cutArr, targetMap, cycleMap, totalList); + let threadArr: Array = JSON.parse(JSON.stringify(this.threadArr)); + let processArr: Array = JSON.parse(JSON.stringify(this.processArr)); + this.mergeThreadData(threadArr, cycleMap); + let totalData = this.merge(totalList); + this.mergeTotalData(threadArr, totalData); + this.mergePidData(processArr, threadArr); + this.fixedDeal(processArr); + this.threadStatesTblSource = processArr; + this.threadStatesTbl!.recycleDataSource = processArr; + this.threadStatesTbl!.loading = false; + this.threadClick(processArr); } else { - this.threadStatesTbl!.loading = false; - if (threadIdValue === '') { - threadId.style.border = '2px solid rgb(255,0,0)'; - } - if (threadFuncName === '') { - threadFunc.style.border = '2px solid rgb(255,0,0)'; - } + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = false; } + }); + } else { + this.threadStatesTbl!.loading = false; + if (threadIdValue === '') { + threadId.style.border = '2px solid rgb(255,0,0)'; + } + if (threadFuncName === '') { + threadFunc.style.border = '2px solid rgb(255,0,0)'; + } } - /** - * 整合Loop切割方式中的频点数据与方法周期数据 - */ - mergeLoopData(cutArr: Array, targetMap: Map>, cycleMap: Map>, totalList: Map>): void { - let timeDur: number = this.currentSelectionParam.recordStartNs; - targetMap.forEach((value, key) => { - cycleMap.set(key, new Array()); - totalList.set(key, new Array()); - for (let i = 0; i < cutArr.length - 1; i++) { - let cpuArr: Array = [], resList: Array = [], cpuMap: Map> = new Map(); - // 时间倍数值 - const countMutiple = 1000000; - cpuMap.set(key, new Array()); - // 创建周期层级数据 - cycleMap.get(key)?.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[0].thread, ((cutArr[i].ts - timeDur) / 1000000).toFixed(3), '', '', 0, '', '', 0, (cutArr[i].dur / 1000000).toFixed(3), 0, 'cycle', i + 1, [])); - for (let j = 0; j < value.length; j++) { - // 判断若用户导入json文件,则替换为对应cpu下的对应频点的算力值进行算力消耗计算 - let consumptionMap: Map | undefined; - if (SpSegmentationChart.freqInfoMapData.size > 0){ - consumptionMap = SpSegmentationChart.freqInfoMapData.get(value[j].cpu); - } - // 若存在算力值,则直接取值做计算。若不存在算力值,且频点值不为unknown的情况,则取频点值做计算,若为unknown,则取0做兼容 - const consumption = (consumptionMap && consumptionMap.get(value[j].freq)) ? consumptionMap.get(value[j].freq) : (value[j].freq == 'unknown' ? 0 : value[j].freq); - if (!cpuArr.includes(value[j].cpu)) { - cpuArr.push(value[j].cpu); - // 创建cpu层级数据,以便后续生成树结构 - cpuMap.get(key)?.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, 0, value[j].cpu, '', 0, '', 0, 'cpu', -1, [])); - } - // 以下为频点数据按Loop周期切割数据如何取舍的判断条件,cutArr为周期切割依据,value为某一线程下的频点汇总数据 - // 如果频点数据开始时间大于某一周期起始时间,且结束时间小于等于下一同名方法开始时间的情况 - if (value[j].ts >= cutArr[i].ts && (value[j].ts + value[j].dur) <= cutArr[i + 1].ts) { - resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, (consumption * value[j].dur) / countMutiple, value[j].cpu, value[j].freq, value[j].dur, '', value[j].percent, 'freqdata', i, undefined)); - totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, (consumption * value[j].dur) / countMutiple, value[j].cpu, value[j].freq, value[j].dur, '', value[j].percent, 'freqdata', i, undefined)); - } - // 如果频点数据开始时间大于某一周期起始时间,且结束时间大于下一同名方法开始时间的情况 - if (value[j].ts >= cutArr[i].ts && (value[j].ts + value[j].dur) > cutArr[i + 1].ts) { - if (cutArr[i + 1].ts - value[j].ts > 0) { - resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, (consumption * (cutArr[i + 1].ts - value[j].ts)) / countMutiple, value[j].cpu, value[j].freq, cutArr[i + 1].ts - value[j].ts, '', value[j].percent * ((cutArr[i + 1].ts - value[j].ts) / value[j].dur), 'freqdata', i, undefined)); - totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, (consumption * (cutArr[i + 1].ts - value[j].ts)) / countMutiple, value[j].cpu, value[j].freq, cutArr[i + 1].ts - value[j].ts, '', value[j].percent * ((cutArr[i + 1].ts - value[j].ts) / value[j].dur), 'freqdata', i, undefined)); - break; - } - } - // 如果频点数据开始时间小于某一周期起始时间,且结束时间大于下一同名方法开始时间的情况 - if (value[j].ts < cutArr[i].ts && (value[j].ts + value[j].dur) > cutArr[i + 1].ts) { - resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, (consumption * (cutArr[i + 1].ts - cutArr[i].ts)) / countMutiple, value[j].cpu, value[j].freq, cutArr[i + 1].ts - cutArr[i].ts, '', value[j].percent * ((cutArr[i + 1].ts - cutArr[i].ts) / value[j].dur), 'freqdata', i, undefined)); - totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, (consumption * (cutArr[i + 1].ts - cutArr[i].ts)) / countMutiple, value[j].cpu, value[j].freq, cutArr[i + 1].ts - cutArr[i].ts, '', value[j].percent * ((cutArr[i + 1].ts - cutArr[i].ts) / value[j].dur), 'freqdata', i, undefined)); - } - // 如果频点数据开始时间小于某一周期起始时间,结束时间大于该方法开始时间。且频点数据结束时间小于下一同名方法开始时间 - if (value[j].ts < cutArr[i].ts && (value[j].ts + value[j].dur) > cutArr[i].ts && (value[j].ts + value[j].dur) < cutArr[i + 1].ts) { - resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, (consumption * (value[j].dur + value[j].ts - cutArr[i].ts)) / countMutiple, value[j].cpu, value[j].freq, value[j].dur + value[j].ts - cutArr[i].ts, '', value[j].percent * ((value[j].dur + value[j].ts - cutArr[i].ts) / value[j].dur), 'freqdata', i, undefined)); - totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, (consumption * (value[j].dur + value[j].ts - cutArr[i].ts)) / countMutiple, value[j].cpu, value[j].freq, value[j].dur + value[j].ts - cutArr[i].ts, '', value[j].percent * ((value[j].dur + value[j].ts - cutArr[i].ts) / value[j].dur), 'freqdata', i, undefined)); - } - } - // 合并相同周期内的数据 - this.mergeData(resList); - // 整理排序相同周期下的数据 - this.mergeCpuData(cpuMap.get(key)!, resList); - // 将cpu数据放置到对应周期层级下 - this.mergeCycleData(cycleMap.get(key)![i], cpuMap.get(key)); + } + /** + * 整合Loop切割方式中的频点数据与方法周期数据 + */ + mergeLoopData( + cutArr: Array<{ts: number, dur: number}>, + targetMap: Map>, + cycleMap: Map>, + totalList: Map> + ): void { + let timeDur: number = this.currentSelectionParam.recordStartNs; + targetMap.forEach((value, key) => { + cycleMap.set(key, new Array()); + totalList.set(key, new Array()); + for (let i = 0; i < cutArr.length - 1; i++) { + let cpuArr: Array = []; + let resList: Array = []; + let cpuMap: Map> = new Map(); + // 时间倍数值 + const countMutiple: number = 1000000; + cpuMap.set(key, new Array()); + // 创建周期层级数据 + cycleMap.get(key)?.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[0].thread, + ((cutArr[i].ts - timeDur) / 1000000).toFixed(3), key.split('_')[0], key.split('_')[1], 0, '', + '', 0, (cutArr[i].dur / 1000000).toFixed(3), 0, 'cycle', i + 1, [])); + for (let j = 0; j < value.length; j++) { + // 判断若用户导入json文件,则替换为对应cpu下的对应频点的算力值进行算力消耗计算 + // @ts-ignore + let consumptionMap: Map = + SpSegmentationChart.freqInfoMapData.size > 0 && SpSegmentationChart.freqInfoMapData.get(value[j].cpu); + // 若存在算力值,则直接取值做计算。若不存在算力值,且频点值不为unknown的情况,则取频点值做计算,若为unknown,则取0做兼容 + const consumption: number = consumptionMap && consumptionMap.get(value[j].freq) ? + consumptionMap.get(value[j].freq) : (value[j].freq === 'unknown' ? 0 : value[j].freq); + if (!cpuArr.includes(value[j].cpu)) { + cpuArr.push(value[j].cpu); + // 创建cpu层级数据,以便后续生成树结构 + cpuMap.get(key)?.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, + '', value[j].pid, value[j].tid, 0, value[j].cpu, '', 0, '', 0, 'cpu', -1, [])); + } + // 以下为频点数据按Loop周期切割数据如何取舍的判断条件,cutArr为周期切割依据,value为某一线程下的频点汇总数据 + // 如果频点数据开始时间大于某一周期起始时间,且结束时间小于等于下一同名方法开始时间的情况 + if (value[j].ts >= cutArr[i].ts && value[j].ts + value[j].dur <= cutArr[i + 1].ts) { + resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', + value[j].pid, value[j].tid, (consumption * value[j].dur) / countMutiple, value[j].cpu, + value[j].freq, value[j].dur, '', value[j].percent, 'freqdata', i, undefined)); + totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, + value[j].tid, (consumption * value[j].dur) / countMutiple, value[j].cpu, value[j].freq, + value[j].dur, '', value[j].percent, 'freqdata', i, undefined)); + } + // 如果频点数据开始时间大于某一周期起始时间,且结束时间大于下一同名方法开始时间的情况 + if (value[j].ts >= cutArr[i].ts && value[j].ts + value[j].dur > cutArr[i + 1].ts) { + if (cutArr[i + 1].ts - value[j].ts > 0) { + resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', + value[j].pid, value[j].tid, (consumption * (cutArr[i + 1].ts - value[j].ts)) / countMutiple, + value[j].cpu, value[j].freq, cutArr[i + 1].ts - value[j].ts, '', + value[j].percent * ((cutArr[i + 1].ts - value[j].ts) / value[j].dur), 'freqdata', i, undefined)); + totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, + (consumption * (cutArr[i + 1].ts - value[j].ts)) / countMutiple, value[j].cpu, value[j].freq, + cutArr[i + 1].ts - value[j].ts, '', value[j].percent * ((cutArr[i + 1].ts - value[j].ts) / value[j].dur), + 'freqdata', i, undefined)); + break; } - }); + } + // 如果频点数据开始时间小于某一周期起始时间,且结束时间大于下一同名方法开始时间的情况 + if (value[j].ts < cutArr[i].ts && value[j].ts + value[j].dur > cutArr[i + 1].ts) { + resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread,'', value[j].pid, + value[j].tid, (consumption * (cutArr[i + 1].ts - cutArr[i].ts)) / countMutiple, value[j].cpu, value[j].freq, + cutArr[i + 1].ts - cutArr[i].ts, '', value[j].percent * ((cutArr[i + 1].ts - cutArr[i].ts) / value[j].dur), + 'freqdata', i, undefined)); + totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, + (consumption * (cutArr[i + 1].ts - cutArr[i].ts)) / countMutiple, value[j].cpu, value[j].freq, + cutArr[i + 1].ts - cutArr[i].ts, '', value[j].percent * ((cutArr[i + 1].ts - cutArr[i].ts) / value[j].dur), + 'freqdata', i, undefined)); + } + // 如果频点数据开始时间小于某一周期起始时间,结束时间大于该方法开始时间。且频点数据结束时间小于下一同名方法开始时间 + if (value[j].ts < cutArr[i].ts && + value[j].ts + value[j].dur > cutArr[i].ts && value[j].ts + value[j].dur < cutArr[i + 1].ts) { + resList.push(new TabPaneFreqUsageConfig('cycle' + (i + 1) + '—' + value[j].thread, '', value[j].pid, value[j].tid, + (consumption * (value[j].dur + value[j].ts - cutArr[i].ts)) / countMutiple, value[j].cpu, value[j].freq, + value[j].dur + value[j].ts - cutArr[i].ts, '', value[j].percent * + ((value[j].dur + value[j].ts - cutArr[i].ts) / value[j].dur), 'freqdata', i, undefined)); + totalList.get(key)?.push(new TabPaneFreqUsageConfig(value[j].thread, '', value[j].pid, value[j].tid, + (consumption * (value[j].dur + value[j].ts - cutArr[i].ts)) / countMutiple, value[j].cpu, value[j].freq, + value[j].dur + value[j].ts - cutArr[i].ts, '', value[j].percent * ((value[j].dur + value[j].ts - cutArr[i].ts) / + value[j].dur), 'freqdata', i, undefined)); + } + } + // 合并相同周期内的数据 + this.mergeData(resList); + // 整理排序相同周期下的数据 + this.mergeCpuData(cpuMap.get(key)!, resList); + // 将cpu数据放置到对应周期层级下 + this.mergeCycleData(cycleMap.get(key)![i], cpuMap.get(key)!); + } + }); + } + + /** + * 切割后整合好的周期频点数据放置到对应的线程下 + */ + mergeThreadData( + threadArr: Array, + cycleMap: Map> + ): void { + for (let i = 0; i < threadArr.length; i++) { + let cycleMapData: Array | undefined = cycleMap.get( + threadArr[i].pid + '_' + threadArr[i].tid + ); + for (let j = 0; j < cycleMapData!.length; j++) { + threadArr[i].children?.push(cycleMapData![j]); + threadArr[i].count += cycleMapData![j].count; + threadArr[i].dur += cycleMapData![j].dur; + // @ts-ignore + threadArr[i].percent += cycleMapData![j].percent; + } } - /** - * 切割后整合好的周期频点数据放置到对应的线程下 - */ - mergeThreadData(threadArr: Array, cycleMap: Map>): void { - for (let i = 0; i < threadArr.length; i++) { - let cycleMapData = cycleMap.get(threadArr[i].pid + '_' + threadArr[i].tid); - for (let j = 0; j < cycleMapData!.length; j++) { - threadArr[i].children.push(cycleMapData![j]); - threadArr[i].count += cycleMapData![j].count; - threadArr[i].dur += cycleMapData![j].dur; - threadArr[i].percent += cycleMapData![j].percent; - } + } + /** + * 切割后整合好的线程级频点数据放置到对应的进程 + */ + mergePidData( + pidArr: Array, + threadArr: Array + ): void { + for (let i = 0; i < pidArr.length; i++) { + for (let j = 0; j < threadArr.length; j++) { + if (pidArr[i].pid === threadArr[j].pid) { + pidArr[i].children?.push(threadArr[j]); + pidArr[i].count += threadArr[j].count; + pidArr[i].dur += threadArr[j].dur; + // @ts-ignore + pidArr[i].percent += threadArr[j].percent; } + } } - /** - * 切割后整合好的线程级频点数据放置到对应的进程 - */ - mergePidData(pidArr: Array, threadArr: Array): void { - for (let i = 0; i < pidArr.length; i++) { - for (let j = 0; j < threadArr.length; j++) { - if (pidArr[i].pid === threadArr[j].pid) { - pidArr[i].children.push(threadArr[j]); - pidArr[i].count += threadArr[j].count; - pidArr[i].dur += threadArr[j].dur; - pidArr[i].percent += threadArr[j].percent; - } - } + } + /** + * 合并相同周期内运行所在cpu相同、频点相同的数据 + */ + mergeData(resList: Array): void { + // 合并相同周期内的数据 + for (let i = 0; i < resList.length; i++) { + for (let j = i + 1; j < resList.length; j++) { + if ( + resList[i].cpu === resList[j].cpu && + resList[i].freq === resList[j].freq && + resList[i].id === resList[j].id + ) { + resList[i].dur += resList[j].dur; + // @ts-ignore + resList[i].percent += resList[j].percent; + resList[i].count += resList[j].count; + resList.splice(j, 1); + j--; } + } } - /** - * 合并相同周期内运行所在cpu相同、频点相同的数据 - */ - mergeData(resList: Array): void { - // 合并相同周期内的数据 - for (let i = 0; i < resList.length; i++) { - for (let j = i + 1; j < resList.length; j++) { - if (resList[i].cpu === resList[j].cpu && resList[i].freq === resList[j].freq && resList[i].id === resList[j].id) { - resList[i].dur += resList[j].dur; - resList[i].percent += resList[j].percent; - resList[i].count += resList[j].count; - resList.splice(j, 1); - j--; - } - } + } + /** + * 将cpu层级数据放到对应的周期层级下 + */ + mergeCycleData( + obj: TabPaneFreqUsageConfig, + arr: Array + ): void { + for (let i = 0; i < arr!.length; i++) { + if (arr![i].count === 0 && arr![i].dur === 0) { + continue; + } + obj.children?.push(arr![i]); + obj.count += arr![i].count; + obj.dur += arr![i].dur; + // @ts-ignore + obj.percent += arr![i].percent; + } + } + /** + * 将切割好的不区分周期的数据作为total数据放到对应的线程层级下,周期数据前 + */ + mergeTotalData( + threadArr: Array, + totalData: Array + ): void { + for (let i = 0; i < threadArr.length; i++) { + for (let j = 0; j < totalData.length; j++) { + if ( + Number(threadArr[i].pid) === Number(totalData[j].pid) && + Number(threadArr[i].tid) === Number(totalData[j].tid) + ) { + totalData[j].thread = 'TotalData'; + // @ts-ignore + threadArr[i].children.unshift(totalData[j]); } + } } - /** - * 将cpu层级数据放到对应的周期层级下 - */ - mergeCycleData(obj: TabPaneFreqUsageConfig, arr: Array | undefined): void { - for (let i = 0; i < arr!.length; i++) { - if (arr![i].count === 0 && arr![i].dur === 0) { - continue; - } - obj.children?.push(arr![i]); - obj.count += arr![i].count; - obj.dur += arr![i].dur; - obj.percent += arr![i].percent; + } + /** + * 整理排序相同周期下的数据 + */ + mergeCpuData( + cpuArray: Array, + resList: Array + ): void { + // 以算力消耗降序排列 + resList.sort((a, b) => b.count - a.count); + // 以cpu升序排列 + cpuArray.sort((a: any, b: any) => a.cpu - b.cpu); + cpuArray.forEach((item: any) => { + for (let s = 0; s < resList.length; s++) { + if (item.cpu === resList[s].cpu) { + item.children.push(resList[s]); + item.count += resList[s].count; + item.dur += resList[s].dur; + item.percent += resList[s].percent; } + } + }); + } + /** + * 切割好的不区分周期的数据,以相同cpu相同频点的进行整合 + */ + merge( + totalList: Map> + ): Array { + let result: Array = new Array(); + totalList.forEach((value: any, key: any) => { + let countNum = result.push( + new TabPaneFreqUsageConfig('', '', key.split('_')[0], key.split('_')[1], + 0, '', '', 0, '', 0, 'cycle', 0, [] + ) + ); + let cpuArr: Array = []; + let flagArr: Array = []; + for (let i = 0; i < value.length; i++) { + if (!flagArr.includes(value[i].cpu)) { + flagArr.push(value[i].cpu); + let flag = cpuArr.push( + new TabPaneFreqUsageConfig(value[i].thread, '', value[i].pid, value[i].tid, + 0, value[i].cpu, '', 0, '', 0, 'cpu', -1, [] + ) + ); + result[countNum - 1].children?.push(cpuArr[flag - 1]); + } + for (let j = i + 1; j < value.length; j++) { + if (value[i].cpu === value[j].cpu && value[i].freq === value[j].freq) { + value[i].dur += value[j].dur; + value[i].percent += value[j].percent; + value[i].count += value[j].count; + value.splice(j, 1); + j--; + } + } + } + result[countNum - 1].children?.sort((a: any, b: any) => a.cpu - b.cpu); + for (let i = 0; i < cpuArr.length; i++) { + for (let j = 0; j < value.length; j++) { + if (cpuArr[i].cpu === value[j].cpu) { + cpuArr[i].children.push(value[j]); + cpuArr[i].dur += value[j].dur; + cpuArr[i].count += value[j].count; + cpuArr[i].percent += value[j].percent; + } + } + result[countNum - 1].dur += cpuArr[i].dur; + result[countNum - 1].count += cpuArr[i].count; + result[countNum - 1].percent += cpuArr[i].percent; + } + }); + return result; + } + /** + * 递归整理数据,取小数位数,转换单位 + */ + fixedDeal(arr: Array): void { + if (arr === undefined) { + return; } - /** - * 将切割好的不区分周期的数据作为total数据放到对应的线程层级下,周期数据前 - */ - mergeTotalData(threadArr: Array, totalData: Array): void { - for (let i = 0; i < threadArr.length; i++) { - for (let j = 0; j < totalData.length; j++) { - if (Number(threadArr[i].pid) === Number(totalData[j].pid) && Number(threadArr[i].tid) === Number(totalData[j].tid)) { - totalData[j].thread = 'TotalData'; - threadArr[i].children.unshift(totalData[j]); - } - } + for (let i = 0; i < arr.length; i++) { + // @ts-ignore + arr[i].percent = arr[i].percent.toFixed(2); + // @ts-ignore + arr[i].dur = (arr[i].dur / 1000000).toFixed(3); + if (arr[i].freq !== '') { + if (arr[i].freq === 'unknown') { + arr[i].freq = 'unknown'; + } else { + // @ts-ignore + arr[i].freq = arr[i].freq / 1000; } + } + if (!(SpSegmentationChart.freqInfoMapData.size > 0)) { + // @ts-ignore + arr[i].count = (arr[i].count / 1000).toFixed(3); + } else { + // @ts-ignore + arr[i].count = arr[i].count.toFixed(3); + } + // @ts-ignore + this.fixedDeal(arr[i].children); } - /** - * 整理排序相同周期下的数据 - */ - mergeCpuData(cpuArray: Array, resList: Array): void { - // 以算力消耗降序排列 - resList.sort((a, b) => b.count - a.count); - // 以cpu升序排列 - cpuArray.sort((a: any, b: any) => a.cpu - b.cpu); - cpuArray.forEach((item: any) => { - for (let s = 0; s < resList.length; s++) { - if (item.cpu === resList[s].cpu) { - item.children.push(resList[s]); - item.count += resList[s].count; - item.dur += resList[s].dur; - item.percent += resList[s].percent; - } - } - }); + } - } - /** - * 切割好的不区分周期的数据,以相同cpu相同频点的进行整合 - */ - merge(totalList: Map>): Array { - let result: Array = new Array(); - totalList.forEach((value: any, key: any) => { - let countNum = result.push(new TabPaneFreqUsageConfig('', '', key.split('_')[0], key.split('_')[1], 0, '', '', 0, '', 0, 'cycle', 0, [])); - let cpuArr: Array = []; - let flagArr: Array = []; - for (let i = 0; i < value.length; i++) { - if (!flagArr.includes(value[i].cpu)) { - flagArr.push(value[i].cpu); - let flag = cpuArr.push(new TabPaneFreqUsageConfig(value[i].thread, '', value[i].pid, value[i].tid, 0, value[i].cpu, '', 0, '', 0, 'cpu', -1, [])); - result[countNum - 1].children?.push(cpuArr[flag - 1]); - } - for (let j = i + 1; j < value.length; j++) { - if (value[i].cpu === value[j].cpu && value[i].freq === value[j].freq) { - value[i].dur += value[j].dur; - value[i].percent += value[j].percent; - value[i].count += value[j].count; - value.splice(j, 1); - j--; - } - } + /** + * 绑定表格点击事件 + */ + private threadClick(data: Array): void { + 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 (!this.threadStatesTblSource.length && !this.threadStatesTbl!.recycleDataSource.length) { + data = []; + } + if (label.includes('Process') && i === 0) { + this.threadStatesTbl!.setStatus(data, false); + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.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.threadStatesTbl!.setStatus(item.children, false); + } } - result[countNum - 1].children?.sort((a: any, b: any) => a.cpu - b.cpu); - for (let i = 0; i < cpuArr.length; i++) { - for (let j = 0; j < value.length; j++) { - if (cpuArr[i].cpu === value[j].cpu) { - cpuArr[i].children.push(value[j]); - cpuArr[i].dur += value[j].dur; - cpuArr[i].count += value[j].count; - cpuArr[i].percent += value[j].percent; - } + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement( data, RedrawTreeForm.Retract); + } else if (label.includes('Cycle') && i === 2) { + for (let item of data) { + item.status = true; + for (let value of item.children ? item.children : []) { + value.status = true; + if (value.children !== undefined && value.children.length > 0) { + this.threadStatesTbl!.setStatus(value.children, false); } - result[countNum - 1].dur += cpuArr[i].dur; - result[countNum - 1].count += cpuArr[i].count; - result[countNum - 1].percent += cpuArr[i].percent; + } } + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('CPU') && i === 3) { + this.threadStatesTbl!.setStatus(data, true); + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); + } }); - return result; + } } - /** - * 递归整理数据,取小数位数,转换单位 - */ - fixedDeal(arr: Array): void { - if (arr === undefined) { - return; + } + /** + * 散点图渲染数据整理 + */ + render(res: Array, str: string, queryCycleScatter: Array): void { + let maxFreq: HTMLInputElement = this.scatterInput!.querySelector('#maxFreq')!; + let maxHz: HTMLInputElement = this.scatterInput!.querySelector('#maxHz')!; + if (maxFreq.value && maxHz.value) { + if (/^[0-9]*$/.test(maxFreq.value) && /^[0-9]*$/.test(maxHz.value)) { + this.organizeData(res, str, queryCycleScatter, maxFreq.value, maxHz.value); + } else { + if (!/^[0-9]*$/.test(maxFreq.value)) { + maxFreq.style.border = '2px solid rgb(255,0,0)'; } - for (let i = 0; i < arr.length; i++) { - arr[i].percent = arr[i].percent > 100 ? 100 : arr[i].percent; - arr[i].percent = arr[i].percent.toFixed(2); - arr[i].dur = (arr[i].dur / 1000000).toFixed(3); - if (arr[i].freq !== '') { - if (arr[i].freq === 'unknown') { - arr[i].freq = 'unknown'; - } else { - arr[i].freq = arr[i].freq / 1000; - } - } - if(!(SpSegmentationChart.freqInfoMapData.size > 0)) { - arr[i].count = (arr[i].count / 1000).toFixed(3); - }else{ - arr[i].count = (arr[i].count).toFixed(3); - } - this.fixedDeal(arr[i].children); + if (!/^[0-9]*$/.test(maxHz.value)) { + maxHz.style.border = '2px solid rgb(255,0,0)'; } + } + } else { + if (maxFreq.value === '') { + maxFreq.style.border = '2px solid rgb(255,0,0)'; + } + if (maxHz.value === '') { + maxHz.style.border = '2px solid rgb(255,0,0)'; + } + SpSegmentationChart.setChartData('CPU-FREQ', []); } - - /** - * 绑定表格点击事件 - */ - private threadClick(data: Array): void { - 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 (!this.threadStatesTblSource.length && !this.threadStatesTbl!.recycleDataSource.length) { - data = []; - } - if (label.includes('Process') && i === 0) { - this.threadStatesTbl!.setStatus(data, false); - this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.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.threadStatesTbl!.setStatus(item.children, false); - } - } - this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); - } else if (label.includes('Cycle') && i === 2) { - for (let item of data) { - item.status = true; - for (let value of item.children ? item.children : []) { - value.status = true; - if (value.children != undefined && value.children.length > 0) { - this.threadStatesTbl!.setStatus(value.children, false); - } - } - } - this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); - } else if (label.includes('CPU') && i === 3) { - this.threadStatesTbl!.setStatus(data, true); - this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); - } - }); - } - } + } + /** + * 数据整理 + */ + organizeData( + res: Array, + str: string, + queryCycleScatter: Array, + maxFreqValue: string, + maxHzValue: string + ): void { + // @ts-ignore + this.shadowRoot?.querySelector('#cycleQuery')!.style.display = 'block'; + // @ts-ignore + let freq: Map = SpSegmentationChart.freqInfoMapData.size > 0 && + SpSegmentationChart.freqInfoMapData.get(SpSegmentationChart.freqInfoMapData.size - 1); + // @ts-ignore + let yAxis: number = freq && freq.get(Number(maxFreqValue) * 1000) + ? freq.get(Number(maxFreqValue) * 1000) : Number(maxFreqValue); + let xAxis: number = (yAxis * 1000) / Number(maxHzValue); + // 需要做筛选时,会利用下面的cycleA、cycleB数组 + let scatterArr: Array> = []; + let traceRowdata: Array<{ + dur: number; + startNS: number; + value: number; + cycle: number; + }> = []; + let cycleA: Array> = []; + let cycleB: Array> = []; + let cycleAStart: number = queryCycleScatter[0] || 0; + let cycleAEnd: number = queryCycleScatter[1] || 0; + let cycleBStart: number = queryCycleScatter[2] || 0; + let cycleBEnd: number = queryCycleScatter[3] || 0; + for (let i = 1; i < res.length; i++) { + const count: number = Number(res[i].count); + const dur: number = Number(res[i].cdur); + const rdur: number = Number(res[i].dur); //MHz·ms ms ms + scatterArr.push([count, count / dur, i, dur, rdur]); + traceRowdata.push({ + dur: dur * 1000000, + value: count, + startNS: Number(res[i].ts) * 1000000, + cycle: i - 1, + }); + if (dur >= cycleAStart && dur < cycleAEnd) { + cycleA.push([count, count / dur, i, dur, rdur]); + } + if (dur >= cycleBStart && dur < cycleBEnd) { + cycleB.push([count, count / dur, i, dur, rdur]); + } } - /** - * 散点图渲染数据整理 - */ - render(res: Array, str: string, queryCycleScatter: Array): void { - let maxFreq: HTMLInputElement = this.scatterInput!.querySelector('#maxFreq')!; - let maxHz: HTMLInputElement = this.scatterInput!.querySelector('#maxHz')!; - maxFreq.style.border = '1px solid rgb(151,151,151)'; - maxHz.style.border = '1px solid rgb(151,151,151)'; - if (maxFreq.value && maxHz.value) { - if (/^[0-9]*$/.test(maxFreq.value) && /^[0-9]*$/.test(maxHz.value)) { - // @ts-ignore - this.shadowRoot?.querySelector('#cycleQuery')!.style.display = 'block'; - let freq: Map | undefined; - if (SpSegmentationChart.freqInfoMapData.size > 0){ - freq = SpSegmentationChart.freqInfoMapData.get(SpSegmentationChart.freqInfoMapData.size - 1) - } - // @ts-ignore - let yAxis: number = (freq && freq.get(Number(maxFreq.value) * 1000)) ? freq.get(Number(maxFreq.value) * 1000) : Number(maxFreq.value); - let xAxis: number = yAxis * 1000 / Number(maxHz.value);//MHz·s - // 需要做筛选时,会利用下面的cycleA、cycleB数组 - let scatterArr: Array> = [], traceRowdata: Array = [], cycleA: Array> = [], cycleB: Array> = []; - let cycleAStart: number = queryCycleScatter[0] || 0, cycleAEnd: number = queryCycleScatter[1] || 0, cycleBStart: number = queryCycleScatter[2] || 0, cycleBEnd: number = queryCycleScatter[3] || 0; - for (let i = 1; i < res.length; i++) { - const count: number = Number(res[i].count), dur: number = Number(res[i].cdur), r_dur: number = Number(res[i].dur);//MHz·ms ms ms - scatterArr.push([count, count / dur, i, dur, r_dur]); - traceRowdata.push( - { - 'dur': dur * 1000000, - 'value': count, - 'freq': Math.round(count / dur) * 1000, - 'startNS': Number(res[i].ts) * 1000000, - 'cycle': i - 1 - } - ); - if (dur >= cycleAStart && dur < cycleAEnd) { - cycleA.push([count, count / dur, i, dur, r_dur]); - } - if (dur >= cycleBStart && dur < cycleBEnd) { - cycleB.push([count, count / dur, i, dur, r_dur]); - } - } - this.statisticsScatter!.config = { - // 纵轴坐标值 - yAxisLabel: [Math.round(yAxis / 5), Math.round(yAxis * 2 / 5), Math.round(yAxis * 3 / 5), Math.round(yAxis * 4 / 5), Math.round(yAxis)], - // 横轴坐标值 - xAxisLabel: [Math.round(xAxis / 5), Math.round(xAxis * 2 / 5), Math.round(xAxis * 3 / 5), Math.round(xAxis * 4 / 5), Math.round(xAxis), Math.round(xAxis * 6 / 5)], - // 横轴字段、纵轴字段 - AxisLabel: ['负载', '算力供给'], - // 是否加载最大负载线及均衡线 - drawload: true, - // 最大负载线及均衡线值 - load: [xAxis, Number(maxHz.value)], - // 绘制点数据信息存储数组 - paintingData: [], - // 当前移入点坐标信息 - hoverData: {}, - // 颜色池 - colorPool: () => ['#2f72f8', '#ffab67', '#a285d2'], - // 移入数据点时是否触发函数 - //@ts-ignore - hoverEvent: SpSegmentationChart.tabHover, - // 渐变色背景信息 - globalGradient: undefined, - // 渲染数据点 - data: [scatterArr, cycleA, cycleB], - // 散点图title - title: str, - colorPoolText: () => ['Total', 'CycleA', 'CycleB'], - tip: (data: any) => { - return ` -
- Cycle: ${data.c[2]};
- Comsumption: ${data.c[0]};
- Cycle_dur: ${data.c[3]} ms;
- Running_dur: ${data.c[4]} ms;
-
- ` - } - }; - SpSegmentationChart.setChartData('CPU-FREQ', traceRowdata); - } else { - if (!/^[0-9]*$/.test(maxFreq.value)) { - maxFreq.style.border = '2px solid rgb(255,0,0)'; - } - if (!/^[0-9]*$/.test(maxHz.value)) { - maxHz.style.border = '2px solid rgb(255,0,0)'; - } - } - } else { - if (maxFreq.value === '') { - maxFreq.style.border = '2px solid rgb(255,0,0)'; - maxFreq.setAttribute('placeholder', 'Please input maxFreq'); - } - if (maxHz.value === '') { - maxHz.style.border = '2px solid rgb(255,0,0)'; - maxHz.setAttribute('placeholder', 'Please input Fps'); - } - SpSegmentationChart.setChartData('CPU-FREQ', []); + this.setConfig(Number(maxHzValue), str, scatterArr, yAxis, xAxis, cycleA, cycleB); + SpSegmentationChart.setChartData('CPU-FREQ', traceRowdata); + } - } - } + /** + * 配置散点图 + */ + setConfig( + maxHz: number, + str: string, + scatterArr: Array>, + yAxis: number, + xAxis: number, + cycleA: Array>, + cycleB: Array> + ): void { + this.statisticsScatter!.config = { + // 纵轴坐标值 + yAxisLabel: [ + Math.round(yAxis / 5), + Math.round((yAxis * 2) / 5), + Math.round((yAxis * 3) / 5), + Math.round((yAxis * 4) / 5), + Math.round(yAxis), + ], + // 横轴坐标值 + xAxisLabel: [ + Math.round(xAxis / 5), + Math.round((xAxis * 2) / 5), + Math.round((xAxis * 3) / 5), + Math.round((xAxis * 4) / 5), + Math.round(xAxis), + Math.round((xAxis * 6) / 5), + ], + // 横轴字段、纵轴字段 + AxisLabel: ['负载', '算力供给'], + // 是否加载最大负载线及均衡线 + drawload: true, + // 最大负载线及均衡线值 + load: [xAxis, maxHz], + // 绘制点数据信息存储数组 + paintingData: [], + // 当前移入点坐标信息 + hoverData: {}, + // 颜色池 + colorPool: () => ['#2f72f8', '#ffab67', '#a285d2'], + // 移入数据点时是否触发函数 + //@ts-ignore + hoverEvent: SpSegmentationChart.tabHover, + // 渐变色背景信息 + globalGradient: undefined, + // 渲染数据点 + data: [scatterArr, cycleA, cycleB], + // 散点图title + title: str, + colorPoolText: (): Array => ['Total', 'CycleA', 'CycleB'], + tip: (data: any): string => { + return ` +
+ Cycle: ${data.c[2]};
+ Comsumption: ${data.c[0]};
+ Cycle_dur: ${data.c[3]} ms;
+ Running_dur: ${data.c[4]} ms;
+
+ `; + }, + }; + } - initElements(): void { - this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-running-datacut'); - // 绑定single、loop按钮点击事件 - this.threadStatesDIV = this.shadowRoot?.querySelector('#dataCut'); - this.threadStatesDIV?.children[2].children[0].addEventListener('click', (e) => { - this.threadStatesTbl!.loading = true; - // @ts-ignore - this.dataSingleCut(this.threadStatesDIV?.children[0]!, this.threadStatesDIV?.children[1]!, this.initData); - }) - this.threadStatesDIV?.children[2].children[1].addEventListener('click', (e) => { - this.threadStatesTbl!.loading = true; - // @ts-ignore - this.dataLoopCut(this.threadStatesDIV?.children[0]!, this.threadStatesDIV?.children[1]!, this.initData); - }) - this.statisticsScatter = this.shadowRoot?.querySelector('#chart-scatter'); - // 增加表格thread层级点击更新散点图事件、周期层级点击高亮泳道图对应段事件 - let scatterData: Array = new Array(); - let str: string = ''; - this.threadStatesTbl!.addEventListener('row-click', (evt): void => { - // @ts-ignore - if (evt.detail.flag === 'thread') { - // @ts-ignore - scatterData = evt.detail.children; - // @ts-ignore - str = evt.detail.thread; - this.render(scatterData, str, []); - } - // @ts-ignore - if (evt.detail.flag === 'cycle') { - // @ts-ignore - SpSegmentationChart.tabHover('CPU-FREQ', true, evt.detail.id - 1); + initElements(): void { + this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-running-datacut'); + // 绑定事件 + this.addListener(); + this.statisticsScatter = this.shadowRoot?.querySelector('#chart-scatter'); + // 增加表格thread层级点击更新散点图事件、周期层级点击高亮泳道图对应段事件 + let scatterData: Array = new Array(); + let str: string = ''; + this.threadStatesTbl!.addEventListener('row-click', (evt): void => { + // @ts-ignore + if (evt.detail.flag === 'thread') { + // @ts-ignore + scatterData = evt.detail.children; + // @ts-ignore + str = evt.detail.thread; + this.render(scatterData, str, []); + } + // @ts-ignore + if (evt.detail.flag === 'cycle' && evt.detail.pid === scatterData[evt.detail.id - 1].pid + // @ts-ignore + && evt.detail.tid === scatterData[evt.detail.id - 1].tid && evt.detail.id > 0) { + // @ts-ignore + SpSegmentationChart.tabHover('CPU-FREQ', true, evt.detail.id - 1); + } + }); + this.scatterInput = this.shadowRoot?.querySelector('.chart-box'); + this.shadowRoot?.querySelector('#query-btn')!.addEventListener('click', (e) => { + // @ts-ignore + let cycleAStartValue = this.shadowRoot?.querySelector('#cycle-a-start-range')!.value; + // @ts-ignore + let cycleAEndValue = this.shadowRoot?.querySelector('#cycle-a-end-range')!.value; + // @ts-ignore + let cycleBStartValue = this.shadowRoot?.querySelector('#cycle-b-start-range')!.value; + // @ts-ignore + let cycleBEndValue = this.shadowRoot?.querySelector('#cycle-b-end-range')!.value; + let queryCycleScatter = [Number(cycleAStartValue), Number(cycleAEndValue), Number(cycleBStartValue), Number(cycleBEndValue)]; + this.render(scatterData, str, queryCycleScatter); + }); + } + /** + * 配置监听事件 + */ + addListener(): void { + // 绑定single、loop按钮点击事件 + this.threadStatesDIV = this.shadowRoot?.querySelector('#dataCut'); + this.threadStatesDIV?.children[2].children[0].addEventListener('click', (e) => { + this.threadStatesTbl!.loading = true; + // @ts-ignore + this.dataSingleCut(this.threadStatesDIV?.children[0]!, this.threadStatesDIV?.children[1]!, this.initData); + } + ); + this.threadStatesDIV?.children[2].children[1].addEventListener('click', (e) => { + this.threadStatesTbl!.loading = true; + // @ts-ignore + this.dataLoopCut(this.threadStatesDIV?.children[0]!, this.threadStatesDIV?.children[1]!, this.initData); + } + ); + this.threadStatesDIV?.children[0].addEventListener('focus', (e) => { + // @ts-ignore + this.threadStatesDIV?.children[0]!.style.border = '1px solid rgb(151,151,151)'; + } + ); + this.threadStatesDIV?.children[1].addEventListener('focus', (e) => { + // @ts-ignore + this.threadStatesDIV?.children[1]!.style.border = '1px solid rgb(151,151,151)'; + } + ); + this.shadowRoot?.querySelector('#maxFreq')?.addEventListener('focus', (e) => { + // @ts-ignore + this.shadowRoot?.querySelector('#maxFreq')!.style.border = '1px solid rgb(151,151,151)'; + }); + this.shadowRoot?.querySelector('#maxHz')?.addEventListener('focus', (e) => { + // @ts-ignore + this.shadowRoot?.querySelector('#maxHz')!.style.border = '1px solid rgb(151,151,151)'; + }); + } - } - }); - this.scatterInput = this.shadowRoot?.querySelector('.chart-box'); - this.shadowRoot?.querySelector('#query-btn')!.addEventListener('click', (e) => { - // @ts-ignore - let cycleAStartValue = this.shadowRoot?.querySelector('#cycle-a-start-range')!.value; - // @ts-ignore - let cycleAEndValue = this.shadowRoot?.querySelector('#cycle-a-end-range')!.value; - // @ts-ignore - let cycleBStartValue = this.shadowRoot?.querySelector('#cycle-b-start-range')!.value; - // @ts-ignore - let cycleBEndValue = this.shadowRoot?.querySelector('#cycle-b-end-range')!.value; - let queryCycleScatter = [Number(cycleAStartValue), Number(cycleAEndValue), Number(cycleBStartValue), Number(cycleBEndValue)]; - this.render(scatterData, str, queryCycleScatter); - }) - } + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.threadStatesTbl!); + } - connectedCallback(): void { - super.connectedCallback(); - resizeObserver(this.parentElement!, this.threadStatesTbl!); + initHtml(): string { + return ` + -
- - -
- - -
+ #dataCut{ + display: flex; + justify-content: space-between; + width:100%; + height:20px; + margin-bottom:2px; + align-items:center; + } + button{ + width:40%; + height:100%; + border: solid 1px #666666; + background-color: rgba(0,0,0,0); + border-radius:10px; + } + button:hover{ + background-color:#666666; + color:white; + } + .d-box{ + display: flex; + margin-left: 0; + height: 100%; + margin-top: 5px; + } + .chart-box{ + width: 35%; + min-width: 486px; + overflow: auto; + } + #chart-scatter{ + height: 100%; + max-height: 390px; + } + #query-btn{ + width:90px; + } + +
+ + +
+ + +
+
+ + +
+ + + + + + + + + + + + + + + + + +
- - -
- - - - - - - - - - - - - - - - - - + +
+
+ maxFreq: + + Fps: +
- -
-
- maxFreq: - - Fps: - -
-
-
- -