为什么Spring MVC json序列化比手动调用jackson慢10倍?

Geo*_*one 8 performance spring spring-mvc jackson

使用带有"ab -k -c 50 -n 1000000"选项的apachebench(50个并发线程)显示以下两种方法(手动和弹簧管理的序列化)之间的性能差异为10倍.是否可以通过配置Spring序列化来实现相同的性能?

我在Windows 7,JDK8,i7-6700上运行测试.嵌入式Tomcat,与UndertowJetty类似的结果.类似的WildFly 10 JAX-RS示例应用程序性能产生与手动弹簧类似的结果,因此我认为没有理由为什么Spring自动模式应该如此慢.

完整源代码:

@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;
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

编辑:自动序列化的跟踪: 跟踪自动序列化

跟踪手动序列化: 跟踪手动序列化

Mil*_*vić 5

我唯一的想法是 Spring 的默认ObjectMapper配置与您在基准测试中使用的配置略有不同。就像评论中提到的那样,如果让 Spring 自动处理映射,您可能会看到一些开销,但它的影响不应超过百分之几。

为了确保比较是公平的,请将此 bean 定义添加到您的配置中:

@Bean
@Primary
ObjectMapper objectMapper() {
    return new ObjectMapper(new JsonFactory());
}
Run Code Online (Sandbox Code Playgroud)

并替换ObjectMapper mapper = new ObjectMapper(new JsonFactory());为自动装配字段:

@Autowired
ObjectMapper mapper;
Run Code Online (Sandbox Code Playgroud)

并查看基准是否返回相同的值。

编辑

我想为 myselt 验证这一点,所以我编写了一个 JMeter 计划,并准确地执行每个端点 5kk 次,预热时间为 1 分钟。结果符合预期,方法之间没有重大差异:

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
Run Code Online (Sandbox Code Playgroud)

需要注意的重要一点是吞吐量差异 - 自动的 15577.3 与手动的 15660.2。

这是我的 JMeter 测试计划,如果你想自己测试,我在 8081 端口上运行。如果我有时间,我会尝试另一个基准测试框架,也许是 Gatling。