[Enhancement] Reduce allocation in ExtraInfoUtil POP info parsing and return primitives from numeric getters
- Dominant language
- Java
- Stars
- 22.6k
- Forks
- 12k
- Avg merge
- 3d 1h
- Merged PRs (30d)
- 27
Description
### Before Creating the Enhancement Request
- [x] I have confirmed that this should be classified as an enhancement rather than a bug/feature.
### Summary
Reduce per-request allocation in `ExtraInfoUtil`: parse POP `startOffsetInfo` / `msgOffsetInfo` / `orderCountInfo` without the intermediate `split` arrays, and return primitives from the numeric extraInfo getters.
### Motivation
Every POP response and every ACK goes through `ExtraInfoUtil`:
1. `parseStartOffsetInfo` / `parseMsgOffsetInfo` / `parseOrderCountInfo` split each entry with `one.split(KEY_SEPARATOR)` (a `String[]` plus three substrings per entry) and re-concatenate the first two fields into a map key; `parseMsgOffsetInfo` additionally splits the offset list with `split(",")`.
2. `getCkQueueOffset` / `getPopTime` / `getInvisibleTime` return boxed `Long` although every caller in the repository immediately assigns the result to a `long` (broker ACK/changeInvisibleTime paths, client batch-ack path, proxy `LocalMessageService`).
### Solution
- Walk each entry with `indexOf` instead of `split`: no intermediate array, and the map key is built with `StringBuilder.append(CharSequence, int, int)` without substrings. The value field keeps one substring for `parseLong` (Java 8 target has no range-parse API).
- Change the three getters to return `long` (`Long.parseLong` instead of `Long.valueOf`). This is source-compatible for all in-repo callers (none rely on nullability or identity); it is binary-incompatible for externally compiled bytecode, which needs a recompile.
- Behavior note: the previous split-based validation half-accepted corrupt entries with empty fields or trailing separators (producing keys like `"@a"`); the new validation rejects them with the same `IllegalArgumentException` used for other malformed shapes. Well-formed wire strings produced by the builders are unaffected, covered by new round-trip tests.
### Verification
- `ExtraInfoUtilTest` extended with round-trip (normal + retry topic, multi-entry), getter, and malformed-input cases; 5/5 pass. `AckMessageProcessorTest` / `ChangeInvisibleTimeProcessorTest` / `PopMessageProcessorTest` 25/25, `MQClientAPIImplTest` 133/133.
- 4-node cluster A/B in POP mode (`mqadmin setConsumeMode -m POP`, producer 64 threads + consumer 20 threads, consume TPS steady at 150–154k, 3 interleaved trials per side):
- broker side (remoting jar swapped on broker): young GC per million consumed msgs 2.60/2.62/2.70 (base) vs 2.63/2.64/2.62 (patch) — parity;
- client side (remoting jar swapped on consumer): 1.10/1.08/1.10 vs 1.11/1.10/1.10 — parity.
No regression on either side; the allocation saving itself (tens of bytes per response) is below GC-count resolution, so this is submitted as a cleanup-level optimization on a hot path.
Contributor guide
Research direction
Start in ExtraInfoUtil and trace parseStartOffsetInfo, parseMsgOffsetInfo, parseOrderCountInfo, and the three numeric getters. Read the extended ExtraInfoUtilTest round-trip and malformed-input cases first, then run it with AckMessageProcessorTest, ChangeInvisibleTimeProcessorTest, PopMessageProcessorTest, and MQClientAPIImplTest. Done means the listed tests pass while preserving well-formed POP behavior and reducing the described temporary allocations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, performance
- Issue type
- Refactor
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100