Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions encoding/proto/proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ package proto
import (
"fmt"

"google.golang.org/grpc/encoding"
"google.golang.org/grpc/mem"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/protoadapt"

"google.golang.org/grpc/encoding"
"google.golang.org/grpc/mem"
)

// Name is the name registered for the proto compressor.
Expand All @@ -48,15 +49,15 @@ func (c *codecV2) Marshal(v any) (data mem.BufferSlice, err error) {

size := proto.Size(vv)
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this seems to rely on a runtime behaviour of calling proto.Size(vv) before using the cached size (please correct me if I'm wrong), we should call this out in a code comment just above this to serve as a warning for future code authors.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think if we don't call proto.Size(vv) here, we could end up using a stale cached size.

Copy link
Contributor Author

@rs-unity rs-unity Sep 11, 2025

Choose a reason for hiding this comment

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

Would this be cleaner? rs-unity@188bece rs-unity@ec0c47e

Copy link
Contributor

Choose a reason for hiding this comment

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

The docstring of UseCachedSize does say the following:

	// UseCachedSize indicates that the result of a previous Size call
	// may be reused.****

And that if that condition is not met, bad things might happen.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just want to flag an edge case that normally shouldn’t happen: if another part of the stack keeps a reference to the proto message and it’s shared across multiple Go routines, one routine might modify the message while another is marshaling it through this codec. In that situation, enabling UseCachedSize becomes risky.

That said, the issue I’m describing would still cause (other) problems even if UseCachedSize isn’t enabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated the comment: rs-unity@ec0c47e

if mem.IsBelowBufferPoolingThreshold(size) {
buf, err := proto.Marshal(vv)
buf, err := proto.MarshalOptions{UseCachedSize: true}.Marshal(vv)
if err != nil {
return nil, err
}
data = append(data, mem.SliceBuffer(buf))
} else {
pool := mem.DefaultBufferPool()
buf := pool.Get(size)
if _, err := (proto.MarshalOptions{}).MarshalAppend((*buf)[:0], vv); err != nil {
if _, err := (proto.MarshalOptions{UseCachedSize: true}).MarshalAppend((*buf)[:0], vv); err != nil {
pool.Put(buf)
return nil, err
}
Expand Down
Loading