perf(serializer): generate the Moshi adapter with KSP instead of reflection - #552
perf(serializer): generate the Moshi adapter with KSP instead of reflection#552yoobi wants to merge 7 commits into
Conversation
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 0 |
| Duplication | 0 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
… into feat/moshi-codegen # Conflicts: # gradle/libs.versions.toml # serializer/moshi/src/test/kotlin/io/wax911/emojify/serializer/moshi/MoshiDeserializerTest.kt
|
@wax911 fixed the missing doc, but I think the Android CI / Spotless needs a fix as well, it fails on Set up JDK |
|
I checked this PR out into a worktree and ran it locally. The implementation is correct and verified working, but I have one compatibility concern before approving. Per-file
Nits (optional, non-blocking)
CI note (the "spotless" failure you flagged)Not a formatting issue — every job using
|
There was a problem hiding this comment.
KSP codegen verified working locally (adapter generated, moshi tests pass, spotless clean). See my detailed review comment above for per-file assessment. CI will go green once rerun picks up the temurin fix from develop (#555 merged).
|
I’ll check the license scan failure |
# Conflicts: # .github/workflows/android-ci.yml
6fbc0ab to
658b3a3
Compare
Concurrent push race — apology and context@yoobi — I owe you an explanation for what happened to your branch today. While reviewing this PR I needed to fix two pre-existing CI issues on I later recovered your commit ( I see you've since reset your branch back to If you're preparing your own rebase onto
Sorry for the mess on your branch. Happy to help if you'd like me to do anything on this side. |
Description of Bug
MoshiEmojiis annotated@JsonClass(generateAdapter = true), butserializer/moshi/build.gradle.ktsapplies only the shared
io.wax911.emojifyconvention plugin — no KSP and nomoshi-kotlin-codegen— and there is no KSP in
buildSrceither, so the generated adapter is never produced. At runtimeMoshiDeserializertherefore falls back toMoshi.Builder().addLast(KotlinJsonAdapterFactory())andparses the ~480 KB
emoticons/emoji.jsonasset entirely by reflection.By contrast
serializer/kotlinx/build.gradle.ktsdoes apply itskotlinx-serializationplugin, sothat serializer is codegen-backed. The annotation on
MoshiEmojisuggests codegen was intended forthe Moshi path as well.
Reproduction Steps
emojify+contract+moshi.2.0-2.5 s.
moshiartifact: it containsMoshiDeserializerandMoshiEmoji, but nogenerated
MoshiEmojiJsonAdapter, confirming codegen never ran.Additional Context
Why it bites in practice: with Hilt the manager is typically provided as a
@Singleton, so the firstfield injection that asks for it resolves it on the main thread — in my case inside a fragment
transaction, which produced a visible stall when opening a screen containing comments. Resolving it
via a
Provideron a background dispatcher at application startup fixes the symptom, but the ~1.5 sof CPU is still paid on every cold start.
I measured the difference rather than guessing. Implementing
IEmojiDeserializerin my own modulewith an identical model — same fields, same
@Jsonnames, the only change being that KSP actuallyruns, and a plain
Moshi.Builder().build()so the generated adapter is used — gives, in one process,alternating A/B/A/B to cancel out page-cache and JIT warm-up (API 35 arm64 emulator, debug build):
MoshiDeserializer)create()in the process (cold)create()(warm)Both produced 1603 entries, and comparing all of them field by field across every
IEmojipropertygave 0 mismatches, so this is like-for-like output.
The interesting part is the cold/warm split: the reflective path costs ~2 s the first time and
under 100 ms afterwards, so almost all of it is one-time
kotlin-reflectinitialisation rather thanper-parse work. Since
EmojiManageris normally a singleton created once per process, real appsalways pay the expensive first call.
Suggested fix: add KSP +
moshi-kotlin-codegento theserializer/moshimodule — no API change, andon these numbers it removes ~2 s of cold-start CPU.
It may also be worth a line in the README noting that
create()performs blocking asset I/O plus afull parse of the emoji list, and should be called off the main thread.