[Python-checkins] bpo-35380: Enable TCP_NODELAY for proactor event loop (#10867)
Andrew Svetlov
webhook-mailer at python.org
Mon Dec 3 14:08:16 EST 2018
https://github.com/python/cpython/commit/3bc0ebab17bf5a2c29d2214743c82034f82e6573
commit: 3bc0ebab17bf5a2c29d2214743c82034f82e6573
branch: master
author: Andrew Svetlov <andrew.svetlov at gmail.com>
committer: GitHub <noreply at github.com>
date: 2018-12-03T21:08:13+02:00
summary:
bpo-35380: Enable TCP_NODELAY for proactor event loop (#10867)
files:
A Misc/NEWS.d/next/Library/2018-12-03-14-41-11.bpo-35380.SdRF9l.rst
M Lib/asyncio/base_events.py
M Lib/asyncio/proactor_events.py
M Lib/asyncio/selector_events.py
M Lib/test/test_asyncio/test_base_events.py
M Lib/test/test_asyncio/test_selector_events.py
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index f5ab6e7b2d21..60a189bdfb7e 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -168,6 +168,17 @@ def _run_until_complete_cb(fut):
futures._get_loop(fut).stop()
+if hasattr(socket, 'TCP_NODELAY'):
+ def _set_nodelay(sock):
+ if (sock.family in {socket.AF_INET, socket.AF_INET6} and
+ sock.type == socket.SOCK_STREAM and
+ sock.proto == socket.IPPROTO_TCP):
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+else:
+ def _set_nodelay(sock):
+ pass
+
+
class _SendfileFallbackProtocol(protocols.Protocol):
def __init__(self, transp):
if not isinstance(transp, transports._FlowControlMixin):
diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py
index ad23918802fa..69d96a81035e 100644
--- a/Lib/asyncio/proactor_events.py
+++ b/Lib/asyncio/proactor_events.py
@@ -13,7 +13,6 @@
from . import base_events
from . import constants
-from . import events
from . import futures
from . import exceptions
from . import protocols
@@ -445,6 +444,11 @@ class _ProactorSocketTransport(_ProactorReadPipeTransport,
_sendfile_compatible = constants._SendfileMode.TRY_NATIVE
+ 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
diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py
index ad093001dd9a..112c4b15b8d8 100644
--- a/Lib/asyncio/selector_events.py
+++ b/Lib/asyncio/selector_events.py
@@ -39,17 +39,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
- sock.type == socket.SOCK_STREAM 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.
@@ -742,7 +731,7 @@ def __init__(self, loop, sock, protocol, waiter=None,
# 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 6d544d1eda86..53854758a27d 100644
--- a/Lib/test/test_asyncio/test_base_events.py
+++ b/Lib/test/test_asyncio/test_base_events.py
@@ -2,7 +2,6 @@
import concurrent.futures
import errno
-import logging
import math
import os
import socket
@@ -15,7 +14,6 @@
import asyncio
from asyncio import base_events
from asyncio import constants
-from asyncio import events
from test.test_asyncio import utils as test_utils
from test import support
from test.support.script_helper import assert_python_ok
@@ -288,7 +286,7 @@ def cb():
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):
@@ -2075,5 +2073,31 @@ def test_negative_offset(self):
self.run_loop(self.loop.sock_sendfile(sock, self.file, -1))
+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 b99e8e696070..d0d171a9853a 100644
--- a/Lib/test/test_asyncio/test_selector_events.py
+++ b/Lib/test/test_asyncio/test_selector_events.py
@@ -14,7 +14,6 @@
from asyncio.selector_events import _SelectorTransport
from asyncio.selector_events import _SelectorSocketTransport
from asyncio.selector_events import _SelectorDatagramTransport
-from asyncio.selector_events import _set_nodelay
from test.test_asyncio import utils as test_utils
@@ -1344,30 +1343,5 @@ def test_fatal_error_connected(self, m_exc):
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.
More information about the Python-checkins
mailing list