mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
bpo-35380: Enable TCP_NODELAY for proactor event loop (#10867)
This commit is contained in:
parent
3bb150d814
commit
3bc0ebab17
6 changed files with 45 additions and 42 deletions
|
@ -168,6 +168,17 @@ def _run_until_complete_cb(fut):
|
||||||
futures._get_loop(fut).stop()
|
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):
|
class _SendfileFallbackProtocol(protocols.Protocol):
|
||||||
def __init__(self, transp):
|
def __init__(self, transp):
|
||||||
if not isinstance(transp, transports._FlowControlMixin):
|
if not isinstance(transp, transports._FlowControlMixin):
|
||||||
|
|
|
@ -13,7 +13,6 @@ import warnings
|
||||||
|
|
||||||
from . import base_events
|
from . import base_events
|
||||||
from . import constants
|
from . import constants
|
||||||
from . import events
|
|
||||||
from . import futures
|
from . import futures
|
||||||
from . import exceptions
|
from . import exceptions
|
||||||
from . import protocols
|
from . import protocols
|
||||||
|
@ -445,6 +444,11 @@ class _ProactorSocketTransport(_ProactorReadPipeTransport,
|
||||||
|
|
||||||
_sendfile_compatible = constants._SendfileMode.TRY_NATIVE
|
_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):
|
def _set_extra(self, sock):
|
||||||
self._extra['socket'] = sock
|
self._extra['socket'] = sock
|
||||||
|
|
||||||
|
|
|
@ -39,17 +39,6 @@ def _test_selector_event(selector, fd, event):
|
||||||
return bool(key.events & 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):
|
class BaseSelectorEventLoop(base_events.BaseEventLoop):
|
||||||
"""Selector event loop.
|
"""Selector event loop.
|
||||||
|
|
||||||
|
@ -742,7 +731,7 @@ class _SelectorSocketTransport(_SelectorTransport):
|
||||||
# Disable the Nagle algorithm -- small writes will be
|
# Disable the Nagle algorithm -- small writes will be
|
||||||
# sent without waiting for the TCP ACK. This generally
|
# sent without waiting for the TCP ACK. This generally
|
||||||
# decreases the latency (in some cases significantly.)
|
# 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)
|
self._loop.call_soon(self._protocol.connection_made, self)
|
||||||
# only start reading when connection_made() has been called
|
# only start reading when connection_made() has been called
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
import errno
|
import errno
|
||||||
import logging
|
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
|
@ -15,7 +14,6 @@ from unittest import mock
|
||||||
import asyncio
|
import asyncio
|
||||||
from asyncio import base_events
|
from asyncio import base_events
|
||||||
from asyncio import constants
|
from asyncio import constants
|
||||||
from asyncio import events
|
|
||||||
from test.test_asyncio import utils as test_utils
|
from test.test_asyncio import utils as test_utils
|
||||||
from test import support
|
from test import support
|
||||||
from test.support.script_helper import assert_python_ok
|
from test.support.script_helper import assert_python_ok
|
||||||
|
@ -288,7 +286,7 @@ class BaseEventLoopTests(test_utils.TestCase):
|
||||||
loop.set_debug(debug)
|
loop.set_debug(debug)
|
||||||
if debug:
|
if debug:
|
||||||
msg = ("Non-thread-safe operation invoked on an event loop other "
|
msg = ("Non-thread-safe operation invoked on an event loop other "
|
||||||
"than the current one")
|
"than the current one")
|
||||||
with self.assertRaisesRegex(RuntimeError, msg):
|
with self.assertRaisesRegex(RuntimeError, msg):
|
||||||
loop.call_soon(cb)
|
loop.call_soon(cb)
|
||||||
with self.assertRaisesRegex(RuntimeError, msg):
|
with self.assertRaisesRegex(RuntimeError, msg):
|
||||||
|
@ -2075,5 +2073,31 @@ class BaseLoopSockSendfileTests(test_utils.TestCase):
|
||||||
self.run_loop(self.loop.sock_sendfile(sock, self.file, -1))
|
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__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -14,7 +14,6 @@ from asyncio.selector_events import BaseSelectorEventLoop
|
||||||
from asyncio.selector_events import _SelectorTransport
|
from asyncio.selector_events import _SelectorTransport
|
||||||
from asyncio.selector_events import _SelectorSocketTransport
|
from asyncio.selector_events import _SelectorSocketTransport
|
||||||
from asyncio.selector_events import _SelectorDatagramTransport
|
from asyncio.selector_events import _SelectorDatagramTransport
|
||||||
from asyncio.selector_events import _set_nodelay
|
|
||||||
from test.test_asyncio import utils as test_utils
|
from test.test_asyncio import utils as test_utils
|
||||||
|
|
||||||
|
|
||||||
|
@ -1344,30 +1343,5 @@ class SelectorDatagramTransportTests(test_utils.TestCase):
|
||||||
exc_info=(ConnectionRefusedError, MOCK_ANY, MOCK_ANY))
|
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__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Enable TCP_NODELAY on Windows for proactor asyncio event loop.
|
Loading…
Add table
Add a link
Reference in a new issue