Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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). 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 automatic serialization

Trace of manual serialization: Trace of manual serialization

like image 326
GeorgeStone Avatar asked Jul 17 '16 15:07

GeorgeStone


People also ask

Does Jackson use serializable?

Note that Jackson does not use java. io. Serializable for anything: there is no real value for adding that. It gets ignored.

Does Spring MVC use Jackson?

Spring uses Jackson internally for serializing and deserializing data in json format. It just works in most cases.

Does spring use Jackson by default?

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.

What is Jackson object serialization?

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.


1 Answers

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.

like image 128
Miloš Milivojević Avatar answered Sep 21 '22 08:09

Miloš Milivojević