How to increase your performance in Kotlin?
Have you ever wondered if your JSON serialization and deserialization performance is perfect? Are your defaults “optimal” in every scenario or maybe there is something superior?
We all know that whenever using REST, making calls to any other microservice or even working with some files, improvements in serialization and deserialization can be extremely quickly forgotten. However, they can create multiple problems, leading to some scenarios where handling 10,000,000 requests daily might create enormous latency in your application.

Is there a way to measure it? If so — how? And what are maybe some alternatives in the typical serialization and deserialization scenario?
Before we dive into it — let’s see what tools are mostly used for this task.
Which JSON libraries are mostly used?
Jackson and Gson are mostly used, especially for Java, and are also similarly used for Kotlin on the backend. What is more, there was also kotlinx.serialization , a library released by JetBrains a couple of years ago. Having those three libraries, one might be more convenient to use Jackson, someone else prefers Gson and someone else native serialization.

But is there one that is superior than the others?
How can you check performance in the system?
Usually — the tool that has been battle-tested and has been around for many years is Java Microbenchmark Harness (JMH) — which allows you to run nano/micro/milli/macro benchmarks which are written in languages that target JVM.

Before working on any kind of performance test — it is important to answer a couple of questions:
What behaviour of the system do we plan to test?
We are verifying the serialization and deserialization of the JSON files.
What data will you use as input for tests?
In the current scenario, we have created four different JSON files:
- Simple JSON
{
"website": "www.codingflower.com"
}2. Complex JSON
{
"id": "5fd2c8d36ce07686bcc76b2b",
"index": 0,
"guid": "25bbb5bd-4fcb-4dc5-ba93-f83816b4e502",
"isActive": true,
"picture": "http://placehold.it/32x32",
"age": 25,
"eyeColor": "blue",
"name": {
"first": "Shawna",
"last": "Byers"
},
"company": "ZILLA",
"tags": [
"sit",
"cillum",
"irure",
"deserunt",
"elit",
"mollit",
"ad"
],
"range": [
0,
1,
8,
9
],
"friends": [
{
"id": 0,
"name": "Hopkins Savage"
},
{
"id": 1,
"name": "Tasha Cooley"
},
{
"id": 2,
"name": "Tami Newman"
},
{
"id": 3,
"name": "Angelica Hopper"
},
{
"id": 4,
"name": "Valdez Terrell"
},
{
"id": 5,
"name": "Carlson Ramos"
},
{
"id": 6,
"name": "Elinor Pope"
},
{
"id": 7,
"name": "Vincent Rush"
},
{
"id": 13,
"name": "Elisa Burt"
},
{
"id": 14,
"name": "Maribel Jacobson"
},
{
"id": 15,
"name": "Blanche Fleming"
},
{
"id": 16,
"name": "Daisy Robles"
},
{
"id": 17,
"name": "Schultz Booker"
}
],
"rating": {
"1": " Mcclain",
"2": " Villarreal",
"3": " Bailey",
"4": " Keith",
"5": " Michael",
"6": " Booth",
"14": " Joseph",
"15": " Erickson",
"16": " Willis",
"17": " Carney",
"18": " Hansen",
"19": " Spencer",
"20": " Le"
}
}3. List with 1000 simple JSONs
4. List with 100 complex JSONs
What implementations do you want to compare with each other?
We are trying to compare Jackson, Gson and Kotlinx.
What are you EXACTLY testing?
Here we are testing the number of operations per unit of time — Throughput.
How can you benchmark all of those tests?
Having all the above configuration we have 24 different runs — 3 libraries, 2 different behaviours and 4 different inputs, so let’s run it!

Simple JSON serialization
All three libraries had to serialize given simple objects to JSON.
@Benchmark
fun jackson(bl: Blackhole) {
val text = jackson.writeValueAsString(simpleJson)
bl.consume(text)
}
@Benchmark
fun gson(bl: Blackhole) {
val text = gson.toJson(simpleJson)
bl.consume(text)
}
@Benchmark
fun kotlin(bl: Blackhole) {
val text = kotlinx.encodeToString(simpleJson)
bl.consume(text)
}The results are presented in the chart below.

As you see, the highest throughput shows Jackson, followed by Gson and only afterwards Kotlinx. It gives a piece of short and concise information — for simple JSON, stick to Jackson!
Simple JSON deserialization
This time deserialization of simple JSON was measured:
@Benchmark
fun jackson(bl: Blackhole) {
val simpleJson = jackson.readValue(simpleText, SimpleJson::class.java)
bl.consume(simpleJson)
}
@Benchmark
fun gson(bl: Blackhole) {
val simpleJson = gson.fromJson(simpleText, SimpleJson::class.java)
bl.consume(simpleJson)
}
@Benchmark
fun kotlinx(bl: Blackhole) {
val simpleJson = kotlinx.decodeFromString<SimpleJson>(simpleText)
bl.consume(simpleJson)
}And the results are as follows:

As you see, there isn’t a huge difference between Kotlinx and Jackson as it was before. What is more — Gson is leading in this scenario for simple deserialization of the objects.
Simple objects list serialization
Similarly to the scenario above — we have verified with the simple objects list situation. As the code looks extremely similar, here is the most important thing, the results:

Jackson is still leading with the serialization. On the other hand, Kotlinx has taken over the 2nd place over the Gson and stopped being the last place.
Simple JSON list deserialization
The chart with the result of benchmarking 1000 simpleJson in one JSON array is under the code snippet:
@Benchmark
fun jackson(bl: Blackhole) {
val simpleJsons = jackson.readValue<List<SimpleJson>>(text)
bl.consume(simpleJsons)
}
@Benchmark
fun gson(bl: Blackhole) {
val itemType = object : TypeToken<List<SimpleJson>>() {}.type
val simpleJsons = gson.fromJson<List<SimpleJson>>(text, itemType)
bl.consume(simpleJsons)
}
@Benchmark
fun kotlinx(bl: Blackhole) {
val simpleJsons = kotlinx.decodeFromString<List<SimpleJson>>(text)
bl.consume(simpleJsons)
}The results are as follows:

And similarly with the deserialization of the simple objects — Gson is the fastest. Kotlinx also took over Jackson in 2nd place however, still didn't manage to beat any other library in any of the scenarios.
Complex JSON serialization and deserialization
Similarly performed, here are the checks for the complex JSON verification.


As you see, the leader in object serialization is mostly Jackson. On the other hand, deserialization seems to be winning almost always Gson. Kotlinx is never in the first place.
Complex objects list serialization and deserialization
Serializing the list of 100 complex objects shows similar results to the one above:


Jackson is leading the serialization throughput, yet the deserialization is working much better for Gson.
Which should you choose?
There are a couple of things important here — sometimes what you need is not performance, but clarity in the code, therefore always consider whether the changes that you are going to make will not make your code more ugly than it already is.

On the other hand , if you look to improve your performance, based on those results, we can see a couple of things:
- Jackson is fastest in serialization, but also slowest in deserialization
- Gson copes best with deserialization, but complex objects are much harder for him
- Kotlinx is kind of in the middle — not the worst, but also not the best
If you are looking for the fastest solution — Jackson for serialization and Gson for deserialization. Combining benefits of both of them, gives you the performance and power that you need.
On the other hand, if you aren’t looking for a tenth of a second improvement in JSON serialization and deserialization, go for something that is the most widely used, like Jackson, making sure that you can easily achieve everything there and that this solution is extremely battle-tested.
If you are looking for some other stories related to Java or Kotlin, check out this:





