-
Node Select
-
-
-
+
+
+
CPU Usage [{{key}}]
+
+ Node Select
+ cpuChange(key, index)">
+
+
+
+
+
-
-
-
+
+
+
+
+
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: {}
+ }
}));
}
}