wang-jiahua opened a new issue, #10976:
URL: https://github.com/apache/rocketmq/issues/10976
### Before Creating the Enhancement Request
- [x] I have confirmed that this should be classified as an enhancement
rather than a bug/feature.
### Summary
Remove two per-message allocation sources on the proxy gRPC path: the
`MessageDigest.getInstance("MD5")` lookup for every delivered message, and the
`getBytes(UTF_8)` calls used only for length validation on every received
message.
### Motivation
1. `GrpcConverter#buildSystemProperties` computes the body digest for every
message delivered to a gRPC consumer, and `BinaryUtil.calculateMd5` performs a
`MessageDigest.getInstance("MD5")` provider lookup plus a fresh digest instance
on every call.
2. `SendMessageActivity#buildMessageProperty` (and `validateMessageGroup`)
call `str.getBytes(StandardCharsets.UTF_8)` on every user-property key/value,
the tag, each message key, and the message group — only to read `.length` for
size validation; the byte arrays are discarded immediately. That is 2N+
transient arrays per received message (N = user property count).
### Solution
- `BinaryUtil`: keep one `MessageDigest` per thread in a `ThreadLocal`
(`MessageDigest` is not thread safe) and `reset()` before each use.
- `SendMessageActivity`: add a `utf8Length(String)` helper that computes the
UTF-8 encoded length without materializing the array, matching
`String.getBytes(UTF_8).length` exactly, including the single-byte replacement
for unpaired surrogates; replace the five call sites.
### Verification
- `BinaryUtilTest` (new): digest matches a fresh `MessageDigest` and stays
stable across interleaved calls on the reused per-thread instance.
`SendMessageActivityTest#testUtf8Length`: sample-by-sample equality with
`getBytes(UTF_8).length` covering ASCII, CJK, supplementary (emoji), and
unpaired surrogates; full class 12/12.
- Dedicated gRPC A/B on a 4-node cluster: proxy (cluster mode) plus a
loopback load tool built on `rocketmq-client-java` 5.0.7 (producer 8 threads
with multi-byte user properties exercising `utf8Length`, SimpleConsumer 4
threads exercising the digest path), swapping the proxy's
`rocketmq-common`/`rocketmq-proxy` jars per arm; 3 interleaved trials plus 1
reversed-order control: ~9.4k send TPS / ~5.1k consume TPS, zero failures in
all 8 arms; proxy young GC showed a pure positional artifact (first arm of each
pair always 9, second always 10, independent of the jar — confirmed by the
reversed-order control), i.e. parity after correction. No regression; the
allocation saving itself is below GC-count resolution, so this is a
cleanup-level optimization on the proxy hot path.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]