- 
                Notifications
    You must be signed in to change notification settings 
- Fork 4.6k
transport: Reduce heap allocations #8668
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
Conversation
| Codecov Report❌ Patch coverage is  
 Additional details and impacted files@@            Coverage Diff             @@
##           master    #8668      +/-   ##
==========================================
+ Coverage   81.97%   83.17%   +1.20%     
==========================================
  Files         417      417              
  Lines       40788    32178    -8610     
==========================================
- Hits        33435    26764    -6671     
+ Misses       5991     4034    -1957     
- Partials     1362     1380      +18     
 🚀 New features to boost your workflow:
 | 
| closeStream: func(err error) { | ||
| s.Close(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.
What heap allocation does this reduce?
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.
The closeStream closure captures a variable, s, from outside its own body.
The Go compiler performs escape analysis to determine if a variable can safely live on the stack or if it must be "escaped" to the heap. A variable on the stack is automatically freed when its parent function returns. The closeStream function might be called long after the function that created it has returned (for example, if it's stored in a struct field that lives on).
If s remained on the stack of the creating function, the closeStream function would be left holding an invalid pointer to garbage memory. To prevent this, the compiler sees that s is captured by a closure that might outlive the current function. It therefore allocates s on the heap instead of the stack. The closure then holds a valid pointer to this heap-allocated s.
Note that even though s already points to data on the heap, the s variable itself (the pointer) also escapes. This is different from simply assigning s to a struct field. In that case, a copy of the pointer s is stored in the field. With a closure, the closure captures a reference to the original s variable, forcing that variable to move to the heap so it can be safely shared.
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.
Cool. That helps. The last paragraph was what I wanted. Because I was thinking the ClientStream should already be on the heap, so what is this change preventing. Thanks.
| closeStream: func(err error) { | ||
| s.Close(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.
Cool. That helps. The last paragraph was what I wanted. Because I was thinking the ClientStream should already be on the heap, so what is this change preventing. Thanks.
Benchmarks
RELEASE NOTES: N/A