Description
Currently, the crypto/tls package sends all data records using a max payload size of 16 KB, which is the maximum allowed by the TLS spec. This is optimal for throughput-sensitive applications, but not for latency-sensitive applications, such as web browsing, because the entire 16KB record must be downloaded and decrypted before any of the plaintext can be processed by the application layer. On slow 2G connections this can easily add a 500-1000ms latency to web page load time, since the browser cannot start fetching subresources until that first 16KB record has been fully decrypted.
A simple heuristic that works well in practice is to use small records for the first ~1MB of data, then switch to 16KB records for subsequent data, then switch back to smaller records after the connection goes idle. Ideally, the smaller records should fit exactly within one TCP packet.
For more background reading, see:
https://www.igvita.com/2013/10/24/optimizing-tls-record-size-and-buffering-latency/
http://chimera.labs.oreilly.com/books/1230000000545/ch04.html#TLS_RECORD_SIZE
https://issues.apache.org/jira/browse/TS-2503
I have an implementation sketch here:
https://go-review.googlesource.com/#/c/19591/
I can demonstrate the latency improvement in a simple test environment:
- Go HTTPS server
- Chrome client browser
- Simulated cellular network (bandwidth = ~200kbps)
Without this change, I notice a ~500ms delay between the time that Chrome receives the first byte of the HTTP response and the time Chrome sends the first request for a subresource. With this change, that difference drops to ~10ms.
If the general approach looks good, I can mail the change for review. +@bradfitz and +@agl for TLS expertise.