diff --git a/component/DevkitDistribute/devkit_distribute/config/perf_report.html b/component/DevkitDistribute/devkit_distribute/config/perf_report.html index e96f6034dc2ac830c93162f0def885876c434fc3..978119a1680fd9d10a8e4f0f4bfb05d2b65c492f 100644 --- a/component/DevkitDistribute/devkit_distribute/config/perf_report.html +++ b/component/DevkitDistribute/devkit_distribute/config/perf_report.html @@ -48,6 +48,9 @@ fill-opacity: 1 !important; stroke-opacity: 1 !important; } + .middle-header-row { + text-align: center !important; + } @@ -94,27 +97,35 @@

Summary

- - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + +

Charts

-
+

Response Time

- TopN Jump + Total Top 10
-
-
-
-

FlameGraph

- -
- Data Set - - - -
-
- -
-
+

Failed Response Time

- TopN Jump + Total Top 10
-
-
-

tps/qps

+
+

TPS/QPS

- TopN Jump + Total Top 10
-
-
-

Memory Usage

-
- Node Select - - - +
+
+

Memory Usage [{{key}}]

+
+ Node Select + + + +
+
+
+
-
-
-
-
-
-

CPU% Usage

-
- Node Select - - - +
+
+

CPU Usage [{{key}}]

+
+ Node Select + + + +
+
+
+
-
-
-
+
+ +
+
+

FlameGraph

