New issue
Advanced search Search tips

Issue 828387 link

Starred by 2 users

Issue metadata

Status: Untriaged
Owner: ----
Components:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 3
Type: Feature



Sign in to add a comment

Support QUIC read coalescing if possible in Cronet

Project Member Reported by pauljensen@chromium.org, Apr 3 2018

Issue description

Cronet embedders have noticed when enabling QUIC that Cronet goes from completely filling ByteBuffers passed to Cronet, to just filling one packet's worth (~1400 bytes of payload) in the buffer.

I wonder if we could eek out a bit more performance by checking if more data is available and more completely filling the buffers (i.e don't block waiting for more data, but if the data is ready by the time we intend on issuing a onReadCompleted callback to the app, append it to the buffer).  The possible performance boost would come from decreasing the round-trips through the Cronet API.

I don't know if more data is really available, or if the performance boost would be significant, but I wanted to file this potential optimization idea so I didn't forget.

I also don't know which level of the network stack this kind of optimization should take place in.
 

Comment 1 by rch@chromium.org, Apr 3 2018

If we don't delaying the OnDataRead() callback by one message loop iteration, it would be simple to post a task to deliver the callback while we continue filling the buffer while packets are read synchronously. 

That being said, the async read rate on Android seems depressingly high:

https://uma.googleplex.com/histograms/?endDate=20180401&dayCount=1&histograms=Net.QuicSession.AsyncRead&fixupData=true&showMax=true&filters=platform%2Ceq%2CA%2Cisofficial%2Ceq%2CTrue&implicitFilters=isofficial

Boolean	Count	PDF
False	310,357,194,714	53.41%
True	270,674,382,511	46.59%

This says that only 53% of the time we issue a read it returns synchronously. Of course, that's probably skewed to some extent by the fact that we're not usually doing enormous downloads. So I'm not sure what fraction of the time that there is more data sent by the server, it can be read synchronously.

Presumably, when we're using TCP, the server is roughly sending at the same rate as with UDP. But since we're seeing larger read results in TCP, there must be more buffering going on, and presumably we could emulate this in QUIC somehow.

Oh!

I wonder if this could be related to TLS record sizes! With TLS, you can't access the data in a TLS record until the whole record has arrived (as I understand it). So even if the data can be read out of the kernel and up into the TCPClientSocket,  it'll be buffered in the SSLClientSocket.

This is a bit rambling. Does any of this resonate with you?
All sounds plausible to me.  

I think this has to be done inside the network stack, not in Cronet.  My reasoning:  We don't have a peek API AFAIK.  So say caller passes a big buffer to Cronet to fill.  Cronet calls UrlRequest.Read() and gets back 1400 bytes, but the problem is Cronet can't call UrlRequest.Read() again because that might give back ERR_IO_PENDING and hold onto the buffer for an indeterminate amount of time when we should be passing the buffer back to the app in this async case.

Sign in to add a comment