[英]Why is Spring MVC json serialization 10x slower than calling jackson manually?
Using apachebench with "ab -k -c 50 -n 1000000" options (50 concurrent threads) shows a 10x performance difference between the following 2 methods (manual and spring-managed serialization). 将apachebench与“ ab -k -c 50 -n 1000000”选项(50个并发线程)一起使用时,在以下两种方法(手动和弹簧管理的序列化)之间的性能差异为10倍。 Is it possible to achieve the same performance via configuration of Spring serialization? 通过配置Spring序列化可以实现相同的性能吗?
I'm running the test on Windows 7, JDK8, i7-6700. 我正在Windows 7,JDK8,i7-6700上运行测试。 Embedded Tomcat , similar results with Undertow or Jetty too. 嵌入式Tomcat ,与Undertow或Jetty相似的结果。 A similar WildFly 10 JAX-RS sample apps performance yields similar results as the manual spring one, so I see no reason why Spring automatic mode should be so slow. 类似的WildFly 10 JAX-RS样本应用程序性能所产生的结果与手动spring相似,因此我认为没有理由说明Spring自动模式应该这么慢。
Full source code: 完整的源代码:
@SpringBootApplication
@Controller
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
ObjectMapper mapper = new ObjectMapper(new JsonFactory());
@RequestMapping(value = "/auto", produces = "application/json; charset=utf-8")
@ResponseBody
public Lol automaticSerialization() {
Lol lol = new Lol();
lol.a = UUID.randomUUID().toString();
lol.b = System.currentTimeMillis();
return lol;
}
@RequestMapping(value = "/manual", produces = "application/json; charset=utf-8")
@ResponseBody
public String manualSerialization() throws JsonProcessingException {
Lol lol = new Lol();
lol.a = UUID.randomUUID().toString();
lol.b = System.currentTimeMillis();
return mapper.writeValueAsString(lol);
}
public static class Lol {
String a;
long b;
public void setA(String a) {
this.a = a;
}
public void setB(long b) {
this.b = b;
}
public String getA() {
return a;
}
public long getB() {
return b;
}
}
}
The only idea that I have is that Spring's default ObjectMapper
is configured a bit differently than the one you use in your benchmark. 我唯一的想法是,Spring的默认ObjectMapper
的配置与您在基准测试中使用的配置有所不同。 Like the comments mention, you'd probably see a bit of overhead if you let Spring handle the mapping automatically but it shouldn't have more than a few percent's worth of impact. 就像提到的评论一样,如果让Spring自动处理映射,您可能会看到一些开销,但是影响不应该超过百分之几。
To be sure that the comparison is fair, add this bean definition to your configuration: 为了确保比较是公平的,请将以下bean定义添加到您的配置中:
@Bean
@Primary
ObjectMapper objectMapper() {
return new ObjectMapper(new JsonFactory());
}
and replace ObjectMapper mapper = new ObjectMapper(new JsonFactory());
并替换ObjectMapper mapper = new ObjectMapper(new JsonFactory());
with an autowired field: 具有自动连接的字段:
@Autowired
ObjectMapper mapper;
and see if the benchmarks return the same value. 并查看基准是否返回相同的值。
EDIT 编辑
I wanted to verify this for myselt so I wrote a JMeter plan and executed each endpoint exactly 5kk times, with a 1-minute warm-up period. 我想为自己进行验证,因此我编写了一个JMeter计划,并在5分钟内准确地执行了每个端点,预热了1分钟。 The results were as expected, no major differences between the approaches: 结果符合预期,两种方法之间没有重大差异:
Label,# Samples,Average,Min,Max,Std. Dev.,Error %,Throughput,KB/sec,Avg. Bytes
Auto Request,5000000,2,0,108,5.88,0.00%,15577.3,3088.08,203.0
Manual Request,5000000,2,0,149,5.99,0.00%,15660.2,2813.94,184.0
The important thing to note is the throughput difference - auto's 15577.3 vs. manual's 15660.2. 要注意的重要一点是吞吐量的差异-自动的15577.3与手动的15660.2。
Here's my JMeter test plan , if you'd like to test it yourself, I was running on port 8081. If I find the time, I'll try another benchmarking framework, perhaps Gatling. 这是我的JMeter测试计划 ,如果您想自己测试,我正在8081端口上运行。如果有时间,我将尝试另一个基准测试框架,也许是加特林。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.