Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into optimize_write_latency
Browse files Browse the repository at this point in the history
  • Loading branch information
taras committed Aug 29, 2024
2 parents cfa33ab + 3fba9fa commit 96dc94c
Show file tree
Hide file tree
Showing 15 changed files with 76 additions and 50 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ _default: compile


clean:
rm -fr dist/ doc/_build/ *.egg-info uvloop/loop.*.pyd
rm -fr dist/ doc/_build/ *.egg-info uvloop/loop.*.pyd uvloop/loop_d.*.pyd
rm -fr uvloop/*.c uvloop/*.html uvloop/*.so
rm -fr uvloop/handles/*.html uvloop/includes/*.html
find . -name '__pycache__' | xargs rm -rf
Expand Down
10 changes: 6 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@ test = [
# pycodestyle is a dependency of flake8, but it must be frozen because
# their combination breaks too often
# (example breakage: https://gitlab.com/pycqa/flake8/issues/427)
'aiohttp>=3.8.1; python_version < "3.12"',
'aiohttp==3.9.0b0; python_version >= "3.12"',
'aiohttp>=3.10.5',
'flake8~=5.0',
'psutil',
'pycodestyle~=2.9.0',
'pyOpenSSL~=23.0.0',
'mypy>=0.800',
'Cython(>=0.29.36,<0.30.0)',
]
dev = [
'setuptools>=60',
'Cython~=3.0',
]
docs = [
'Sphinx~=4.1.2',
Expand All @@ -55,7 +57,7 @@ docs = [
requires = [
"setuptools>=60",
"wheel",
"Cython(>=0.29.36,<0.30.0)",
"Cython~=3.0",
]
build-backend = "setuptools.build_meta"

Expand Down
6 changes: 4 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from setuptools.command.sdist import sdist


CYTHON_DEPENDENCY = 'Cython(>=0.29.36,<0.30.0)'
CYTHON_DEPENDENCY = 'Cython~=3.0'
MACHINE = platform.machine()
MODULES_CFLAGS = [os.getenv('UVLOOP_OPT_CFLAGS', '-O2')]
_ROOT = pathlib.Path(__file__).parent
Expand Down Expand Up @@ -144,7 +144,9 @@ def finalize_options(self):
self.distribution.ext_modules[:] = cythonize(
self.distribution.ext_modules,
compiler_directives=directives,
annotate=self.cython_annotate)
annotate=self.cython_annotate,
compile_time_env=dict(DEFAULT_FREELIST_SIZE=250),
emit_linenums=self.debug)

super().finalize_options()

Expand Down
21 changes: 12 additions & 9 deletions tests/test_tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1626,17 +1626,22 @@ async def client(addr):
self.fail("unexpected call to connection_made()")

def test_ssl_connect_accepted_socket(self):
if hasattr(ssl, 'PROTOCOL_TLS'):
proto = ssl.PROTOCOL_TLS
if hasattr(ssl, 'PROTOCOL_TLS_SERVER'):
server_proto = ssl.PROTOCOL_TLS_SERVER
client_proto = ssl.PROTOCOL_TLS_CLIENT
else:
proto = ssl.PROTOCOL_SSLv23
server_context = ssl.SSLContext(proto)
if hasattr(ssl, 'PROTOCOL_TLS'):
client_proto = server_proto = ssl.PROTOCOL_TLS
else:
client_proto = server_proto = ssl.PROTOCOL_SSLv23

server_context = ssl.SSLContext(server_proto)
server_context.load_cert_chain(self.ONLYCERT, self.ONLYKEY)
if hasattr(server_context, 'check_hostname'):
server_context.check_hostname = False
server_context.verify_mode = ssl.CERT_NONE

client_context = ssl.SSLContext(proto)
client_context = ssl.SSLContext(client_proto)
if hasattr(server_context, 'check_hostname'):
client_context.check_hostname = False
client_context.verify_mode = ssl.CERT_NONE
Expand Down Expand Up @@ -2229,8 +2234,7 @@ def test_renegotiation(self):
sslctx.use_privatekey_file(self.ONLYKEY)
sslctx.use_certificate_chain_file(self.ONLYCERT)
client_sslctx = self._create_client_ssl_context()
if hasattr(ssl, 'OP_NO_TLSv1_3'):
client_sslctx.options |= ssl.OP_NO_TLSv1_3
client_sslctx.maximum_version = ssl.TLSVersion.TLSv1_2

def server(sock):
conn = openssl_ssl.Connection(sslctx, sock)
Expand Down Expand Up @@ -2588,8 +2592,7 @@ def test_flush_before_shutdown(self):
sslctx_openssl.use_privatekey_file(self.ONLYKEY)
sslctx_openssl.use_certificate_chain_file(self.ONLYCERT)
client_sslctx = self._create_client_ssl_context()
if hasattr(ssl, 'OP_NO_TLSv1_3'):
client_sslctx.options |= ssl.OP_NO_TLSv1_3
client_sslctx.maximum_version = ssl.TLSVersion.TLSv1_2

future = None

Expand Down
4 changes: 3 additions & 1 deletion uvloop/_testbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,9 @@ def find_free_port(start_from=50000):
class SSLTestCase:

def _create_server_ssl_context(self, certfile, keyfile=None):
if hasattr(ssl, 'PROTOCOL_TLS'):
if hasattr(ssl, 'PROTOCOL_TLS_SERVER'):
sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
elif hasattr(ssl, 'PROTOCOL_TLS'):
sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS)
else:
sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Expand Down
2 changes: 1 addition & 1 deletion uvloop/dns.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ cdef class AddrInfo:
uv.uv_freeaddrinfo(self.data) # returns void
self.data = NULL

cdef void set_data(self, system.addrinfo *data):
cdef void set_data(self, system.addrinfo *data) noexcept:
self.data = data

cdef unpack(self):
Expand Down
2 changes: 1 addition & 1 deletion uvloop/handles/handle.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ cdef void __uv_close_handle_cb(uv.uv_handle_t* handle) noexcept with gil:
Py_DECREF(h) # Was INCREFed in UVHandle._close


cdef void __close_all_handles(Loop loop):
cdef void __close_all_handles(Loop loop) noexcept:
uv.uv_walk(loop.uvloop,
__uv_walk_close_all_handles_cb,
<void*>loop) # void
Expand Down
2 changes: 1 addition & 1 deletion uvloop/handles/pipe.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ cdef __pipe_init_uv_handle(UVStream handle, Loop loop):
cdef __pipe_open(UVStream handle, int fd):
cdef int err
err = uv.uv_pipe_open(<uv.uv_pipe_t *>handle._handle,
<uv.uv_file>fd)
<uv.uv_os_fd_t>fd)
if err < 0:
exc = convert_error(err)
raise exc
Expand Down
2 changes: 1 addition & 1 deletion uvloop/handles/poll.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ cdef class UVPoll(UVHandle):
cdef inline _poll_start(self, int flags)
cdef inline _poll_stop(self)

cdef int is_active(self)
cdef int is_active(self) noexcept

cdef is_reading(self)
cdef is_writing(self)
Expand Down
2 changes: 1 addition & 1 deletion uvloop/handles/poll.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ cdef class UVPoll(UVHandle):
handle._init(loop, fd)
return handle

cdef int is_active(self):
cdef int is_active(self) noexcept:
return (self.reading_handle is not None or
self.writing_handle is not None)

Expand Down
6 changes: 5 additions & 1 deletion uvloop/handles/stream.pyx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
DEF __PREALLOCED_BUFS = 4
cdef extern from *:
'''
enum {__PREALLOCED_BUFS = 4};
'''
const bint __PREALLOCED_BUFS


@cython.no_gc_clear
Expand Down
40 changes: 24 additions & 16 deletions uvloop/includes/consts.pxi
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
DEF UV_STREAM_RECV_BUF_SIZE = 256000 # 250kb
cdef enum:
UV_STREAM_RECV_BUF_SIZE = 256000 # 250kb

DEF FLOW_CONTROL_HIGH_WATER = 64 # KiB
DEF FLOW_CONTROL_HIGH_WATER_SSL_READ = 256 # KiB
DEF FLOW_CONTROL_HIGH_WATER_SSL_WRITE = 512 # KiB
FLOW_CONTROL_HIGH_WATER = 64 # KiB
FLOW_CONTROL_HIGH_WATER_SSL_READ = 256 # KiB
FLOW_CONTROL_HIGH_WATER_SSL_WRITE = 512 # KiB

DEF DEFAULT_FREELIST_SIZE = 250
DEF DNS_PYADDR_TO_SOCKADDR_CACHE_SIZE = 2048
DEFAULT_FREELIST_SIZE = 250
DNS_PYADDR_TO_SOCKADDR_CACHE_SIZE = 2048

DEF DEBUG_STACK_DEPTH = 10
DEBUG_STACK_DEPTH = 10


DEF __PROCESS_DEBUG_SLEEP_AFTER_FORK = 1
__PROCESS_DEBUG_SLEEP_AFTER_FORK = 1


DEF LOG_THRESHOLD_FOR_CONNLOST_WRITES = 5
LOG_THRESHOLD_FOR_CONNLOST_WRITES = 5
SSL_READ_MAX_SIZE = 256 * 1024


# Number of seconds to wait for SSL handshake to complete
# The default timeout matches that of Nginx.
DEF SSL_HANDSHAKE_TIMEOUT = 60.0
# Number of seconds to wait for SSL shutdown to complete
# The default timeout mimics lingering_time
DEF SSL_SHUTDOWN_TIMEOUT = 30.0
DEF SSL_READ_MAX_SIZE = 256 * 1024
cdef extern from *:
'''
// Number of seconds to wait for SSL handshake to complete
// The default timeout matches that of Nginx.
#define SSL_HANDSHAKE_TIMEOUT 60.0
// Number of seconds to wait for SSL shutdown to complete
// The default timeout mimics lingering_time
#define SSL_SHUTDOWN_TIMEOUT 30.0
'''

const float SSL_HANDSHAKE_TIMEOUT
const float SSL_SHUTDOWN_TIMEOUT
6 changes: 5 additions & 1 deletion uvloop/includes/fork_handler.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#ifndef UVLOOP_FORK_HANDLER_H_
#define UVLOOP_FORK_HANDLER_H_

volatile uint64_t MAIN_THREAD_ID = 0;
volatile int8_t MAIN_THREAD_ID_SET = 0;

typedef void (*OnForkHandler)();
typedef void (*OnForkHandler)(void);

OnForkHandler __forkHandler = NULL;

Expand Down Expand Up @@ -36,3 +39,4 @@ void setMainThreadID(uint64_t id) {
MAIN_THREAD_ID = id;
MAIN_THREAD_ID_SET = 1;
}
#endif
6 changes: 3 additions & 3 deletions uvloop/includes/uv.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ cdef extern from "uv.h" nogil:
UV_LEAVE_GROUP = 0,
UV_JOIN_GROUP

cpdef enum uv_fs_event:
cdef enum uv_fs_event:
UV_RENAME = 1,
UV_CHANGE = 2

Expand Down Expand Up @@ -282,7 +282,7 @@ cdef extern from "uv.h" nogil:
int uv_loop_close(uv_loop_t* loop)
int uv_loop_alive(uv_loop_t* loop)
int uv_loop_fork(uv_loop_t* loop)
int uv_backend_fd(uv_loop_t* loop)
uv_os_fd_t uv_backend_fd(uv_loop_t* loop)

void uv_update_time(uv_loop_t* loop)
uint64_t uv_now(const uv_loop_t*)
Expand Down Expand Up @@ -378,7 +378,7 @@ cdef extern from "uv.h" nogil:
# Pipes

int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc)
int uv_pipe_open(uv_pipe_t* handle, uv_file file)
int uv_pipe_open(uv_pipe_t* handle, uv_os_fd_t file)
int uv_pipe_bind(uv_pipe_t* handle, const char* name)

void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
Expand Down
15 changes: 8 additions & 7 deletions uvloop/loop.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ from cpython.pycapsule cimport PyCapsule_New, PyCapsule_GetPointer
from . import _noop


include "includes/consts.pxi"
include "includes/stdlib.pxi"

include "errors.pyx"
Expand Down Expand Up @@ -1118,7 +1117,7 @@ cdef class Loop:

cdef _sock_set_reuseport(self, int fd):
cdef:
int err
int err = 0
int reuseport_flag = 1

err = system.setsockopt(
Expand Down Expand Up @@ -1396,8 +1395,7 @@ cdef class Loop:
def set_debug(self, enabled):
self._debug = bool(enabled)
if self.is_running():
self.call_soon_threadsafe(
self._set_coroutine_debug, self, self._debug)
self.call_soon_threadsafe(self._set_coroutine_debug, self._debug)

def is_running(self):
"""Return whether the event loop is currently running."""
Expand Down Expand Up @@ -2749,8 +2747,7 @@ cdef class Loop:
start_new_session=False,
executable=None,
pass_fds=(),
# For tests only! Do not use in your code. Ever.
__uvloop_sleep_after_fork=False):
**kwargs):

# TODO: Implement close_fds (might not be very important in
# Python 3.5, since all FDs aren't inheritable by default.)
Expand All @@ -2770,8 +2767,12 @@ cdef class Loop:
if executable is not None:
args[0] = executable

if __uvloop_sleep_after_fork:
# For tests only! Do not use in your code. Ever.
if kwargs.pop("__uvloop_sleep_after_fork", False):
debug_flags |= __PROCESS_DEBUG_SLEEP_AFTER_FORK
if kwargs:
raise ValueError(
'unexpected kwargs: {}'.format(', '.join(kwargs.keys())))

waiter = self._new_future()
protocol = protocol_factory()
Expand Down

0 comments on commit 96dc94c

Please sign in to comment.