Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Commit 36b71f8

Browse files
committed
Initalize SocketOutput Queues, Reuse WriteContexts
1 parent dca9d60 commit 36b71f8

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public class SocketOutput : ISocketOutput
1515
{
1616
private const int _maxPendingWrites = 3;
1717
private const int _maxBytesPreCompleted = 65536;
18+
private const int _maxPooledWriteContexts = 16;
19+
private const int _maxPooledBufferQueues = 16;
1820

1921
private readonly KestrelThread _thread;
2022
private readonly UvStreamHandle _socket;
@@ -32,14 +34,16 @@ public class SocketOutput : ISocketOutput
3234
private Exception _lastWriteError;
3335
private WriteContext _nextWriteContext;
3436
private readonly Queue<TaskCompletionSource<object>> _tasksPending;
37+
private readonly Queue<WriteContext> _writeContexts;
3538

3639
public SocketOutput(KestrelThread thread, UvStreamHandle socket, long connectionId, IKestrelTrace log)
3740
{
3841
_thread = thread;
3942
_socket = socket;
4043
_connectionId = connectionId;
4144
_log = log;
42-
_tasksPending = new Queue<TaskCompletionSource<object>>();
45+
_tasksPending = new Queue<TaskCompletionSource<object>>(16);
46+
_writeContexts = new Queue<WriteContext>(_maxPooledWriteContexts);
4347
}
4448

4549
public Task WriteAsync(
@@ -63,7 +67,14 @@ public Task WriteAsync(
6367
{
6468
if (_nextWriteContext == null)
6569
{
66-
_nextWriteContext = new WriteContext(this);
70+
if (_writeContexts.Count > 0)
71+
{
72+
_nextWriteContext = _writeContexts.Dequeue();
73+
}
74+
else
75+
{
76+
_nextWriteContext = new WriteContext(this);
77+
}
6778
}
6879

6980
if (buffer.Array != null)
@@ -172,13 +183,13 @@ private void WriteAllPending()
172183
}
173184

174185
// This is called on the libuv event loop
175-
private void OnWriteCompleted(Queue<ArraySegment<byte>> writtenBuffers, int status, Exception error)
186+
private void OnWriteCompleted(WriteContext write)
176187
{
177-
_log.ConnectionWriteCallback(_connectionId, status);
188+
var status = write.WriteStatus;
178189

179190
lock (_lockObj)
180191
{
181-
_lastWriteError = error;
192+
_lastWriteError = write.WriteError;
182193

183194
if (_nextWriteContext != null)
184195
{
@@ -189,7 +200,7 @@ private void OnWriteCompleted(Queue<ArraySegment<byte>> writtenBuffers, int stat
189200
_writesPending--;
190201
}
191202

192-
foreach (var writeBuffer in writtenBuffers)
203+
foreach (var writeBuffer in write.Buffers)
193204
{
194205
// _numBytesPreCompleted can temporarily go negative in the event there are
195206
// completed writes that we haven't triggered callbacks for yet.
@@ -208,24 +219,34 @@ private void OnWriteCompleted(Queue<ArraySegment<byte>> writtenBuffers, int stat
208219
_numBytesPreCompleted += bytesToWrite;
209220
bytesLeftToBuffer -= bytesToWrite;
210221

211-
if (error == null)
222+
if (write.WriteError == null)
212223
{
213224
ThreadPool.QueueUserWorkItem(
214225
(o) => ((TaskCompletionSource<object>)o).SetResult(null),
215226
tcs);
216227
}
217228
else
218229
{
230+
var error = write.WriteError;
219231
// error is closure captured
220232
ThreadPool.QueueUserWorkItem(
221233
(o) => ((TaskCompletionSource<object>)o).SetException(error),
222234
tcs);
223235
}
224236
}
225237

238+
if (_writeContexts.Count < _maxPooledWriteContexts
239+
&& write.Buffers.Count <= _maxPooledBufferQueues)
240+
{
241+
write.Reset();
242+
_writeContexts.Enqueue(write);
243+
}
244+
226245
// Now that the while loop has completed the following invariants should hold true:
227246
Debug.Assert(_numBytesPreCompleted >= 0);
228247
}
248+
249+
_log.ConnectionWriteCallback(_connectionId, status);
229250
}
230251

231252
void ISocketOutput.Write(ArraySegment<byte> buffer, bool immediate)
@@ -263,7 +284,7 @@ private class WriteContext
263284
public WriteContext(SocketOutput self)
264285
{
265286
Self = self;
266-
Buffers = new Queue<ArraySegment<byte>>();
287+
Buffers = new Queue<ArraySegment<byte>>(_maxPooledBufferQueues);
267288
}
268289

269290
/// <summary>
@@ -340,7 +361,17 @@ public void DoDisconnectIfNeeded()
340361

341362
public void Complete()
342363
{
343-
Self.OnWriteCompleted(Buffers, WriteStatus, WriteError);
364+
Self.OnWriteCompleted(this);
365+
}
366+
367+
public void Reset()
368+
{
369+
Buffers.Clear();
370+
SocketDisconnect = false;
371+
SocketShutdownSend = false;
372+
WriteStatus = 0;
373+
WriteError = null;
374+
ShutdownSendStatus = 0;
344375
}
345376
}
346377
}

0 commit comments

Comments
 (0)