Before Creating the Enhancement Request
Summary
Enhance the FastCodesHeader interface and RocketMQSerializable utility to reduce allocation and CPU overhead during Remoting header encoding/decoding.
Motivation
In high-throughput scenarios, every RPC request/response goes through the Remoting header encode/decode path. Current implementation has several inefficiencies:
FastCodesHeader.writeIfNotNull always converts numeric values (Long/Integer) to String via value.toString(), creating transient String objects.
RocketMQSerializable.readStr allocates a new String even for single-byte ASCII values.
RocketMQSerializable.mapDeserialize pre-allocates a HashMap with capacity 128, which is oversized for typical headers and wastes memory.
- There is no direct way to write primitive
long/int values to the ByteBuf without first boxing them into Long/Integer.
These small overheads are amplified by millions of RPCs per second in production.
Describe the Solution You'd Like
- Add
writeDecimalLong(ByteBuf, long) and writeDecimalInt(ByteBuf, int) to RocketMQSerializable to write primitive decimal numbers directly to ByteBuf without String allocation.
- Add
writeLong(ByteBuf, String, long) and writeInt(ByteBuf, String, int) helpers to FastCodesHeader.
- Optimize
FastCodesHeader.writeIfNotNull to route Long/Integer values through the new primitive writers.
- Add a
SINGLE_BYTE_STRINGS cache for ASCII single-byte strings in RocketMQSerializable.readStr.
- Reduce the initial capacity of
HashMap in mapDeserialize from 128 to 24.
All changes are additive and keep existing method signatures backward compatible.
Describe Alternatives You've Considered
- Use
String.valueOf + writeStr: still allocates String objects.
- Use
ByteBuf.writeAscii for numbers: Netty's API does not provide direct decimal writing with length prefix required by RocketMQ protocol.
- Keep
HashMap(128) in mapDeserialize: wastes memory for small maps; 24 is sufficient for typical headers.
Additional Context
This is part of a larger effort to reduce Broker allocation rate. Related previous PRs: #10443, #10491, #10485, #10514, #10513, #10517.
Before Creating the Enhancement Request
Summary
Enhance the
FastCodesHeaderinterface andRocketMQSerializableutility to reduce allocation and CPU overhead during Remoting header encoding/decoding.Motivation
In high-throughput scenarios, every RPC request/response goes through the Remoting header encode/decode path. Current implementation has several inefficiencies:
FastCodesHeader.writeIfNotNullalways converts numeric values (Long/Integer) toStringviavalue.toString(), creating transient String objects.RocketMQSerializable.readStrallocates a newStringeven for single-byte ASCII values.RocketMQSerializable.mapDeserializepre-allocates aHashMapwith capacity 128, which is oversized for typical headers and wastes memory.long/intvalues to the ByteBuf without first boxing them intoLong/Integer.These small overheads are amplified by millions of RPCs per second in production.
Describe the Solution You'd Like
writeDecimalLong(ByteBuf, long)andwriteDecimalInt(ByteBuf, int)toRocketMQSerializableto write primitive decimal numbers directly to ByteBuf without String allocation.writeLong(ByteBuf, String, long)andwriteInt(ByteBuf, String, int)helpers toFastCodesHeader.FastCodesHeader.writeIfNotNullto routeLong/Integervalues through the new primitive writers.SINGLE_BYTE_STRINGScache for ASCII single-byte strings inRocketMQSerializable.readStr.HashMapinmapDeserializefrom 128 to 24.All changes are additive and keep existing method signatures backward compatible.
Describe Alternatives You've Considered
String.valueOf+writeStr: still allocates String objects.ByteBuf.writeAsciifor numbers: Netty's API does not provide direct decimal writing with length prefix required by RocketMQ protocol.HashMap(128)inmapDeserialize: wastes memory for small maps; 24 is sufficient for typical headers.Additional Context
This is part of a larger effort to reduce Broker allocation rate. Related previous PRs: #10443, #10491, #10485, #10514, #10513, #10517.