Skip to content

Add setReadbufferSize API to CronetChannelBuilder #12199

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

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

Conversation

aymanm-google
Copy link

By default, CronetClientStreams would use a 4KB buffer to read data from Cronet. This can be inefficient especially if the amount of data being read is huge (~MBs) as each read callback operation incur overhead from Cronet itself (e.g. Context switch, JNI calls). The alternative would be to immediately bump the default to a bigger number but that would incur an increase in memory usage.

If the API is not called then the default of 4KB is used.

By default, CronetClientStreams would use a 4KB buffer to read data
from Cronet. This can be inefficient especially if the amount of data
being read is huge (~MBs) as each read callback operation incur overhead
from Cronet itself (e.g. Context switch, JNI calls). The alternative
would be to immediately bump the default to a bigger number but that
would incur an increase in memory usage.

If the API is not called then the default of 4KB is used.
Copy link

linux-foundation-easycla bot commented Jul 2, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@ejona86
Copy link
Member

ejona86 commented Jul 24, 2025

I think this is a bit more fundamental and we need to think about it some. I agree there's a problem here to be solved, but I'm not all that confident that setting a read buffer size is what we want. In some ways I wouldn't mind adding this, but we would want to be able to remove it in the future.

I'm assuming the latency here is between the application and network thread. There had been some work on MigratingDeframer. I wonder if it helps this problem. (If you revert #7198 you might be able to see if the performance improves.)

@aymanm-google
Copy link
Author

So I understand that adding a new API is a little bit difficult here. However, this API is purely for performance reasons, which means that it can be deprecated at any time and it would not affect the correctness. If we conclude that the difference in performance was not that reasonable then we can just put a @deprecated above it and say that the default is still 4KB?

I'm assuming the latency here is between the application and network thread. There had been some work on MigratingDeframer. I wonder if it helps this problem. (If you revert #7198 you might be able to see if the performance improves.)

I don't understand how this is related? The current performance overhead is between the application and Cronet's network thread which gRPC does not have control over.

@ejona86
Copy link
Member

ejona86 commented Jul 24, 2025

The current performance overhead is between the application and Cronet's network thread which gRPC does not have control over.

I wasn't convinced that was the full problem. I see now that gRPC is starting the next read() directly from the onReadCompleted() callback.

gRPC does know how many bytes are remaining for the current message, but we avoid using it to avoid penalizing streaming. So something along the lines of this PR does seem necessary.

Should this setting be per-stream instead of per-channel? That can be communicated via CallOptions, like done with CRONET_ANNOTATIONS_KEY. The caller then uses stub.withOption(THE_KEY, 4096) to configure it on the stub. So they can still use the same setting for multiple RPCs.

@groakley
Copy link
Contributor

Should this setting be per-stream instead of per-channel?

I agree that a per-stream setting would make sense. A single service may have one method that expects particularly large message sizes, but others that have more conventional payload sizes where the extra buffer space would be wasteful.

Configuring this with a CallOption doesn't prevent setting this once for a channel if that's the desired behavior. You could wrap the channel with a ClientInterceptor that sets the option for all methods and avoid setting it on each stub.

My concern with the CallOption approach would be if it prevents the Cronet channel from pooling these buffers across streams. But from what I can tell looking through CronetClientStream, there is no buffer pooling today; each new stream allocates a new buffer anyways.

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.

3 participants