Open swankjesse opened 1 month ago
I don't think plain objects is the right answer because they still need to undergo JSON encoding. It'll be faster, since it's C code instead of JS-hosted Kotlin code, but it's still JSON encoding.
We can instead teach each Change
subtype to JSON "encode" itself directly to a string and build up the JSON in a buildString
directly, only calling out to kotlinx.serialization for user types like you said.
I mean look at what we generate:
The Create
class can get a member
public fun appendJsonTo(builder: StringBuilder) {
builder.append("""["create",{"id":""")
builder.append(id.value)
builder.append(""","tag":""")
builder.append(tag.value)
builder.append("}]")
}
and we're done. Repeat for all the other subtypes.
Then with a custom serializer for List<Change>
we can do the top-level buildString
+ comma insertion, and then write that as an unsafe raw string into the JsonEncoder
.
An even more efficient version of this bypasses allocating any Change
instances and simply builds the raw JSON string directly. Unfortunately this breaks the current API unless we do something crazy like
class RawJsonChange : Change {
val json = StringBuidler()
}
and only have this single allocation per set of changes.
Doing JSON encoding in JS would be more efficient if we had a good StringBuilder on QuickJS. Sigh.
True. We could do a List
I used a sampling profiler to measure just how much time we’re spending in serialization code. For one sample I took it’s about 19% of the samples:
With this optimization implemented that drops down to about 3% of the samples:
Is this done?
We spend a lot of CPU encoding changes from Redwood. Right now the guest code goes through our very nice Kotlin APIs for ChangeSink and Change. Unfortunately kotlinx.serialization is not particularly inefficient here.
I’d like to try to write a new implementation of the guest versions of these classes that’s optimized for Kotlin/JS. I would like to skip directly to producing plain JS objects rather than creating Kotlin objects and then using kotlinx.serialization to convert ’em. (I will still need to use kotlinx.serialization to encode property values.)