Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
spring-projects-issues opened this issue Sep 3, 2020 · 2 comments

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Sep 3, 2020

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)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Sep 3, 2020

Thomas Heigl commented

Created #559

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Sep 17, 2020

Thomas Heigl commented

DefaultMessage.getChannel is called 3 times for every message in Spring Session. DefaultMessage.getBody once. Only one call to getChannel really needs the underlying byte array. Allocation from the other 3 calls can be avoided with my PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.