Details
-
Type:
Improvement
-
Status: Closed
-
Priority:
Major
-
Resolution: Complete
-
Affects Version/s: None
-
Fix Version/s: 2.2.11 (Moore SR11), 2.3.5 (Neumann SR5), 2.4 GA (2020.0.0)
-
Component/s: Core
-
Labels:None
-
Pull Request URL:
-
Sprint:2020.0.0 - Ockham RC2
Description
DefaultMessage.getChannel is the method with the highest allocation rate in my application:
DefaultMessage creates defensive clones of the underlying byte[] for every invocation of getChannel and getBody:
public DefaultMessage(byte[] channel, byte[] body) { this.body = body; this.channel = channel; } public byte[] getChannel() { return channel.clone(); } public byte[] getBody() { return body.clone(); }
I'm assuming this is done to ensure the message is immutable and that makes sense.
However, most invocations of getChannel do not actually need the underlying byte[]. Some are simple null checks and in the case of RedisIndexedSessionRepository, only the String value of the message is needed.
I suggest to add a couple of default methods to Message that directly use the underlying byte[] in the DefaultMessage implementation:
public boolean hasChannel() { return !ObjectUtils.isEmpty(channel); } public boolean hasBody() { return !ObjectUtils.isEmpty(body); } public String getChannelAsString() { return new String(channel); } public String getBodyAsString() { return new String(channel); } public ByteArrayWrapper wrapChannel() { return new ByteArrayWrapper(channel); } public ByteArrayWrapper wrapBody() { return new ByteArrayWrapper(body); }
Nearly all allocations can be prevented by adding these methods while still maintaining immutability and - by using default methods in the Message interface - API compatibility.
I will create a PR for this.