+ +
+ Data Set + + + +
+
+ +
@@ -311,19 +324,38 @@ scales = group.ts.length; } - const memoryIps = Object.keys(pipelineData.perf.memory); - bars.memory.ts = pipelineData.perf.memory[memoryIps[0]][Object.keys(pipelineData.perf.memory[memoryIps[0]])[0]].startTime; - bars.memory.series = Object.keys(pipelineData.perf.memory[memoryIps[0]]).map(key => ({[key]:Object.keys(pipelineData.perf.memory[memoryIps[0]][key]).filter(innerKey => innerKey !== 'startTime').map(innerKey =>({[innerKey]: pipelineData.perf.memory[memoryIps[0]][key][innerKey]}))})); - const cpuIps = Object.keys(pipelineData.perf.cpu); - bars.cpu.ts = pipelineData.perf.cpu[cpuIps[0]][Object.keys(pipelineData.perf.cpu[cpuIps[0]])[0]].startTime; - bars.cpu.series = Object.keys(pipelineData.perf.cpu[cpuIps[0]]).map(key => ({[key]:Object.keys(pipelineData.perf.cpu[cpuIps[0]][key]).filter(innerKey => innerKey !== 'startTime').map(innerKey =>({[innerKey]: pipelineData.perf.cpu[cpuIps[0]][key][innerKey]}))})); + + const memoryD = pipelineData.perf.memory; + const cpuD = pipelineData.perf.cpu; + const memoryDatas = {}; + const memoryNodes = {}; + const cpuDatas = {}; + const cpuNodes = {}; + Array.from(Object.keys(memoryD)).forEach(node => Array.from(Object.keys(memoryD[node])).forEach(app => { + if (memoryDatas?.[app]?.length) { + memoryDatas[app].push(memoryD[node][app]); + memoryNodes[app].push(node); + } else { + memoryDatas[app] = [memoryD[node][app]]; + memoryNodes[app] = [node]; + } + })); + Array.from(Object.keys(cpuD)).forEach(node => Array.from(Object.keys(cpuD[node])).forEach(app => { + if (cpuDatas?.[app]?.length) { + cpuDatas[app].push(cpuD[node][app]); + cpuNodes[app].push(node); + } else { + cpuDatas[app] = [cpuD[node][app]]; + cpuNodes[app] = [node]; + } + })); const getTopN = (data, topN) => { const idxArr = [...Array(data.length).keys()] return idxArr.sort((a, b) => data[b] - data[a]).slice(0, topN); } - const topN = 50; + const topN = 10; const topNs = { rt: getTopN(group.rt.Total, topN), frt: getTopN(group.frt.Total, topN), @@ -333,8 +365,8 @@ const timeFormatter = (timestamp, ignoreDate = true) => { const date = new Date(timestamp); const localeTime = ignoreDate ? date.toLocaleTimeString() : date.toLocaleString().substring(5).replace('/', '-'); - const ms = date.getMilliseconds(); - return `${localeTime}.${ms}`; + // const ms = date.getMilliseconds(); + return localeTime; } const colorRank = (start, end, ranks, idx) => { @@ -489,7 +521,7 @@ class FlameData { flamed: pipelineData.perf.flame['-1'], ffgSearch: '', fd: null, - isUnfold: false, + isUnfold: true, selectVal: 'all', selectOptions: Object.keys(pipelineData.perf.flame).map(key => { if (key === '-1') { @@ -504,12 +536,14 @@ class FlameData { myCt1: null, myCt2: null, myCt3: null, - myCt4: null, - myCt5: null, - memoryIps, - cpuIps, - memoryNode: memoryIps[0], - cpuNode: cpuIps[0] + myCt4: [], + myCt5: [], + memoryNode: Array.from(Object.keys(memoryNodes)).map(key => memoryNodes[key][0]), + cpuNode: Array.from(Object.keys(cpuNodes)).map(key => cpuNodes[key][0]), + memoryDatas, + memoryNodes, + cpuDatas, + cpuNodes }; }, mounted() { @@ -598,20 +632,30 @@ class FlameData { } echarts.connect(Object.values(order)); - this.myCt4 = Vue.markRaw(echarts.init(document.getElementById('ct4'))); - this.myCt5 = Vue.markRaw(echarts.init(document.getElementById('ct5'))); - const orderInd = {'memory': this.myCt4, 'cpu': this.myCt5}; - for (const [category, chartObj] of Object.entries(orderInd)) { + Array.from(Object.keys(memoryDatas)).forEach((app, index) => { + this.myCt4.push(Vue.markRaw(echarts.init(document.getElementById(`ct4${index}`)))); + const data = memoryDatas[app][0]; + const ts = data.startTime; + const seriesKey = []; + const seriesData = []; + Array.from(Object.keys(data)).forEach(title => { + if (title === 'startTime') { + return; + } else { + seriesKey.push(title); + seriesData.push(data[title]); + } + }); const option = { tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, - valueFormatter: (value) => category === 'cpu' ? value + '%' : value + ' Mb', + valueFormatter: (value) => value + ' MB', }, legend: {}, - dataZoom: [{type: 'slider', start: 0, end: 50 / bars[category].ts.length * 100, moveHandleStyle: {color: 'black'}},{type: 'inside', start: 0, end: 50 / bars[category].ts.length * 100}], + dataZoom: [{type: 'slider', start: 0, end: 50 / ts.length * 100, moveHandleStyle: {color: 'black'}},{type: 'inside', start: 0, end: 50 / ts.length * 100}], grid: { left: '3%', right: '4%', @@ -619,7 +663,7 @@ class FlameData { containLabel: true }, xAxis: { - data: bars[category].ts.map(item => timeFormatter(item)), + data: ts.map(item => timeFormatter(item)), axisTick: { show: false }, @@ -633,7 +677,7 @@ class FlameData { { type: 'value', axisLabel: { - formatter: category==='cpu' ? '{value}%' : '{value} Mb' + formatter: '{value} MB' }, splitLine: { lineStyle: { @@ -643,9 +687,9 @@ class FlameData { splitNumber: 2 } ], - series: bars[category].series.map(keyObj => keyObj[Object.keys(keyObj)[0]].map(innerObj => ({ - data: innerObj[Object.keys(innerObj)[0]].map(val => category === 'memory' ? (val/1024/1024).toFixed(2) : (val*100).toFixed(2)), - name: `(${Object.keys(keyObj)[0]})${Object.keys(innerObj)[0]}`, + series: seriesKey.map((key, innerIdx) => ({ + data: seriesData[innerIdx].map((val => (val/1024/1024).toFixed(2))), + name: key, type: 'line', emphasis: { focus: 'series', @@ -656,10 +700,82 @@ class FlameData { connectNulls: true, symbol: 'emptyCircle', symbolSize: 8 - }))).flat(), - }; - chartObj.setOption(option); - } + })), + } + this.myCt4[index].setOption(option); + }); + Array.from(Object.keys(cpuDatas)).forEach((app, index) => { + this.myCt5.push(Vue.markRaw(echarts.init(document.getElementById(`ct5${index}`)))); + const data = cpuDatas[app][0]; + const ts = data.startTime; + const seriesKey = []; + const seriesData = []; + Array.from(Object.keys(data)).forEach(title => { + if (title === 'startTime') { + return; + } else { + seriesKey.push(title); + seriesData.push(data[title]); + } + }); + const option = { + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + }, + valueFormatter: (value) => value + '%', + }, + legend: {}, + dataZoom: [{type: 'slider', start: 0, end: 50 / ts.length * 100, moveHandleStyle: {color: 'black'}},{type: 'inside', start: 0, end: 50 / ts.length * 100}], + grid: { + left: '3%', + right: '4%', + bottom: 50, + containLabel: true + }, + xAxis: { + data: ts.map(item => timeFormatter(item)), + axisTick: { + show: false + }, + axisLine: { + lineStyle: { + opacity: 0.1 + } + } + }, + yAxis: [ + { + type: 'value', + axisLabel: { + formatter: '{value}%' + }, + splitLine: { + lineStyle: { + type: [1, 4] + } + }, + splitNumber: 2 + } + ], + series: seriesKey.map((key, innerIdx) => ({ + data: seriesData[innerIdx].map((val => (val*100).toFixed(2))), + name: key, + type: 'line', + emphasis: { + focus: 'series', + scale: true + }, + showSymbol: false, + smooth: 0.05, + connectNulls: true, + symbol: 'emptyCircle', + symbolSize: 8 + })), + } + this.myCt5[index].setOption(option); + }); }, setAndBindFG(id, fd, sid) { let fid = 1; @@ -694,31 +810,41 @@ class FlameData { rtJump() { this.myCt1.dispatchAction({ type: 'dataZoom', - startValue: this.rtTop - 10 >= 0 ? this.rtTop-10 : 0, - endValue: this.rtTop + 10 <= this.group.ts.length ? this.rtTop + 10 : this.group.ts.length + startValue: this.rtTop - 1 >= 0 ? this.rtTop-1 : 0, + endValue: this.rtTop + 1 <= this.group.ts.length ? this.rtTop + 1 : this.group.ts.length }); }, frtJump() { this.myCt2.dispatchAction({ type: 'dataZoom', - startValue: this.frtTop - 10 >= 0 ? this.frtTop-10 : 0, - endValue: this.frtTop + 10 <= this.group.ts.length ? this.frtTop + 10 : this.group.ts.length + startValue: this.frtTop - 1 >= 0 ? this.frtTop-1 : 0, + endValue: this.frtTop + 1 <= this.group.ts.length ? this.frtTop + 1 : this.group.ts.length }); }, tpsJump() { this.myCt3.dispatchAction({ type: 'dataZoom', - startValue: this.tpsTop - 10 >= 0 ? this.tpsTop-10 : 0, - endValue: this.tpsTop + 10 <= this.group.ts.length ? this.tpsTop + 10 : this.group.ts.length + startValue: this.tpsTop - 1 >= 0 ? this.tpsTop-1 : 0, + endValue: this.tpsTop + 1 <= this.group.ts.length ? this.tpsTop + 1 : this.group.ts.length }); }, - memoryChange() { - const timestamps = pipelineData.perf.memory[this.memoryNode][Object.keys(pipelineData.perf.memory[this.memoryNode])[0]].startTime; - const seriesData = Object.keys(pipelineData.perf.memory[this.memoryNode]).map(key => ({[key]:Object.keys(pipelineData.perf.memory[this.memoryNode][key]).filter(innerKey => innerKey !== 'startTime').map(innerKey =>({[innerKey]: pipelineData.perf.memory[this.memoryNode][key][innerKey]}))})); - Vue.markRaw(this.myCt4.setOption({ - series: seriesData.map(keyObj => keyObj[Object.keys(keyObj)[0]].map(innerObj => ({ - data: innerObj[Object.keys(innerObj)[0]].map(val => (val/1024/1024).toFixed(2)), - name: `(${Object.keys(keyObj)[0]})${Object.keys(innerObj)[0]}`, + memoryChange(key, index) { + const data = memoryDatas[key][index]; + const ts = data.startTime; + const seriesKey = []; + const seriesData = []; + Array.from(Object.keys(data)).forEach(title => { + if (title === 'startTime') { + return; + } else { + seriesKey.push(title); + seriesData.push(data[title]); + } + }); + Vue.markRaw(this.myCt4[index].setOption({ + series: seriesKey.map((key, innerIdx) => ({ + data: seriesData[innerIdx].map((val => (val/1024/1024).toFixed(2))), + name: key, type: 'line', emphasis: { focus: 'series', @@ -729,9 +855,9 @@ class FlameData { connectNulls: true, symbol: 'emptyCircle', symbolSize: 8 - }))).flat(), + })), xAxis: { - data: timestamps.map(item => timeFormatter(item)), + data: ts.map(item => timeFormatter(item)), axisTick: { show: false }, @@ -740,17 +866,26 @@ class FlameData { opacity: 0.1 } } - }, - legend: {} + } })); }, - cpuChange() { - const timestamps = pipelineData.perf.cpu[this.cpuNode][Object.keys(pipelineData.perf.cpu[this.cpuNode])[0]].startTime; - const seriesData = Object.keys(pipelineData.perf.cpu[this.cpuNode]).map(key => ({[key]:Object.keys(pipelineData.perf.cpu[this.cpuNode][key]).filter(innerKey => innerKey !== 'startTime').map(innerKey =>({[innerKey]: pipelineData.perf.cpu[this.cpuNode][key][innerKey]}))})); - Vue.markRaw(this.myCt5.setOption({ - series: seriesData.map(keyObj => keyObj[Object.keys(keyObj)[0]].map(innerObj => ({ - data: innerObj[Object.keys(innerObj)[0]].map(val => (val*100).toFixed(2)), - name: `(${Object.keys(keyObj)[0]})${Object.keys(innerObj)[0]}`, + cpuChange(key, index) { + const data = cpuDatas[key][index]; + const ts = data.startTime; + const seriesKey = []; + const seriesData = []; + Array.from(Object.keys(data)).forEach(title => { + if (title === 'startTime') { + return; + } else { + seriesKey.push(title); + seriesData.push(data[title]); + } + }); + Vue.markRaw(this.myCt5[index].setOption({ + series: seriesKey.map((key, innerIdx) => ({ + data: seriesData[innerIdx].map((val => (val*100).toFixed(2))), + name: key, type: 'line', emphasis: { focus: 'series', @@ -761,9 +896,9 @@ class FlameData { connectNulls: true, symbol: 'emptyCircle', symbolSize: 8 - }))).flat(), + })), xAxis: { - data: timestamps.map(item => timeFormatter(item)), + data: ts.map(item => timeFormatter(item)), axisTick: { show: false }, @@ -772,8 +907,7 @@ class FlameData { opacity: 0.1 } } - }, - legend: {} + } })); } }