Skip to content

Reduce memory allocation when retrieving message content [DATAREDIS-1212] #1781

@spring-projects-issues

Description

@spring-projects-issues

Thomas Heigl opened DATAREDIS-1212 and commented

DefaultMessage.getChannel is the method with the highest allocation rate in my application:

!image-2020-09-03-09-41-19-110.png|width=765,height=142!

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


Attachments:

Referenced from: pull request #559

Backported to: 2.3.5 (Neumann SR5), 2.2.11 (Moore SR11)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions