-
Notifications
You must be signed in to change notification settings - Fork 596
Description
Environment
- Android (Kotlin)
- Wire version: (add your version)
- Gson / Moshi version: (add versions)
- Proto generated using wire-compiler
- App supports both binary protobuf and JSON responses
📌 Summary
I have an Android app that has used protobuf + wire-compiler–generated Kotlin data classes for a long time. Proto decoding is extremely fast, as expected.
We also added an option to return JSON responses for the same proto schema. To support this, I registered WireTypeAdapterFactory with Gson so I can decode JSON into the same generated Wire messages.
However, after switching to JSON responses, parsing time increased massively (multiple-fold slowdown) compared to protobuf. Even moderately nested messages take much longer to read, causing visible UI delays and frame drops.
I wrote a custom implementation of WireTypeAdapterFactory (mainly to change enum handling), and even after caching all RuntimeMessageAdapter instances, performance is still very slow.
I also tested with Moshi + WireJsonAdapterFactory, and while slightly faster, it still suffers from the same fundamental cost — JSON decoding of Wire messages is an order of magnitude slower than protobuf decoding.
🔍 What I Have Already Tried
✔️ 1. Caching RuntimeMessageAdapter instances
I verified that RuntimeMessageAdapter.create() is not being called repeatedly.
All adapters are cached in a global map. → No major improvement.
✔️ 2. Custom TypeAdapter with optimized field lookup
I built a custom implementation of WireTypeAdapterFactory that includes:
Cached field maps (nameToField)
Pre-bound setter lambdas to avoid reflection inside FieldBinding.set()
Inline fast paths for primitives (avoid TypeAdapter.read() for boolean/int/double/string)
✔️ 3. Switching from Gson → Moshi
Tried WireJsonAdapterFactory:
But, unfortunately none of this worked.
Example Proto (dummy simplified version)
message WidgetResponse {
WidgetConfig widget_config = 1;
oneof widgets {
Widget1 widget_1 = 2;
Widget2 widget_2 = 3;
}
}
message WidgetConfig {
WidgetType widget_type = 1;
}
enum WidgetType {
WIDGET_TYPE_1 = 0;
WIDGET_TYPE_2 = 1;
}
message Widget1 {
string title = 1;
}
message Widget2 {
string title = 1;
string subtitle = 2;
}
Please help me out in fixing this problem.