square / square/wire

Parsing time too long while using WireTypeAdapterFactory

Open
#3,460 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
4.4k
Forks
627
Avg merge
3d 15m
Merged PRs (30d)
20

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the WireTypeAdapterFactory, RuntimeMessageAdapter, and WireJsonAdapterFactory entry points mentioned in the report, using the supplied WidgetResponse schema as a reproduction case. Confirm the Wire, Gson, and Moshi versions and compare JSON and protobuf parsing with a repeatable benchmark. Done means the performance bottleneck is identified and a measurable improvement is demonstrated.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, kotlin
Domain
mobile-dev, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.