Optimize JsonElement
I’m using kotlinx.serialization on Kotlin/JS. I wrote some code that did something like this:
val value = 1L
val jsonElement = Json.encodeToJsonElement(value)
val dynamic = Json.encodeToDynamic(jsonElement)
(In my actual code, each of these 3 lines happen in different parts of the application. And in my actual code, the value is a more sophisticated data class.)
When I ran this code, it was super slow! In particular I found that a severe bottleneck for my entire program was encoding 1L as a string, and then converting it back to a number.
In particular, this code in JsonElementSerializer was a hot spot:
https://github.com/Kotlin/kotlinx.serialization/blob/master/formats/json/commonMain/src/kotlinx/serialization/json/JsonElementSerializers.kt#L120-L122
// use .content instead of .longOrNull as latter can process exponential notation,
// and it should be delegated to double when encoding.
value.content.toLongOrNull()?.let { return encoder.encodeLong(it) }
This is partly because Long is inefficient on Kotlin/JS, and partly because String.toLongOrNull() does a lot of work.
I was able to get dramatically better performance by skipping the JsonElement intermediate model:
val value = 1L
val dynamic = Json.encodeToDynamic(value)
Here’s the actual PR if you’re curious.
I would like for JsonElement to be a low-cost abstraction. In particular I believe the before & after samples above should have similar performance.
Thanks for your investigation! I'll see what I can do with it. Since Double formatting is already different on JS, maybe we'll be able to make this part platform-specific