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

message: Fix reuse of first segment #556

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

matheusd
Copy link
Contributor

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

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.
@lthibault
Copy link
Collaborator

Test failures seems unrelated. Re-running.

Thank you for submitting this -- I am currently traveling, but will track this as closely as possible.

@matheusd matheusd mentioned this pull request Apr 5, 2024
Copy link
Collaborator

@lthibault lthibault left a 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 {
Copy link
Collaborator

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)
Copy link
Collaborator

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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very helpful, ty!

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

Successfully merging this pull request may close these issues.

None yet

2 participants