From 3d7fad416cfeda4f73cc1ab9649503a553628d7b Mon Sep 17 00:00:00 2001 From: Paul Lietar Date: Thu, 12 Jan 2023 16:03:32 +0000 Subject: [PATCH] Enable TCP_NODELAY for all synchronous sockets. The widely documented poor interaction between the Nagle algorithm and TCP's delayed ACK feature, when making short successive writes, leads to unnecessary delays (around 50ms on Linux). This happens in httpcore whenever a POST request is made, since the headers and body are sent as two separate calls. The TCP_NODELAY can be enabled to disable Nagle's algorithm, and therefore avoid this delay. The option is already enabled by default for all asyncio and Trio sockets. It is also enabled by CPython's http.client module (which urllib and requests use) and by many high-level HTTP libraries found in other languages, including libcurl, Java's Netty, Rust's reqwest and Go's standard library, to name a few. --- httpcore/backends/sync.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/httpcore/backends/sync.py b/httpcore/backends/sync.py index 04455a10b..a07522cd1 100644 --- a/httpcore/backends/sync.py +++ b/httpcore/backends/sync.py @@ -1,3 +1,4 @@ +import errno import socket import ssl import sys @@ -94,6 +95,14 @@ def connect_tcp( sock = socket.create_connection( address, timeout, source_address=source_address ) + + # Might fail in OSs that don't implement TCP_NODELAY + try: + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + except OSError as e: + if e.errno != errno.ENOPROTOOPT: + raise + return SyncStream(sock) def connect_unix_socket(