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

Commit 32c1bd4

Browse files
committed
Don't use QueueUserWorkItem to trigger write callbacks immediately
- In this case we are off the event loop, so we can invoke the callback directly.
1 parent 769e519 commit 32c1bd4

File tree

1 file changed

+33
-45
lines changed

1 file changed

+33
-45
lines changed

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

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,7 @@ public void Write(ArraySegment<byte> buffer, Action<Exception, object> callback,
4545

4646
KestrelTrace.Log.ConnectionWrite(0, buffer.Count);
4747

48-
var writeOp = new WriteOperation
49-
{
50-
Buffer = buffer
51-
};
52-
53-
var callbackContext = new CallbackContext
54-
{
55-
Callback = callback,
56-
State = state,
57-
BytesToWrite = buffer.Count
58-
};
48+
bool triggerCallbackNow = false;
5949

6050
lock (_lockObj)
6151
{
@@ -64,20 +54,22 @@ public void Write(ArraySegment<byte> buffer, Action<Exception, object> callback,
6454
_nextWriteContext = new WriteContext(this);
6555
}
6656

67-
_nextWriteContext.Operations.Enqueue(writeOp);
57+
_nextWriteContext.Buffers.Enqueue(buffer);
6858
_numBytesBuffered += buffer.Count;
6959

7060
// Complete the write task immediately if all previous write tasks have been completed,
7161
// the buffers haven't grown too large, and the last write to the socket succeeded.
72-
if (_lastWriteError == null &&
73-
_callbacksPending.Count == 0 &&
74-
_numBytesBuffered < _maxBytesBufferedBeforeThrottling)
75-
{
76-
TriggerCallback(callbackContext);
77-
}
78-
else
62+
triggerCallbackNow = _lastWriteError == null &&
63+
_callbacksPending.Count == 0 &&
64+
_numBytesBuffered < _maxBytesBufferedBeforeThrottling;
65+
if (!triggerCallbackNow)
7966
{
80-
_callbacksPending.Enqueue(callbackContext);
67+
_callbacksPending.Enqueue(new CallbackContext
68+
{
69+
Callback = callback,
70+
State = state,
71+
BytesToWrite = buffer.Count
72+
});
8173
}
8274

8375
if (_writesPending < _maxPendingWrites)
@@ -86,6 +78,11 @@ public void Write(ArraySegment<byte> buffer, Action<Exception, object> callback,
8678
_writesPending++;
8779
}
8880
}
81+
82+
if (triggerCallbackNow)
83+
{
84+
callback(null, state);
85+
}
8986
}
9087

9188
private void ScheduleWrite()
@@ -118,19 +115,21 @@ private void WriteAllPending()
118115

119116
try
120117
{
121-
var buffers = new ArraySegment<byte>[writingContext.Operations.Count];
118+
var buffers = new ArraySegment<byte>[writingContext.Buffers.Count];
122119

123120
var i = 0;
124-
foreach (var writeOp in writingContext.Operations)
121+
foreach (var buffer in writingContext.Buffers)
125122
{
126-
buffers[i] = writeOp.Buffer;
127-
i++;
123+
buffers[i++] = buffer;
128124
}
129125

130-
writingContext.WriteReq.Write(_socket, new ArraySegment<ArraySegment<byte>>(buffers), (r, status, error, state) =>
126+
var writeReq = new UvWriteReq();
127+
writeReq.Init(_thread.Loop);
128+
129+
writeReq.Write(_socket, new ArraySegment<ArraySegment<byte>>(buffers), (r, status, error, state) =>
131130
{
132131
var writtenContext = (WriteContext)state;
133-
writtenContext.Self.OnWriteCompleted(writtenContext.Operations, r, status, error);
132+
writtenContext.Self.OnWriteCompleted(writtenContext.Buffers, r, status, error);
134133
}, writingContext);
135134
}
136135
catch
@@ -147,7 +146,7 @@ private void WriteAllPending()
147146
}
148147

149148
// This is called on the libuv event loop
150-
private void OnWriteCompleted(Queue<WriteOperation> completedWrites, UvWriteReq req, int status, Exception error)
149+
private void OnWriteCompleted(Queue<ArraySegment<byte>> writtenBuffers, UvWriteReq req, int status, Exception error)
151150
{
152151
lock (_lockObj)
153152
{
@@ -162,16 +161,16 @@ private void OnWriteCompleted(Queue<WriteOperation> completedWrites, UvWriteReq
162161
_writesPending--;
163162
}
164163

165-
foreach (var writeOp in completedWrites)
164+
foreach (var writeBuffer in writtenBuffers)
166165
{
167-
_numBytesBuffered -= writeOp.Buffer.Count;
166+
_numBytesBuffered -= writeBuffer.Count;
168167
}
169168

170169
var bytesLeftToBuffer = _maxBytesBufferedBeforeThrottling - _numBytesBuffered;
171-
while (_callbacksPending.Count > 0 && _callbacksPending.Peek().BytesToWrite < bytesLeftToBuffer)
170+
while (_callbacksPending.Count > 0 &&
171+
_callbacksPending.Peek().BytesToWrite < bytesLeftToBuffer)
172172
{
173-
var context = _callbacksPending.Dequeue();
174-
TriggerCallback(context);
173+
TriggerCallback(_callbacksPending.Dequeue());
175174
}
176175
}
177176

@@ -196,27 +195,16 @@ private class CallbackContext
196195
public int BytesToWrite;
197196
}
198197

199-
private class WriteOperation
200-
{
201-
public ArraySegment<byte> Buffer;
202-
}
203-
204198
private class WriteContext
205199
{
206200
public WriteContext(SocketOutput self)
207201
{
208202
Self = self;
209-
210-
WriteReq = new UvWriteReq();
211-
WriteReq.Init(self._thread.Loop);
212-
213-
Operations = new Queue<WriteOperation>();
203+
Buffers = new Queue<ArraySegment<byte>>();
214204
}
215205

216206
public SocketOutput Self;
217-
218-
public UvWriteReq WriteReq;
219-
public Queue<WriteOperation> Operations;
207+
public Queue<ArraySegment<byte>> Buffers;
220208
}
221209
}
222210
}

0 commit comments

Comments
 (0)