Skip to content

Commit 9c6ecb6

Browse files
jakirkhamfantix
andauthored
Queue write only after processing all buffers (#445)
Allows `writelines` to leverage vectorized IO within uvloop to send multiple buffers in one `sendmsg` call. * Update license copyright Co-authored-by: Fantix King <[email protected]>
1 parent 089f6cb commit 9c6ecb6

File tree

4 files changed

+21
-11
lines changed

4 files changed

+21
-11
lines changed

Diff for: LICENSE-APACHE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2015-present MagicStack Inc. http://magic.io
1+
Copyright (C) 2016-present the uvloop authors and contributors.
22

33
Apache License
44
Version 2.0, January 2004

Diff for: LICENSE-MIT

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License
22

3-
Copyright (c) 2015-present MagicStack Inc. http://magic.io
3+
Copyright (C) 2016-present the uvloop authors and contributors.
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

Diff for: uvloop/handles/stream.pxd

+9-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ cdef class UVStream(UVBaseTransport):
2121
cdef inline _init(self, Loop loop, object protocol, Server server,
2222
object waiter, object context)
2323

24-
cdef inline _exec_write(self)
2524

2625
cdef inline _shutdown(self)
2726
cdef inline _accept(self, UVStream server)
@@ -31,7 +30,15 @@ cdef class UVStream(UVBaseTransport):
3130
cdef inline __reading_started(self)
3231
cdef inline __reading_stopped(self)
3332

34-
cdef inline _write(self, object data)
33+
# The user API firstly calls _buffer_write() to buffer up user data chunks,
34+
# potentially multiple times in writelines(), and then call _start_write()
35+
# to start writing either immediately or in the next iteration.
36+
cdef inline _buffer_write(self, object data)
37+
cdef inline _start_write(self)
38+
39+
# _exec_write() is the method that does the actual send, and _try_write()
40+
# is a fast-path used in _exec_write() to send a single chunk.
41+
cdef inline _exec_write(self)
3542
cdef inline _try_write(self, object data)
3643

3744
cdef _close(self)

Diff for: uvloop/handles/stream.pyx

+10-7
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ cdef class _StreamWriteContext:
162162
PyObject_GetBuffer(
163163
buf, &p_pybufs[py_bufs_len], PyBUF_SIMPLE)
164164
except Exception:
165-
# This shouldn't ever happen, as `UVStream._write`
165+
# This shouldn't ever happen, as `UVStream._buffer_write`
166166
# casts non-bytes objects to `memoryviews`.
167167
ctx.py_bufs_len = py_bufs_len
168168
ctx.free_bufs()
@@ -407,7 +407,7 @@ cdef class UVStream(UVBaseTransport):
407407

408408
return written
409409

410-
cdef inline _write(self, object data):
410+
cdef inline _buffer_write(self, object data):
411411
cdef int dlen
412412

413413
if not PyBytes_CheckExact(data):
@@ -420,6 +420,7 @@ cdef class UVStream(UVBaseTransport):
420420
self._buffer_size += dlen
421421
self._buffer.append(data)
422422

423+
cdef inline _start_write(self):
423424
if (not self._protocol_paused and
424425
(<uv.uv_stream_t*>self._handle).write_queue_size == 0 and
425426
self._buffer_size > self._high_water):
@@ -443,10 +444,10 @@ cdef class UVStream(UVBaseTransport):
443444
# If not all of the data was sent successfully,
444445
# we might need to pause the protocol.
445446
self._maybe_pause_protocol()
446-
return
447447

448-
self._maybe_pause_protocol()
449-
self._loop._queue_write(self)
448+
elif self._buffer_size > 0:
449+
self._maybe_pause_protocol()
450+
self._loop._queue_write(self)
450451

451452
cdef inline _exec_write(self):
452453
cdef:
@@ -679,7 +680,8 @@ cdef class UVStream(UVBaseTransport):
679680
if self._conn_lost:
680681
self._conn_lost += 1
681682
return
682-
self._write(buf)
683+
self._buffer_write(buf)
684+
self._start_write()
683685

684686
def writelines(self, bufs):
685687
self._ensure_alive()
@@ -690,7 +692,8 @@ cdef class UVStream(UVBaseTransport):
690692
self._conn_lost += 1
691693
return
692694
for buf in bufs:
693-
self._write(buf)
695+
self._buffer_write(buf)
696+
self._start_write()
694697

695698
def write_eof(self):
696699
self._ensure_alive()

0 commit comments

Comments
 (0)