[ISSUE #10813] Reduce temporary allocations in the LMQ append path - #10814
[ISSUE #10813] Reduce temporary allocations in the LMQ append path#10814ai-yang wants to merge 1 commit into
Conversation
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Summary
Reduces temporary allocations in the LMQ append path by: (1) building offset strings with StringBuilder.append(long) instead of boxed Long[] + StringUtils.join; (2) parsing multi-dispatch queue names once and reusing them; (3) serializing properties once on the normal path. Good test coverage including a regression test for the original issue.
Findings
- [Info]
LmqDispatch.java— The newprepareLmqDispatchmethod cleanly separates the queue-name resolution from the offset computation. TheparseLmqDispatchQueuescaching viamsgInner.setEncodedBuffis a good optimization. - [Info]
CommitLog.java:1992— ThelmqQueueNamesvariable is declared outside theif (isMultiDispatchMsg)block and reused in the encode-completed path. This is correct and avoids redundant parsing.
LGTM.
Automated review by github-manager-bot
|
Non-blocking readability suggestion: separate LMQ offset preparation from legacy property-order handling
Consider extracting the WAIT-order operation into a clearly named helper and invoking it immediately before |
ba7eacd to
b28b13f
Compare
|
Thanks @fuyou001 — addressed in
Validation on JDK 8: |
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Summary
LGTM. Changes look good.
Automated review by github-manager-bot
| return queueNames; | ||
| } | ||
|
|
||
| static String[] parseLmqQueueNames(final MessageExtBrokerInner msg) { |
There was a problem hiding this comment.
Suggestion (non-blocking): parseLmqQueueNames is only used within LmqDispatch. Consider making it private to minimize its visibility and avoid exposing an unnecessary package-private API.
There was a problem hiding this comment.
Thanks — addressed in 245264ce6 by making parseLmqQueueNames() private; both call sites are internal to LmqDispatch.
Validation on JDK 8: LmqDispatchTest 5/5; full affected reactor 733 tests with 0 failures/errors (4 existing skips); Checkstyle, SpotBugs, store-scoped RAT, and git diff --check passed.
Signed-off-by: Rui <1685901819@qq.com>
b28b13f to
245264c
Compare
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Summary
Excellent performance optimization for the LMQ append path. The PR achieves ~50% allocation reduction (672-1504 B/op saved) with measurable throughput gains (+83-106%) while maintaining full backward compatibility.
Key strengths:
- Clean refactoring:
StringBuilder.append(long)replaces boxedLong[]+StringUtils.join, eliminating autoboxing overhead on the hot path - Smart reuse: queue names parsed once and passed to
updateLmqOffsets, avoiding redundantsplit()calls - Correct END_OF_FILE retry handling: offsets only increase after successful physical append, never twice
- Legacy compatibility preserved:
reinsertWaitStorePropertyForLegacySerializationclearly documents the remove/reinsert mutation - Comprehensive test coverage (263 lines): mixed queues, legacy property order, error mapping, retry safety
- Solid JMH methodology: 5 independent alternating pairs,
-prof gc, paired throughput analysis
The code is well-structured, the performance gains are real and well-measured, and backward compatibility is carefully maintained. LGTM.
Automated review by github-manager-bot
Which Issue(s) This PR Fixes
Brief Description
This PR reduces temporary allocation in the LMQ append path without changing public APIs or the persisted message format.
PROPERTY_INNER_MULTI_QUEUE_OFFSETwithStringBuilder.append(long)instead of a boxedLong[]plusStringUtils.join.WAIT_STORE_MSG_OKproperty order and exact encoded bytes.WAIT_STORE_MSG_OKremove/reinsert compatibility step in a named helper immediately before final property serialization.LmqDispatch.END_OF_FILEretry safe: offsets are increased only after a successful physical append and never twice.LmqDispatchmethods and existing RocksDB/generic consume-queue exception mapping.Compatibility
There are no public API, configuration, protocol, or persistence-format changes. Mixed LMQ/non-LMQ queues, disabled LMQ,
WAIT_STORE_MSG_OK, and encoded retry behavior remain compatible.Performance
Paired JMH results on
developat2daf0e2ca91a1592d18235d43e5d709d1c35d15f:Environment: OpenJDK 8u492, JMH 1.36, Linux x86_64, Intel Xeon Gold 6133. Five independent alternating baseline-to-patched pairs were rerun for reviewer follow-up commit
b28b13f7b. Each variant used one fork per pair, five 1-second warmup iterations, ten 1-second measurement iterations, throughput mode, and-prof gc. The patched harness includes the extracted WAIT compatibility helper immediately before final property serialization. Allocation decreased in 5/5 pairs for both queue counts; the minimum reduction was 672 B/op. Throughput improved in every pair, with a minimum paired gain of 79.374%. The subsequent245264ce6review update only narrows the internal parser's access modifier and does not change the benchmarked operations.How Did You Test This Change?
All Maven gates used JDK 8.
b28b13f7b:LmqDispatchTestpassed in 20 independent Maven/Surefire processes, 100/100 tests, 0 failures/errors/skips.b28b13f7b:mvn -DskipITs -pl store -am testpassed with common 241/241, remoting 174/174, and store 318/318 tests (4 existing skips), 0 failures/errors.245264ce6:LmqDispatchTestpassed 5/5 and the full affected reactor passed common 241/241, remoting 174/174, and store 318/318 tests (4 existing skips), with 0 failures/errors; Checkstyle, SpotBugs, store-scoped RAT, andgit diff --checkalso passed.mvn -DskipITs -pl '!namesrv' package: all 18 selected reactor modules SUCCESS in 42:07, including store (318 tests), broker, controller (72 tests), proxy (303 tests, 3 existing skips), and container.mvn -DskipITs -pl namesrv packagepassed 116/116 tests. The patched tree also passed namesrv package with tests skipped, Checkstyle 0, and SpotBugs 0. This PR only changes store, which is outside the namesrv dependency graph.BugInstance=0,Error=0.mvn -DskipTests apache-rat:check: all 19 reactor modules SUCCESS, 0 unapproved/unknown files; the reviewer follow-up also passed a fresh store-scoped RAT check with 0 unapproved/unknown files.git diff --check: passed.Regression coverage includes mixed queue names, disabled LMQ, exact legacy property bytes, successful append,
END_OF_FILEretry, exactly-once offset increments, RocksDB failure mapping, and generic consume-queue failure mapping.