diff --git a/ci/centos7_python3_prepare.sh b/ci/centos7_python3_prepare.sh
index 58dd87f64e9f882ef5a763d7f46bafd9b47684e2..348e0fb5739e93a8f69dcf49b172ba567ed3d5b4 100644
--- a/ci/centos7_python3_prepare.sh
+++ b/ci/centos7_python3_prepare.sh
@@ -50,6 +50,7 @@ pip3 install Pyinstaller
pip3 install urllib3
pip3 install requests
pip3 install paramiko
+pip3 install psutil
pip3 install wget
pip3 install pyyaml
diff --git a/common/devkit_utils/devkit_client.py b/common/devkit_utils/devkit_client.py
index 7e806c9ff41a584f8c193687c0ed9d3bbc198b37..3d972bc7c2a598e7ba247900785f22623615b161 100644
--- a/common/devkit_utils/devkit_client.py
+++ b/common/devkit_utils/devkit_client.py
@@ -65,7 +65,20 @@ class DevKitClient:
logging.exception(ex)
pass
- def upload_report(self, file_path):
+ def upload_report_by_force(self, file_path):
+ ret = self.__upload_report(file_path)
+ if ret.status_code == requests.codes.ok:
+ return
+ if ret.json().get("code", "") == "JavaPerf.Upload.Recording.RecordingReachLimit":
+ records = self.__get_record_list()
+ task_id, create_time = "", "999999999999999999999999999999"
+ for o in records.json().get("members", []):
+ if float(o["createTime"]) < float(create_time):
+ task_id, create_time = o["id"], o["createTime"]
+ self.__delete_report(task_id)
+ self.__upload_report(file_path)
+
+ def __upload_report(self, file_path):
try:
data = dict({"file": (os.path.basename(file_path), open(file_path, "rb").read())})
except OSError as e:
@@ -80,7 +93,7 @@ class DevKitClient:
else:
return requests.post(url=url, headers=_header, data=encoded_data[0], verify=False, proxies=self.NO_PROXY)
- def get_record_list(self):
+ def __get_record_list(self):
url = f"https://{self.ip}:{self.port}/plugin/api/v1.0/java_perf/api/records/user/"
data = {"userId": self.user_id}
if self.use_proxy:
@@ -88,31 +101,9 @@ class DevKitClient:
else:
return requests.post(url=url, json=data, headers=self.header, verify=False, proxies=self.NO_PROXY)
- def delete_report(self, task_id):
+ def __delete_report(self, task_id):
url = f"https://{self.ip}:{self.port}/plugin/api/v1.0/java_perf/api/records/{task_id}/"
if self.use_proxy:
requests.delete(url=url, headers=self.header, verify=False)
else:
requests.delete(url=url, headers=self.header, verify=False, proxies=self.NO_PROXY)
-
- def upload_report_by_force(self, file_path):
- ret = self.upload_report(file_path)
- if ret.status_code == requests.codes.ok:
- return
- if ret.json().get("code", "") == "JavaPerf.Upload.Recording.RecordingReachLimit":
- records = self.get_record_list()
- task_id, create_time = "", "999999999999999999999999999999"
- for o in records.json().get("members", []):
- if float(o["createTime"]) < float(create_time):
- task_id, create_time = o["id"], o["createTime"]
- self.delete_report(task_id)
- self.upload_report(file_path)
-
-
-if __name__ == "__main__":
- try:
- d = DevKitClient("172.39.173.2", "8086", "devadmin", "Huawei12#$")
- d.upload_report_by_force("/home/panlonglong/Downloads/Main(136462)")
- d.logout()
- except Exception as e:
- print(str(e))
diff --git a/common/devkit_utils/pyinstaller_utils.py b/common/devkit_utils/pyinstaller_utils.py
index 91f578bcd2b2e90b671e9d36e432a031826aceb6..bde176c7243f3738f449bfdb54cf92809b9e81e0 100644
--- a/common/devkit_utils/pyinstaller_utils.py
+++ b/common/devkit_utils/pyinstaller_utils.py
@@ -1,22 +1,45 @@
+import copy
import os.path
import sys
-def check_is_running_in_pyinstaller_bundle():
- """
- 判断是否在pyinstaller
- """
- if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
- return True
- else:
- return False
+class PyInstallerUtils:
+ ORI_ENV = None
+ LD_LIBRARY_PATH_ORIG = "LD_LIBRARY_PATH_ORIG"
+ LD_LIBRARY_PATH = "LD_LIBRARY_PATH"
+ @classmethod
+ def check_is_running_in_pyinstaller_bundle(cls):
+ """
+ 判断是否在pyinstaller
+ """
+ if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
+ return True
+ else:
+ return False
-def obtain_root_path(root_path):
- """
- 获取rootpath,当在pyinstaller中时,为父目录,否则为传入的参数
- """
- if check_is_running_in_pyinstaller_bundle():
- return os.path.dirname(os.path.dirname(sys.executable))
- else:
- return root_path
+ @classmethod
+ def obtain_root_path(cls, root_path):
+ """
+ 获取rootpath,当在pyinstaller中时,为父目录,否则为传入的参数
+ """
+ if cls.check_is_running_in_pyinstaller_bundle():
+ return os.path.dirname(os.path.dirname(sys.executable))
+ else:
+ return root_path
+
+ @classmethod
+ def get_env(cls):
+ """
+ 返回的env,不允许修改
+ """
+ if cls.ORI_ENV:
+ return cls.ORI_ENV
+ env_copy = copy.deepcopy(os.environ)
+ if cls.check_is_running_in_pyinstaller_bundle():
+ if cls.LD_LIBRARY_PATH_ORIG in env_copy:
+ env_copy[cls.LD_LIBRARY_PATH] = env_copy.get(cls.LD_LIBRARY_PATH_ORIG)
+ else:
+ env_copy.pop(cls.LD_LIBRARY_PATH)
+ cls.ORI_ENV = env_copy
+ return cls.ORI_ENV
diff --git a/common/devkit_utils/shell_tools.py b/common/devkit_utils/shell_tools.py
index 07324f7074c360a6ab52de074ac306e6c65564f6..60fb33bf0aaa1b528d4a2dbf481ce5b004d262fc 100644
--- a/common/devkit_utils/shell_tools.py
+++ b/common/devkit_utils/shell_tools.py
@@ -3,6 +3,8 @@ import shlex
import subprocess
import typing
+from devkit_utils.pyinstaller_utils import PyInstallerUtils
+
class ExecutionOutcome:
def __init__(self, return_code=0, out=None, err=None):
@@ -14,17 +16,17 @@ class ExecutionOutcome:
return "code:%s\n out:%s\n err:%s\n" % (self.return_code, self.out, self.err)
-def exec_shell(command: str, is_shell=False, timeout=30) -> ExecutionOutcome:
+def exec_shell(command: str, is_shell=False, timeout=30, env=PyInstallerUtils.get_env()) -> ExecutionOutcome:
"""
执行命令,返回执行结果
"""
try:
if is_shell:
- child = subprocess.Popen(command, close_fds=True, stdout=subprocess.PIPE, stdin=None,
+ child = subprocess.Popen(command, close_fds=True, stdout=subprocess.PIPE, stdin=None, env=env,
stderr=subprocess.PIPE, encoding="utf-8", universal_newlines=True, shell=is_shell)
else:
- child = subprocess.Popen(shlex.split(command), close_fds=True, stdout=subprocess.PIPE, stdin=None,
+ child = subprocess.Popen(shlex.split(command), close_fds=True, stdout=subprocess.PIPE, stdin=None, env=env,
stderr=subprocess.PIPE, encoding="utf-8", universal_newlines=True)
except Exception as ex:
diff --git a/component/DevKitTester/JFRParser/pom.xml b/component/DevKitTester/JFRParser/pom.xml
index 36289eebb1d5a7920afed2e5475d41e31a8b8596..a2ac452ffcf5d092cf3f372e288592cdf203e93e 100644
--- a/component/DevKitTester/JFRParser/pom.xml
+++ b/component/DevKitTester/JFRParser/pom.xml
@@ -30,6 +30,11 @@
jackson-databind
2.16.1
+
+ org.apache.commons
+ commons-math3
+ 3.6.1
+
args4j
args4j
diff --git a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/CpuInfo.java b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/CpuInfo.java
index b37e5d436033b337b0db8902900b02d1e70c7d7b..3917bc146df200fb0d3e350ad2d9ae881e3ec44b 100644
--- a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/CpuInfo.java
+++ b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/CpuInfo.java
@@ -7,13 +7,13 @@ public class CpuInfo {
@JsonProperty("t")
private long startTime;
@JsonProperty("s")
- private float jvmSystem;
+ private Float jvmSystem;
@JsonProperty("u")
- private float jvmUser;
+ private Float jvmUser;
@JsonProperty("m")
- private float machineTotal;
+ private Float machineTotal;
- public CpuInfo(long startTime, float jvmSystem, float jvmUser, float machineTotal) {
+ public CpuInfo(long startTime, Float jvmSystem, Float jvmUser, Float machineTotal) {
this.startTime = startTime;
this.jvmSystem = jvmSystem;
this.jvmUser = jvmUser;
diff --git a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/JmeterReportSummary.java b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/JmeterReportSummary.java
index 01417eb367cd4f302db9643a32e9adb199fa337d..e677e1d0a137a230ac8720185459e062da06ec25 100644
--- a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/JmeterReportSummary.java
+++ b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/JmeterReportSummary.java
@@ -1,5 +1,8 @@
package com.huawei.devkit.pipeline.bo;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.huawei.devkit.pipeline.strategy.DoubleSerialize;
+
public class JmeterReportSummary {
private String label;
@@ -8,21 +11,29 @@ public class JmeterReportSummary {
private long failSamples;
+ @JsonSerialize(using = DoubleSerialize.class)
private double averageLatency;
- private long minLatency;
+ @JsonSerialize(using = DoubleSerialize.class)
+ private double minLatency;
- private long maxLatency;
+ @JsonSerialize(using = DoubleSerialize.class)
+ private double maxLatency;
- private long median;
+ @JsonSerialize(using = DoubleSerialize.class)
+ private double median;
- private long latency99;
+ @JsonSerialize(using = DoubleSerialize.class)
+ private double latency99;
- private long latency95;
+ @JsonSerialize(using = DoubleSerialize.class)
+ private double latency95;
- private long latency90;
+ @JsonSerialize(using = DoubleSerialize.class)
+ private double latency90;
- private long throughput;
+ @JsonSerialize(using = DoubleSerialize.class)
+ private double throughput;
public JmeterReportSummary(String label) {
this.label = label;
@@ -68,59 +79,59 @@ public class JmeterReportSummary {
this.averageLatency = averageLatency;
}
- public long getMinLatency() {
+ public double getMinLatency() {
return minLatency;
}
- public void setMinLatency(long minLatency) {
+ public void setMinLatency(double minLatency) {
this.minLatency = minLatency;
}
- public long getMaxLatency() {
+ public double getMaxLatency() {
return maxLatency;
}
- public void setMaxLatency(long maxLatency) {
+ public void setMaxLatency(double maxLatency) {
this.maxLatency = maxLatency;
}
- public long getMedian() {
+ public double getMedian() {
return median;
}
- public void setMedian(long median) {
+ public void setMedian(double median) {
this.median = median;
}
- public long getLatency99() {
+ public double getLatency99() {
return latency99;
}
- public void setLatency99(long latency99) {
+ public void setLatency99(double latency99) {
this.latency99 = latency99;
}
- public long getLatency95() {
+ public double getLatency95() {
return latency95;
}
- public void setLatency95(long latency95) {
+ public void setLatency95(double latency95) {
this.latency95 = latency95;
}
- public long getLatency90() {
+ public double getLatency90() {
return latency90;
}
- public void setLatency90(long latency90) {
+ public void setLatency90(double latency90) {
this.latency90 = latency90;
}
- public long getThroughput() {
+ public double getThroughput() {
return throughput;
}
- public void setThroughput(long throughput) {
+ public void setThroughput(double throughput) {
this.throughput = throughput;
}
}
diff --git a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/JmeterTPS.java b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/JmeterTPS.java
index 2b5d1c2d64d5247bffe3fe17bf6adf44bd933aff..d406ffc79fcd64e01c92a03aa9f268693be657b4 100644
--- a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/JmeterTPS.java
+++ b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/JmeterTPS.java
@@ -14,4 +14,19 @@ public class JmeterTPS {
this.tps = tps;
}
+ public Long getStartTime() {
+ return startTime;
+ }
+
+ public void setStartTime(Long startTime) {
+ this.startTime = startTime;
+ }
+
+ public int getTps() {
+ return tps;
+ }
+
+ public void setTps(int tps) {
+ this.tps = tps;
+ }
}
diff --git a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/MemInfo.java b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/MemInfo.java
index eef71220312b69535628d7225a6e686e45029ba0..2287cb85bc40e80a77bc8fe9e75d6929880b0b27 100644
--- a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/MemInfo.java
+++ b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/MemInfo.java
@@ -6,13 +6,13 @@ public class MemInfo {
@JsonProperty("t")
private long startTime;
@JsonProperty("c")
- private long committedSize;
+ private Long committedSize;
@JsonProperty("r")
- private long reservedSize;
+ private Long reservedSize;
@JsonProperty("u")
- private long heapUsed;
+ private Long heapUsed;
- public MemInfo(long startTime, long committedSize, long reservedSize, long heapUsed) {
+ public MemInfo(long startTime, Long committedSize, Long reservedSize, Long heapUsed) {
this.startTime = startTime;
this.committedSize = committedSize;
this.reservedSize = reservedSize;
diff --git a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/PerformanceTestResult.java b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/PerformanceTestResult.java
index 226cb208ed465bf56f61646dc1abee656e1d3c4f..445a93f82bf050927011ee7b09bb5b3fcb3eaffe 100644
--- a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/PerformanceTestResult.java
+++ b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/bo/PerformanceTestResult.java
@@ -9,6 +9,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
import java.util.stream.Collectors;
public class PerformanceTestResult {
@@ -73,6 +75,22 @@ public class PerformanceTestResult {
this.toSimpleObject(this.frtMap, this.frt, JmeterRT.class);
this.toSimpleObject(this.tpsMap, this.tps, JmeterTPS.class);
}
+ List allStartTime = memoryMap.values().stream()
+ .flatMap(innerMap -> innerMap.values().stream())
+ .flatMap(List::stream)
+ .map(MemInfo::getStartTime)
+ .distinct()
+ .sorted()
+ .collect(Collectors.toList());
+ this.insertNullInMemoryMap(allStartTime);
+ List allCpuStartTime = cpuMap.values().stream()
+ .flatMap(innerMap -> innerMap.values().stream())
+ .flatMap(List::stream)
+ .map(CpuInfo::getStartTime)
+ .distinct()
+ .sorted()
+ .collect(Collectors.toList());
+ this.insertNullInCpuMap(allCpuStartTime);
this.toSimpleObject2(this.memoryMap, this.memory, MemInfo.class);
this.toSimpleObject2(this.cpuMap, this.cpu, CpuInfo.class);
}
@@ -193,6 +211,52 @@ public class PerformanceTestResult {
}
}
+ private void insertNullInMemoryMap(List allStartTime) {
+ for (String key : this.memoryMap.keySet()) {
+ Map> oldMap = this.memoryMap.get(key);
+ Map> newMap = new HashMap<>();
+ for (Map.Entry> entry : oldMap.entrySet()) {
+ List memInfos = this.insertNullInMemoryMap(entry.getValue(), allStartTime);
+ newMap.put(entry.getKey(), memInfos);
+ }
+ this.memoryMap.put(key, newMap);
+ }
+ }
+
+ private List insertNullInMemoryMap(List target, List allStartTime) {
+ List finalMem = new ArrayList<>(allStartTime.size());
+ Map collected = target.stream()
+ .collect(Collectors.toMap(MemInfo::getStartTime, Function.identity()));
+ for (Long key : allStartTime) {
+ MemInfo info = collected.get(key);
+ finalMem.add(Objects.requireNonNullElseGet(info, () -> new MemInfo(key, null, null, null)));
+ }
+ return finalMem;
+ }
+
+ private void insertNullInCpuMap(List allStartTime) {
+ for (String key : this.cpuMap.keySet()) {
+ Map> oldMap = this.cpuMap.get(key);
+ Map> newMap = new HashMap<>();
+ for (Map.Entry> entry : oldMap.entrySet()) {
+ List memInfos = this.insertNullInCpuMap(entry.getValue(), allStartTime);
+ newMap.put(entry.getKey(), memInfos);
+ }
+ this.cpuMap.put(key, newMap);
+ }
+ }
+
+ private List insertNullInCpuMap(List target, List allStartTime) {
+ List finalMem = new ArrayList<>(allStartTime.size());
+ Map collected = target.stream()
+ .collect(Collectors.toMap(CpuInfo::getStartTime, Function.identity()));
+ for (Long key : allStartTime) {
+ CpuInfo info = collected.get(key);
+ finalMem.add(Objects.requireNonNullElseGet(info, () -> new CpuInfo(key, null, null, null)));
+ }
+ return finalMem;
+ }
+
private void toSimpleObject2(Map>> origin,
Map>>> target, Class clazz) {
for (Map.Entry>> entry : origin.entrySet()) {
diff --git a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/parser/JFRParser.java b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/parser/JFRParser.java
index ca3bcb33bf0afc76a54476269fc80ca03e18297a..46d3347496a65a5935048b216e868026e2447cca 100644
--- a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/parser/JFRParser.java
+++ b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/parser/JFRParser.java
@@ -15,8 +15,12 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
public class JFRParser {
public static Long ALL = -1L;
@@ -66,7 +70,16 @@ public class JFRParser {
Map> cpuMap = result.getCpuMap().get(nodeIP);
cpuMap.put(fileName, cpuInfos);
Map> memoryMap = result.getMemoryMap().get(nodeIP);
- memoryMap.put(fileName, memInfos);
+ Set allStartTime = new HashSet<>();
+ memoryMap.put(fileName, memInfos.stream().filter(item -> {
+ if (allStartTime.contains(item.getStartTime())) {
+ return false;
+ } else {
+ allStartTime.add(item.getStartTime());
+ return true;
+ }
+ })
+ .sorted(Comparator.comparingLong(MemInfo::getStartTime)).collect(Collectors.toList()));
for (LatencyTopInfo latencyTop : top10) {
result.getFlame().put(latencyTop.getKey(), latencyTop.getFlame());
}
diff --git a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/parser/JmeterResultParser.java b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/parser/JmeterResultParser.java
index f277eaff1dc5ba05440c8f106116e6ef191dfdd1..9ab9bd597c8b900d1f279c18328b2ba74c81253a 100644
--- a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/parser/JmeterResultParser.java
+++ b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/parser/JmeterResultParser.java
@@ -7,6 +7,7 @@ import com.huawei.devkit.pipeline.bo.JmeterTPS;
import com.huawei.devkit.pipeline.bo.PerformanceTestResult;
import com.huawei.devkit.pipeline.constants.JFRConstants;
import com.huawei.devkit.pipeline.utils.JmeterResultTransfer;
+import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -84,12 +85,12 @@ public class JmeterResultParser {
long start = startTime;
long end = startTime + JFRConstants.MS_1000;
-
+ DescriptiveStatistics statistics = new DescriptiveStatistics();
boolean exist = false;
for (int i = 0; start < endTime; start += JFRConstants.MS_1000, end += JFRConstants.MS_1000) {
-
while (i < results.size() && results.get(i).getStartTime() >= start && results.get(i).getStartTime() < end) {
summary.samplesIncrease();
+ statistics.addValue(results.get(i).getLatency());
latencyTotalPerSec += results.get(i).getLatency();
latencyTotal += results.get(i).getLatency();
samplePer++;
@@ -115,10 +116,16 @@ public class JmeterResultParser {
latencyFailPerSec = 0;
exist = false;
}
- summary.setThroughput(summary.getSamples() * JFRConstants.MS_TO_S /
- getThroughputTime(startTime, results.get(results.size() - 1).getStartTime()));
+ summary.setMinLatency(statistics.getMin());
+ summary.setMaxLatency(statistics.getMax());
+ summary.setMedian(statistics.getPercentile(50));
+ summary.setLatency90(statistics.getPercentile(90));
+ summary.setLatency95(statistics.getPercentile(95));
+ summary.setLatency99(statistics.getPercentile(99));
+ JmeterResult lastResult = results.get(results.size() - 1);
+ summary.setThroughput(summary.getSamples() * (double) JFRConstants.MS_TO_S /
+ getThroughputTime(startTime, lastResult.getStartTime() + lastResult.getLatency()));
summary.setAverageLatency(latencyTotal / (double) summary.getSamples());
- this.filledSummary(results);
}
public JmeterReportSummary getSummary() {
diff --git a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/strategy/DoubleSerialize.java b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/strategy/DoubleSerialize.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ae65739d2350c106f5fc5db4bf3c091d3c9dd21
--- /dev/null
+++ b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/strategy/DoubleSerialize.java
@@ -0,0 +1,22 @@
+package com.huawei.devkit.pipeline.strategy;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import java.io.IOException;
+import java.text.DecimalFormat;
+
+public class DoubleSerialize extends JsonSerializer {
+
+ public static final DecimalFormat DF = new DecimalFormat("#0.00");
+
+ @Override
+ public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers)
+ throws IOException, JsonProcessingException {
+ if (value != null) {
+ gen.writeString(DF.format(value));
+ }
+ }
+}
\ No newline at end of file
diff --git a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/utils/SimplifyResponse.java b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/utils/SimplifyResponse.java
index 188e2609bfc6894d610735e3ebb48e84876f2479..9841cd4cdceeca4bbb28c26b240822b34e80de9a 100644
--- a/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/utils/SimplifyResponse.java
+++ b/component/DevKitTester/JFRParser/src/main/java/com/huawei/devkit/pipeline/utils/SimplifyResponse.java
@@ -1,6 +1,7 @@
package com.huawei.devkit.pipeline.utils;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.huawei.devkit.pipeline.strategy.DoubleSerialize;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -26,9 +27,21 @@ public class SimplifyResponse {
List