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). Is it possible to achieve the same performance via configuration of Spring serialization?
I'm running the test on Windows 7, JDK8, i7-6700. Embedded Tomcat, similar results with Undertow or Jetty too. 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.
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;
}
}
}
Edit: Trace of automatic serialization:
Trace of manual serialization:
Note that Jackson does not use java. io. Serializable for anything: there is no real value for adding that. It gets ignored.
Spring uses Jackson internally for serializing and deserializing data in json format. It just works in most cases.
Spring Framework and Spring Boot provide builtin support for Jackson based XML serialization/deserialization. As soon as you include the jackson-dataformat-xml dependency to your project, it is automatically used instead of JAXB2.
Jackson is a solid and mature JSON serialization/deserialization library for Java. The ObjectMapper API provides a straightforward way to parse and generate JSON response objects with a lot of flexibility.
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. 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.
To be sure that the comparison is fair, add this bean definition to your configuration:
@Bean
@Primary
ObjectMapper objectMapper() {
return new ObjectMapper(new JsonFactory());
}
and replace 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. 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With