Before Creating the Enhancement Request
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:
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(",").
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.
Before Creating the Enhancement Request
Summary
Reduce per-request allocation in
ExtraInfoUtil: parse POPstartOffsetInfo/msgOffsetInfo/orderCountInfowithout the intermediatesplitarrays, and return primitives from the numeric extraInfo getters.Motivation
Every POP response and every ACK goes through
ExtraInfoUtil:parseStartOffsetInfo/parseMsgOffsetInfo/parseOrderCountInfosplit each entry withone.split(KEY_SEPARATOR)(aString[]plus three substrings per entry) and re-concatenate the first two fields into a map key;parseMsgOffsetInfoadditionally splits the offset list withsplit(",").getCkQueueOffset/getPopTime/getInvisibleTimereturn boxedLongalthough every caller in the repository immediately assigns the result to along(broker ACK/changeInvisibleTime paths, client batch-ack path, proxyLocalMessageService).Solution
indexOfinstead ofsplit: no intermediate array, and the map key is built withStringBuilder.append(CharSequence, int, int)without substrings. The value field keeps one substring forparseLong(Java 8 target has no range-parse API).long(Long.parseLonginstead ofLong.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."@a"); the new validation rejects them with the sameIllegalArgumentExceptionused for other malformed shapes. Well-formed wire strings produced by the builders are unaffected, covered by new round-trip tests.Verification
ExtraInfoUtilTestextended with round-trip (normal + retry topic, multi-entry), getter, and malformed-input cases; 5/5 pass.AckMessageProcessorTest/ChangeInvisibleTimeProcessorTest/PopMessageProcessorTest25/25,MQClientAPIImplTest133/133.mqadmin setConsumeMode -m POP, producer 64 threads + consumer 20 threads, consume TPS steady at 150–154k, 3 interleaved trials per side):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.