Description
JSON deserialization is extremely slow, at least on JS target. I've written the same deserializer myself like this:
override fun decode(string: String): List<ServerEvent> {
val jsonArray = JSON.parse<Array<Array<Any>>>(string)
return jsonArray.map { it.toEvent() }
}
private fun Array<Any>.toEvent(): ServerEvent {
val type = this[0] as String
val content = this[1].unsafeCast<Json>()
return when (type) {
"a" -> ServerImageDataReplyEvent(
content["a"].unsafeCast<Array<Any>>().toImageId(),
content["b"].unsafeCast<Array<Any>>().toImageData()
)
"b" -> ServerPingReplyEvent(content["a"] as Int, content["b"] as Int)
"c" -> ServerClipboardEvent(content["a"] as String)
// ...
It is tedious to write and support but it gives a boost of about 10x. Without the fix, deserialization takes about 80% of processing a message from server time. After the fix, it's only about 30% that is acceptable now.
To Reproduce
For convenience, I've extracted the protocol and deserializer part from our app and created a sample repo: https://github.com/SerVB/kx-serialization-js-benchmark.
I've taken a real JSON which is sent in our app with a size of 200 KB and tested the time of the following deserialization methods:
kotlinx.serialization.json.Json.parse
kotlinx.serialization.DynamicObjectParser.parse
- 3 ways of manual deserialization: using
JSON.parse
and then reading it as JS objects.
It turns out that manual variants are about 20x faster. On smaller JSON sizes, the difference is smaller: in our app, the difference is 10x on average.
You can try it yourself: https://servb.github.io/kx-serialization-js-benchmark/index.html. Just click a button and it will print test results. You can find the results I've received in the README.
Possible solution
I think there should be an option to generate inlined code for deserializer. It's what I've done myself, but autogeneration is what I need here because I believe there can be many errors left in my manual code. Also, autogeneration will help to update deserialization immediately when we change our protocol.
Environment
- Kotlin version: 1.3.72
- Library version: 0.20.0
- Kotlin platforms: JS
- Gradle version: 6.1.1