-
-
Notifications
You must be signed in to change notification settings - Fork 105
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
message: Fix reuse of first segment #556
base: main
Are you sure you want to change the base?
Conversation
This fixes the Message's Reset() call to allow reuse of the first segment. Prior to this fix, the first segment was discarded after the first Reset call, effectively causing a new segment to be initialized on every Reset call. By reusing the first segment, the number of heap allocations is reduced and therefore performance is increased in use cases where the message object is reused. The fix involved associtating the segment to the message and fixing checks to ensure the data of the segment is re-allocated after the reset. A benchmark is included to show the current performance of this.
Test failures seems unrelated. Re-running. Thank you for submitting this -- I am currently traveling, but will track this as closely as possible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great overall. Small changes requested inline.
@@ -100,6 +101,9 @@ func (m *Message) Release() { | |||
func (m *Message) Reset(arena Arena) (first *Segment, err error) { | |||
m.capTable.Reset() | |||
for k := range m.segs { | |||
if k == 0 && m.segs[k] == &m.firstSeg { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment might be helpful here. Something along the lines of:
// optimization: keep the first segment so that the re-used Message does not have to
// allocate a new one.
@@ -442,7 +447,7 @@ func alloc(s *Segment, sz Size) (*Segment, address, error) { | |||
var err error | |||
s, err = s.msg.allocSegment(sz) | |||
if err != nil { | |||
return nil, 0, err | |||
return nil, 0, fmt.Errorf("allocSegment failed: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We previously purged fmt
form the code-base in order to avoid using reflection, which helps keep binary sizes small. I know it's a bit awkward, but can we replace this with errors.New("allocSegment failed: " + err.Error())
?
@@ -15,6 +15,8 @@ type SegmentID uint32 | |||
// It is part of a Message, which can contain other segments that | |||
// reference each other. | |||
type Segment struct { | |||
// msg associated with this segment. A Message instance m maintains the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very helpful, ty!
This fixes the Message's Reset() call to allow reuse of the first segment.
Prior to this fix, the first segment was discarded after the first Reset call, effectively causing a new segment to be initialized on every Reset call.
By reusing the first segment, the number of heap allocations is reduced and therefore performance is increased in use cases where the message object is reused.
The fix involved associtating the segment to the message and fixing checks to ensure the data of the segment is re-allocated after the reset.
A benchmark is included to show the current performance of this.
Part of #554