From: Andrew Svetlov Date: Wed, 5 Dec 2018 08:30:06 +0000 (+0200) Subject: [3.6] bpo-35380: Enable TCP_NODELAY for proactor event loop (GH-10867). (GH-10874) X-Git-Tag: v3.6.8rc1~48 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bfb881849f588cd2046776fb431c3045781c8214;p=thirdparty%2FPython%2Fcpython.git [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 3bc0ebab17bf5a2c29d2214743c82034f82e6573) Co-authored-by: Andrew Svetlov --- diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index accd669250cb..48dd1fc54ae4 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -182,6 +182,17 @@ def _ensure_resolved(address, *, family=0, type=socket.SOCK_STREAM, proto=0, proto=proto, flags=flags) +if hasattr(socket, 'TCP_NODELAY'): + def _set_nodelay(sock): + if (sock.family in {socket.AF_INET, socket.AF_INET6} and + _is_stream_socket(sock.type) and + sock.proto == socket.IPPROTO_TCP): + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) +else: + def _set_nodelay(sock): + pass + + def _run_until_complete_cb(fut): exc = fut._exception if (isinstance(exc, BaseException) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 6f621ef0cc4f..079b7a24db42 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -350,6 +350,11 @@ class _ProactorSocketTransport(_ProactorReadPipeTransport, transports.Transport): """Transport for connected sockets.""" + def __init__(self, loop, sock, protocol, waiter=None, + extra=None, server=None): + super().__init__(loop, sock, protocol, waiter, extra, server) + base_events._set_nodelay(sock) + def _set_extra(self, sock): self._extra['socket'] = sock try: diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index bc7c740cc2af..af21d5ee8914 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -40,17 +40,6 @@ def _test_selector_event(selector, fd, event): return bool(key.events & event) -if hasattr(socket, 'TCP_NODELAY'): - def _set_nodelay(sock): - if (sock.family in {socket.AF_INET, socket.AF_INET6} and - base_events._is_stream_socket(sock.type) and - sock.proto == socket.IPPROTO_TCP): - sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) -else: - def _set_nodelay(sock): - pass - - class BaseSelectorEventLoop(base_events.BaseEventLoop): """Selector event loop. @@ -691,7 +680,7 @@ class _SelectorSocketTransport(_SelectorTransport): # Disable the Nagle algorithm -- small writes will be # sent without waiting for the TCP ACK. This generally # decreases the latency (in some cases significantly.) - _set_nodelay(self._sock) + base_events._set_nodelay(self._sock) self._loop.call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 09f71f2f3900..052a559c3cbb 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -27,7 +27,6 @@ except ImportError: except ImportError: from asyncio.test_support import assert_python_ok - MOCK_ANY = mock.ANY PY34 = sys.version_info >= (3, 4) @@ -288,7 +287,7 @@ class BaseEventLoopTests(test_utils.TestCase): loop.set_debug(debug) if debug: msg = ("Non-thread-safe operation invoked on an event loop other " - "than the current one") + "than the current one") with self.assertRaisesRegex(RuntimeError, msg): loop.call_soon(cb) with self.assertRaisesRegex(RuntimeError, msg): @@ -1839,5 +1838,30 @@ class RunningLoopTests(unittest.TestCase): +class TestSelectorUtils(test_utils.TestCase): + def check_set_nodelay(self, sock): + opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) + self.assertFalse(opt) + + base_events._set_nodelay(sock) + + opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) + self.assertTrue(opt) + + @unittest.skipUnless(hasattr(socket, 'TCP_NODELAY'), + 'need socket.TCP_NODELAY') + def test_set_nodelay(self): + sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, + proto=socket.IPPROTO_TCP) + with sock: + self.check_set_nodelay(sock) + + sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, + proto=socket.IPPROTO_TCP) + with sock: + sock.setblocking(False) + self.check_set_nodelay(sock) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 533d2898e7fc..6716e8916cd5 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -17,7 +17,6 @@ from asyncio.selector_events import _SelectorTransport from asyncio.selector_events import _SelectorSslTransport from asyncio.selector_events import _SelectorSocketTransport from asyncio.selector_events import _SelectorDatagramTransport -from asyncio.selector_events import _set_nodelay MOCK_ANY = mock.ANY @@ -1858,30 +1857,5 @@ class SelectorDatagramTransportTests(test_utils.TestCase): exc_info=(ConnectionRefusedError, MOCK_ANY, MOCK_ANY)) -class TestSelectorUtils(test_utils.TestCase): - def check_set_nodelay(self, sock): - opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) - self.assertFalse(opt) - - _set_nodelay(sock) - - opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY) - self.assertTrue(opt) - - @unittest.skipUnless(hasattr(socket, 'TCP_NODELAY'), - 'need socket.TCP_NODELAY') - def test_set_nodelay(self): - sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, - proto=socket.IPPROTO_TCP) - with sock: - self.check_set_nodelay(sock) - - sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, - proto=socket.IPPROTO_TCP) - with sock: - sock.setblocking(False) - self.check_set_nodelay(sock) - - if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-12-03-14-41-11.bpo-35380.SdRF9l.rst b/Misc/NEWS.d/next/Library/2018-12-03-14-41-11.bpo-35380.SdRF9l.rst new file mode 100644 index 000000000000..91f86e604ea8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-12-03-14-41-11.bpo-35380.SdRF9l.rst @@ -0,0 +1 @@ +Enable TCP_NODELAY on Windows for proactor asyncio event loop.