Skip to content

Commit bfb8818

Browse files
authored
[3.6] bpo-35380: Enable TCP_NODELAY for proactor event loop (GH-10867). (GH-10874)
* [3.6] bpo-35380: Enable TCP_NODELAY for proactor event loop (GH-10867). (cherry picked from commit 3bc0eba) Co-authored-by: Andrew Svetlov <andrew.svetlov@gmail.com>
1 parent afb07fc commit bfb8818

6 files changed

Lines changed: 44 additions & 40 deletions

File tree

Lib/asyncio/base_events.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,17 @@ def _ensure_resolved(address, *, family=0, type=socket.SOCK_STREAM, proto=0,
182182
proto=proto, flags=flags)
183183

184184

185+
if hasattr(socket, 'TCP_NODELAY'):
186+
def _set_nodelay(sock):
187+
if (sock.family in {socket.AF_INET, socket.AF_INET6} and
188+
_is_stream_socket(sock.type) and
189+
sock.proto == socket.IPPROTO_TCP):
190+
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
191+
else:
192+
def _set_nodelay(sock):
193+
pass
194+
195+
185196
def _run_until_complete_cb(fut):
186197
exc = fut._exception
187198
if (isinstance(exc, BaseException)

Lib/asyncio/proactor_events.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,11 @@ class _ProactorSocketTransport(_ProactorReadPipeTransport,
350350
transports.Transport):
351351
"""Transport for connected sockets."""
352352

353+
def __init__(self, loop, sock, protocol, waiter=None,
354+
extra=None, server=None):
355+
super().__init__(loop, sock, protocol, waiter, extra, server)
356+
base_events._set_nodelay(sock)
357+
353358
def _set_extra(self, sock):
354359
self._extra['socket'] = sock
355360
try:

Lib/asyncio/selector_events.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,6 @@ def _test_selector_event(selector, fd, event):
4040
return bool(key.events & event)
4141

4242

43-
if hasattr(socket, 'TCP_NODELAY'):
44-
def _set_nodelay(sock):
45-
if (sock.family in {socket.AF_INET, socket.AF_INET6} and
46-
base_events._is_stream_socket(sock.type) and
47-
sock.proto == socket.IPPROTO_TCP):
48-
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
49-
else:
50-
def _set_nodelay(sock):
51-
pass
52-
53-
5443
class BaseSelectorEventLoop(base_events.BaseEventLoop):
5544
"""Selector event loop.
5645
@@ -691,7 +680,7 @@ def __init__(self, loop, sock, protocol, waiter=None,
691680
# Disable the Nagle algorithm -- small writes will be
692681
# sent without waiting for the TCP ACK. This generally
693682
# decreases the latency (in some cases significantly.)
694-
_set_nodelay(self._sock)
683+
base_events._set_nodelay(self._sock)
695684

696685
self._loop.call_soon(self._protocol.connection_made, self)
697686
# only start reading when connection_made() has been called

Lib/test/test_asyncio/test_base_events.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
except ImportError:
2828
from asyncio.test_support import assert_python_ok
2929

30-
3130
MOCK_ANY = mock.ANY
3231
PY34 = sys.version_info >= (3, 4)
3332

@@ -288,7 +287,7 @@ def cb():
288287
loop.set_debug(debug)
289288
if debug:
290289
msg = ("Non-thread-safe operation invoked on an event loop other "
291-
"than the current one")
290+
"than the current one")
292291
with self.assertRaisesRegex(RuntimeError, msg):
293292
loop.call_soon(cb)
294293
with self.assertRaisesRegex(RuntimeError, msg):
@@ -1839,5 +1838,30 @@ def runner(loop):
18391838

18401839

18411840

1841+
class TestSelectorUtils(test_utils.TestCase):
1842+
def check_set_nodelay(self, sock):
1843+
opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)
1844+
self.assertFalse(opt)
1845+
1846+
base_events._set_nodelay(sock)
1847+
1848+
opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)
1849+
self.assertTrue(opt)
1850+
1851+
@unittest.skipUnless(hasattr(socket, 'TCP_NODELAY'),
1852+
'need socket.TCP_NODELAY')
1853+
def test_set_nodelay(self):
1854+
sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM,
1855+
proto=socket.IPPROTO_TCP)
1856+
with sock:
1857+
self.check_set_nodelay(sock)
1858+
1859+
sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM,
1860+
proto=socket.IPPROTO_TCP)
1861+
with sock:
1862+
sock.setblocking(False)
1863+
self.check_set_nodelay(sock)
1864+
1865+
18421866
if __name__ == '__main__':
18431867
unittest.main()

Lib/test/test_asyncio/test_selector_events.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from asyncio.selector_events import _SelectorSslTransport
1818
from asyncio.selector_events import _SelectorSocketTransport
1919
from asyncio.selector_events import _SelectorDatagramTransport
20-
from asyncio.selector_events import _set_nodelay
2120

2221

2322
MOCK_ANY = mock.ANY
@@ -1858,30 +1857,5 @@ def test_fatal_error_connected(self, m_exc):
18581857
exc_info=(ConnectionRefusedError, MOCK_ANY, MOCK_ANY))
18591858

18601859

1861-
class TestSelectorUtils(test_utils.TestCase):
1862-
def check_set_nodelay(self, sock):
1863-
opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)
1864-
self.assertFalse(opt)
1865-
1866-
_set_nodelay(sock)
1867-
1868-
opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)
1869-
self.assertTrue(opt)
1870-
1871-
@unittest.skipUnless(hasattr(socket, 'TCP_NODELAY'),
1872-
'need socket.TCP_NODELAY')
1873-
def test_set_nodelay(self):
1874-
sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM,
1875-
proto=socket.IPPROTO_TCP)
1876-
with sock:
1877-
self.check_set_nodelay(sock)
1878-
1879-
sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM,
1880-
proto=socket.IPPROTO_TCP)
1881-
with sock:
1882-
sock.setblocking(False)
1883-
self.check_set_nodelay(sock)
1884-
1885-
18861860
if __name__ == '__main__':
18871861
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enable TCP_NODELAY on Windows for proactor asyncio event loop.

0 commit comments

Comments
 (0)