Skip to content

[Enhancement] Reduce allocation in ExtraInfoUtil POP info parsing and return primitives from numeric getters #10973

Description

@wang-jiahua

Before Creating the Enhancement Request

  • 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions