Original: Little Sister Taste (wechat official ID: XjjDog), welcome to share, non-official account reprint this statement reserved.

Jackson JSON has been used more and more widely since fastJSON became popular in China. Especially since the Spring family has made it the default JSON processing package, Jackson usage has exploded.

Many students have noticed that Jackson doesn’t have a really fast looking method like Fastjson’s json.parseobjec. To parse JSON, you have to create a new ObjectMapper to handle the actual parsing action.

It looks like this.

public String getCarString(Car car){
    ObjectMapper objectMapper = new ObjectMapper();
    String str = objectMapper.writeValueAsString(car);
    return str;
}

Copy the code

This kind of code is proliferating in the hands of CV engineers.

Magic.

Is there something wrong with this code?

You can say there’s something wrong with it, it does work correctly. If you say that it’s okay, it’s a piece of code that’s heinous to the performance minded.

Common utility classes are singletons and thread-safe. ObjectMapper is no exception, it is also thread-safe, you can execute it concurrently without any problems.

This code, ObjectMapper, generates one every time a method is called. In addition to causing a certain amount of young generation memory waste, does it have any serious impact on execution time?

Is there really that much difference between new and not new?

At one point, XJjDog obliquely pointed out a problem with a piece of code that was being called frequently, and was yelled at for evidence.

Evidence? To find out, consider JMH, the benchmark tool in Java.

JMH(the Java Microbenchmark Harness) is such a benchmark tool. If you use our suite of tools to locate hot code, test its performance data, and evaluate improvements, you can turn it over to JMH. Its measurement accuracy is very high, up to the nanosecond level.

JMH is a JAR package, much like the unit testing framework JUnit, that can be annotated for some basic configuration. Much of this configuration can be set using the OptionsBuilder of the main method.

The figure above shows what a typical JMH program does. By starting multiple processes, multiple threads, first perform warm-up, then perform iteration, and finally summarize all test data for analysis. Some pre – and post-operations can also be handled before and after execution, depending on granularity.

JMH test results

To test the above scenario, we created the following benchmark class. Divided into three test scenarios:

  1. So directly in the method new ObjectMapper

  2. Share an ObjectMapper globally

  3. With ThreadLocal, one ObjectMapper per thread

Such tests are CPU intensive. My CPU had 10 cores and allocated 10 concurrent threads directly, so the CPU ran full during the test.

@BenchmarkMode({Mode.Throughput}) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Thread) @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @Fork(1) @Threads(10) public class ObjectMapperTest { String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; @State(Scope.Benchmark) public static class BenchmarkState { ObjectMapper GLOBAL_MAP = new ObjectMapper(); ThreadLocal<ObjectMapper> GLOBAL_MAP_THREAD = new ThreadLocal<>(); } @Benchmark public Map globalTest(BenchmarkState state) throws Exception{ Map map = state.GLOBAL_MAP.readValue(json, Map.class); return map; } @Benchmark public Map globalTestThreadLocal(BenchmarkState state) throws Exception{ if(null == state.GLOBAL_MAP_THREAD.get()){ state.GLOBAL_MAP_THREAD.set(new ObjectMapper()); } Map map = state.GLOBAL_MAP_THREAD.get().readValue(json, Map.class); return map; } @Benchmark public Map localTest() throws Exception{ ObjectMapper objectMapper = new ObjectMapper(); Map map = objectMapper.readValue(json, Map.class); return map; } public static void main(String[] args) throws Exception { Options opts = new OptionsBuilder() .include(ObjectMapperTest.class.getSimpleName()) .resultFormat(ResultFormatType.CSV) .build(); new Runner(opts).run(); }}Copy the code

The test results are as follows.

Benchmark Mode Cnt Score Error Units ObjectMapperTest. GlobalTest THRPT 5 to 25125094.559 + 1754308.010 ops/s ObjectMapperTest. GlobalTestThreadLocal THRPT. 5 to 31780573.549 + 7779240.155 ops/s ObjectMapperTest localTest THRPT 5 2131394.345 + / - 216974.682 ops/sCopy the code

From our test results, we can perform 2 million JSON parses per second if we call a new ObjectMapper per second. If an ObjectMapper is used globally, it can execute more than 20 million times per second, which is 10 times faster.

If ThreadLocal is used and each thread is assigned a parser, performance improves a little, but not dramatically.

So when writing code in a project, we just need to make sure we have a global ObjectMapper.

Of course, since ObjectMapper has many features to configure, you may want to assign a separate ObjectMapper for different application scenarios. In short, it doesn’t need to be much because it’s thread-safe.

End

So the conclusion is relatively clear, we only need to use one ObjectMapper in the whole project, there is no need to foollessly pull several new one every time, after all, the performance is 10 times worse. If your JSON has a lot of custom configuration, using global variables is a great advantage.

Don’t feel it’s unnecessary to do this; it’s always good to maintain good coding habits. High-performance code is accumulated bit by bit. A thousand miles is a short step. Not small streams, beyond into rivers and seas, that is the truth.

Xjjdog is a public account that doesn’t allow programmers to get sidetracked. Focus on infrastructure and Linux. Ten years architecture, ten billion daily flow, and you discuss the world of high concurrency, give you a different taste. My personal wechat xjjdog0, welcome to add friends, further communication.

Recommended reading:

2. What does the album taste like

3. Bluetooth is like a dream 4. 5. Lost architect, leaving only a script 6. Bugs written by architect, unusual 7. Some programmers, nature is a flock of sheep!

Taste of little sister

Not envy mandarin duck not envy fairy, a line of code half a day

333 original content