Hi!
You've implemented RuntimeJsonAdapterFactory
I am writing analogue of this for case if polymorphic json looks like that:
{
"type" : "type1",
"value" : { /*some object details here*/}
}
I have two variants in this case:
fromJson like that:val jsonValue = reader.readJsonValue()
val jsonObject = jsonValue as Map<String, Any>?
val resultLabel = jsonObject!![labelKey] as String
val delegate = labelToAdapter[resultLabel]
val obj = delegate!!.fromJsonValue(jsonObject["value"])
return obj
And in this case simple 10 mb json with array of such objects will be parsed in about 350 ms (with warmup)
And if i am implementing like this:
reader.readJsonValue()
reader.beginObject()
reader.nextName() //asserttype
val resultLabel = reader.nextString()
reader.nextName() //value - if value
val delegate = labelToAdapter[resultLabel]
val obj = delegate!!.fromJson(reader)
reader.endObject()
return obj
This gives me around 170 ms.
Possibility to read all the json at once especially in _top of json hierarchy_ can lead to decrease of time parse up to 2 times (and increased memory footprint ofc).
So, if i use RuntimeJsonAdapterFactory my parsing speed is slowing down.
In my case it is pretty simple to do such a thing (i omitted case when fields order can be random btw).
Why i am asking, looks like for RuntimeJsonAdapterFactory in most cases there we are not need to read all the json as object, and simply go through in "flat" mode (do not go deeply inside a structure, just see the "top level"). Then looks like it would be more efficient to go through reader in "not markable" mode and then use fromJson with reader(move peek to start of object for example).
As far as I understand it can be tricky or just not in the nature of json parsers, but I hope I showed a good point for optimisation.
Maybe there any workarounds? Maybe okio can help?
ps:
As far as i know the same is the issue for gson (we have 100kb request with nesting polymorphic objects, that can be parsed up to 800ms)
10 mb json
huge. How many Java objects are getting allocated in readJsonValue() then? I'm guessing that's what's taking so much time. Also, all the names in the maps have to be decoded and have strings allocated in the readJsonValue case.
Typically, it's not a big deal to create a bunch of extra intermediate Java objects, but that's a big structure.
Time ratio 1 : 2 remains the same even if i cut the json off to 100kb.
Memory consumption is bigger ofc, and yes, there are much more temporary objects (100泻b json parsing is about 100 and 200 ms with warmup on my android device):


We use the polymorphic objects with nesting polymorphic objects (etc) broadly in our app. Hence, if we can speed up parsing time two times (and diminish memory footprint, gc calling) simply by not reading the whole json, it is very big deal to us. Getting rid of necessity of preliminary parsing would be a nice advantage.
ps: There are some traces from AS, and a pet project (you can see KeyRuntimeJsonAdapter).
Due to creating a bigger amount of objects (afaiu), the json-to-object trace had generated 5 times longer than do-not-read-the-whole-object one and has 3 times bigger size also.
TestApp.zip
do_not_read_json_as_object.trace.zip
read_json_as_object.trace.zip
I'd like to do this with peek() instead of readJsonValue. Shouldn鈥檛 be impossible...
I'm curious which will be faster. With peek(), you'll have to decode the JSON twice for the RuntimeJsonAdapterFactory.
I have tested new modification of polymorphic factory for my json case (today's master).
Parsing is 5 times slower rn :(
My implementation lies in second and third package, if you are interested in: KeyRuntimeJsonAdapterFactory.
TestApp.zip
@NightlyNexus Hello from KotlinConf guy :)
Can I help you out somehow?
5x slower? Whoa! That鈥檚 something we could profile.
Most helpful comment
I'd like to do this with peek() instead of readJsonValue. Shouldn鈥檛 be impossible...