Skip to content

Commit 042c52f

Browse files
committed
optimize tracking of pending outbuf bytes
1 parent cacdafd commit 042c52f

File tree

2 files changed

+23
-19
lines changed

2 files changed

+23
-19
lines changed

Diff for: waitress/channel.py

+11-13
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def __init__(
7070
self.server = server
7171
self.adj = adj
7272
self.outbufs = [OverflowableBuffer(adj.outbuf_overflow)]
73+
self.total_outbufs_len = 0
7374
self.creation_time = self.last_activity = time.time()
7475

7576
# task_lock used to push/pop requests
@@ -83,16 +84,7 @@ def __init__(
8384
self.addr = addr
8485

8586
def any_outbuf_has_data(self):
86-
for outbuf in self.outbufs:
87-
if bool(outbuf):
88-
return True
89-
return False
90-
91-
def total_outbufs_len(self):
92-
# genexpr == more funccalls
93-
# use b.__len__ rather than len(b) FBO of not getting OverflowError
94-
# on Python 2
95-
return sum([b.__len__() for b in self.outbufs])
87+
return self.total_outbufs_len > 0
9688

9789
def writable(self):
9890
# if there's data in the out buffer or we've been instructed to close
@@ -124,7 +116,7 @@ def handle_write(self):
124116
# won't get done.
125117
flush = self._flush_some_if_lockable
126118
self.force_flush = False
127-
elif (self.total_outbufs_len() >= self.adj.send_bytes):
119+
elif (self.total_outbufs_len >= self.adj.send_bytes):
128120
# 1. There's a running task, so we need to try to lock
129121
# the outbuf before sending
130122
# 2. Only try to send if the data in the out buffer is larger
@@ -196,7 +188,9 @@ def received(self, data):
196188
if not self.sent_continue:
197189
# there's no current task, so we don't need to try to
198190
# lock the outbuf to append to it.
199-
self.outbufs[-1].append(b'HTTP/1.1 100 Continue\r\n\r\n')
191+
outbuf_payload = b'HTTP/1.1 100 Continue\r\n\r\n'
192+
self.outbufs[-1].append(outbuf_payload)
193+
self.total_outbufs_len += len(outbuf_payload)
200194
self.sent_continue = True
201195
self._flush_some()
202196
request.completed = False
@@ -261,6 +255,7 @@ def _flush_some(self):
261255
outbuf.skip(num_sent, True)
262256
outbuflen -= num_sent
263257
sent += num_sent
258+
self.total_outbufs_len -= num_sent
264259
else:
265260
dobreak = True
266261
break
@@ -283,6 +278,7 @@ def handle_close(self):
283278
except:
284279
self.logger.exception(
285280
'Unknown exception while trying to close outbuf')
281+
self.total_outbufs_len = 0
286282
self.connected = False
287283
wasyncore.dispatcher.close(self)
288284

@@ -329,11 +325,13 @@ def write_soon(self, data):
329325
self.outbufs.append(nextbuf)
330326
else:
331327
self.outbufs[-1].append(data)
328+
num_bytes = len(data)
329+
self.total_outbufs_len += num_bytes
332330
# XXX We might eventually need to pull the trigger here (to
333331
# instruct select to stop blocking), but it slows things down so
334332
# much that I'll hold off for now; "server push" on otherwise
335333
# unbusy systems may suffer.
336-
return len(data)
334+
return num_bytes
337335
return 0
338336

339337
def service(self):

Diff for: waitress/tests/test_channel.py

+12-6
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,23 @@ def test_ctor(self):
2525
def test_total_outbufs_len_an_outbuf_size_gt_sys_maxint(self):
2626
from waitress.compat import MAXINT
2727
inst, _, map = self._makeOneWithMap()
28-
class DummyHugeBuffer(object):
28+
class DummyBuffer(object):
29+
chunks = []
30+
def append(self, data):
31+
self.chunks.append(data)
32+
class DummyData(object):
2933
def __len__(self):
30-
return MAXINT + 1
31-
inst.outbufs = [DummyHugeBuffer()]
32-
result = inst.total_outbufs_len()
34+
return MAXINT
35+
inst.total_outbufs_len = 1
36+
inst.outbufs = [DummyBuffer()]
37+
inst.write_soon(DummyData())
3338
# we are testing that this method does not raise an OverflowError
3439
# (see https://github.com/Pylons/waitress/issues/47)
35-
self.assertEqual(result, MAXINT+1)
40+
self.assertEqual(inst.total_outbufs_len, MAXINT+1)
3641

3742
def test_writable_something_in_outbuf(self):
3843
inst, sock, map = self._makeOneWithMap()
39-
inst.outbufs[0].append(b'abc')
44+
inst.total_outbufs_len = 3
4045
self.assertTrue(inst.writable())
4146

4247
def test_writable_nothing_in_outbuf(self):
@@ -132,6 +137,7 @@ def test_handle_write_no_requests_outbuf_gt_send_bytes(self):
132137
inst, sock, map = self._makeOneWithMap()
133138
inst.requests = [True]
134139
inst.outbufs = [DummyBuffer(b'abc')]
140+
inst.total_outbufs_len = 3
135141
inst.adj.send_bytes = 2
136142
inst.will_close = False
137143
inst.last_activity = 0

0 commit comments

Comments
 (0)