encoding/proto: enable use cached size option#8569
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #8569 +/- ##
==========================================
- Coverage 81.64% 80.56% -1.09%
==========================================
Files 413 413
Lines 40621 40843 +222
==========================================
- Hits 33167 32906 -261
- Misses 5991 6260 +269
- Partials 1463 1677 +214
🚀 New features to boost your workflow:
|
|
The code seems okay but I am not sure if we want to do that especially since the description for On the other side it also says that it asserts that nothing has changed in between : So I would like other maintainers opinion on this. cc @dfawley @easwars @arjan-bal |
| @@ -48,15 +49,15 @@ func (c *codecV2) Marshal(v any) (data mem.BufferSlice, err error) { | |||
|
|
|||
| size := proto.Size(vv) | |||
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I think if we don't call proto.Size(vv) here, we could end up using a stale cached size.
There was a problem hiding this comment.
Would this be cleaner? rs-unity@188bece rs-unity@ec0c47e
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I've updated the comment: rs-unity@ec0c47e
…ying the use of UseCachedSize
easwars
left a comment
There was a problem hiding this comment.
Would you also be able to run the benchmarks here: https://github.com/grpc/grpc-go/tree/master/benchmark and report the results? Thanks.
| @@ -48,15 +49,15 @@ func (c *codecV2) Marshal(v any) (data mem.BufferSlice, err error) { | |||
|
|
|||
| size := proto.Size(vv) | |||
There was a problem hiding this comment.
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.
Here are the commands to run them: # get the baseline performance
git checkout master
RUN_NAME="unary-before"
go run benchmark/benchmain/main.go -benchtime=60s -workloads=unary \
-compression=off -maxConcurrentCalls=120 -trace=off \
-reqSizeBytes=1024 -respSizeBytes=1024 -networkMode=Local -resultFile="${RUN_NAME}" -recvBufferPool=simple
# get the performance with the improvements
git checkout use-cached-size
RUN_NAME="unary-after"
go run benchmark/benchmain/main.go -benchtime=60s -workloads=unary \
-compression=off -maxConcurrentCalls=120 -trace=off \
-reqSizeBytes=1024 -respSizeBytes=1024 -networkMode=Local -resultFile="${RUN_NAME}" -recvBufferPool=simple
# generate a report
go run benchmark/benchresult/main.go unary-before unary-afterI suspect the benchmarks may not show a significant improvement since they use a very simple proto with a shallow schema. |
|
In our workload, the improvements had a big impact, we were able to cut node count by 10–20%. That said, our use case is pretty unique since we’re serving over 200M payloads per second. Here's the results of the benchmarks based on @arjan-bal command: Here's the results of the benchmarks based on a test closer to our workload: |
8a1ee43 to
ec0c47e
Compare
arjan-bal
left a comment
There was a problem hiding this comment.
LGTM, thanks for the improvement! We'll wait for a second approval before merging.
Enable UseCachedSize in proto marshal to eliminate redundant size computation
Fixes: #8570
The proto message size was previously being computed twice: once before marshalling and again during the marshalling call itself. In high-throughput workloads, this duplicated computation is expensive.
By enabling
UseCachedSizeonMarshalOptions, we reuse the size calculated immediately before marshalling, avoiding the second call toproto.Size.In our application, the redundant size call accounted for ~12% of total CPU time. With this change, we eliminate that overhead while preserving correctness.
RELEASE NOTES: