From feb40402de27de1d6abe0c5ac3eb6e85dbf17d56 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Fri, 20 Nov 2015 21:27:59 +0000 Subject: [PATCH] merge preamble-output, socket-output --- .../Filter/LibuvStream.cs | 20 ++- .../Filter/StreamSocketOutput.cs | 2 +- .../Http/Frame.cs | 48 ++----- .../Http/FrameHeaders.Generated.cs | 134 +++++++++--------- .../Http/FrameResponseHeaders.cs | 15 +- .../Http/SocketOutput.cs | 12 +- .../Infrastructure/MemoryPoolIterator2.cs | 120 +++++++--------- .../MemoryPoolBlock2Tests.cs | 13 +- .../KnownHeaders.cs | 10 +- 9 files changed, 173 insertions(+), 201 deletions(-) diff --git a/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs b/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs index d61c0eafbc..b4e92b2d76 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs @@ -68,13 +68,29 @@ namespace Microsoft.AspNet.Server.Kestrel.Filter public override void Write(byte[] buffer, int offset, int count) { - var segment = new ArraySegment(buffer, offset, count); + ArraySegment segment; + if (buffer != null) + { + segment = new ArraySegment(buffer, offset, count); + } + else + { + segment = default(ArraySegment); + } _output.Write(segment); } public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token) { - var segment = new ArraySegment(buffer, offset, count); + ArraySegment segment; + if (buffer != null) + { + segment = new ArraySegment(buffer, offset, count); + } + else + { + segment = default(ArraySegment); + } return _output.WriteAsync(segment, cancellationToken: token); } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Filter/StreamSocketOutput.cs b/src/Microsoft.AspNet.Server.Kestrel/Filter/StreamSocketOutput.cs index ba7c57dcf4..e990e34ee8 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Filter/StreamSocketOutput.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Filter/StreamSocketOutput.cs @@ -52,7 +52,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Filter returnBlock.Pool?.Return(returnBlock); } - _outputStream.Write(end.Block.Array, end.Block.Data.Offset, end.Index); + _outputStream.Write(end.Block.Array, end.Block.Data.Offset, end.Index - end.Block.Data.Offset); end.Block.Pool?.Return(end.Block); } } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs index 98652050cd..e86daad1ea 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs @@ -623,8 +623,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http bool appCompleted, bool immediate) { - var memoryBlock = Memory2.Lease(); - var begin = memoryBlock.GetIterator(); + var begin = SocketOutput.ProducingStart(); + var count = 0; var end = begin; if (_keepAlive) { @@ -673,48 +673,20 @@ namespace Microsoft.AspNet.Server.Kestrel.Http _responseHeaders.SetRawConnection("keep-alive", _bytesConnectionKeepAlive); } - end.CopyFrom(_httpVersion == HttpVersionType.Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0); - end.CopyFrom(statusBytes); - _responseHeaders.CopyTo(ref end); - end.CopyFrom(_bytesEndHeaders, 0, _bytesEndHeaders.Length); + count += end.CopyFrom(_httpVersion == HttpVersionType.Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0); + count += end.CopyFrom(statusBytes); + count += _responseHeaders.CopyTo(ref end); + count += end.CopyFrom(_bytesEndHeaders, 0, _bytesEndHeaders.Length); - // TODO: change this to SocketOutput.ProduceStart/ProduceComplete once that change is made - var scan = begin.Block; - while (scan.Next != null) - { - if (scan.Start != scan.End) - { - SocketOutput.WriteAsync( - new ArraySegment(scan.Array, scan.Start, scan.End - scan.Start), - false); - } - var next = scan.Next; - Memory2.Return(scan); - scan = next; - } - var writeTask = SocketOutput.WriteAsync( - new ArraySegment(scan.Array, scan.Start, scan.End - scan.Start), - immediate); + SocketOutput.ProducingComplete(end, count); - if (writeTask.IsCompleted) + if (immediate) { - Memory2.Return(scan); - return TaskUtilities.CompletedTask; + return SocketOutput.WriteAsync(default(ArraySegment), immediate: true); } else { - return writeTask.ContinueWith( - (t, o) => - { - var mb = (MemoryPoolBlock2)o; - mb.Pool.Return(mb); - - if (t.IsFaulted) - { - throw t.Exception; - } - }, - scan); + return TaskUtilities.CompletedTask; } } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/FrameHeaders.Generated.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/FrameHeaders.Generated.cs index 5571e9c56b..bc7f4d0caa 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/FrameHeaders.Generated.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/FrameHeaders.Generated.cs @@ -7821,15 +7821,16 @@ namespace Microsoft.AspNet.Server.Kestrel.Http ((ICollection>)MaybeUnknown)?.CopyTo(array, arrayIndex); } - protected void CopyToFast(ref MemoryPoolIterator2 output) + protected int CopyToFast(ref MemoryPoolIterator2 output) { + var count = 0; if (((_bits & 1L) != 0)) { foreach(var value in _CacheControl) { - output.CopyFrom(_headerBytes, 0, 17); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 0, 17); + count += output.CopyFromAscii(value); } } @@ -7837,12 +7838,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (_rawConnection != null) { - output.CopyFrom(_rawConnection, 0, _rawConnection.Length); + count += output.CopyFrom(_rawConnection, 0, _rawConnection.Length); } else foreach(var value in _Connection) { - output.CopyFrom(_headerBytes, 17, 14); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 17, 14); + count += output.CopyFromAscii(value); } } @@ -7850,12 +7851,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (_rawDate != null) { - output.CopyFrom(_rawDate, 0, _rawDate.Length); + count += output.CopyFrom(_rawDate, 0, _rawDate.Length); } else foreach(var value in _Date) { - output.CopyFrom(_headerBytes, 31, 8); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 31, 8); + count += output.CopyFromAscii(value); } } @@ -7863,8 +7864,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _KeepAlive) { - output.CopyFrom(_headerBytes, 39, 14); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 39, 14); + count += output.CopyFromAscii(value); } } @@ -7872,8 +7873,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Pragma) { - output.CopyFrom(_headerBytes, 53, 10); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 53, 10); + count += output.CopyFromAscii(value); } } @@ -7881,8 +7882,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Trailer) { - output.CopyFrom(_headerBytes, 63, 11); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 63, 11); + count += output.CopyFromAscii(value); } } @@ -7890,12 +7891,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (_rawTransferEncoding != null) { - output.CopyFrom(_rawTransferEncoding, 0, _rawTransferEncoding.Length); + count += output.CopyFrom(_rawTransferEncoding, 0, _rawTransferEncoding.Length); } else foreach(var value in _TransferEncoding) { - output.CopyFrom(_headerBytes, 74, 21); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 74, 21); + count += output.CopyFromAscii(value); } } @@ -7903,8 +7904,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Upgrade) { - output.CopyFrom(_headerBytes, 95, 11); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 95, 11); + count += output.CopyFromAscii(value); } } @@ -7912,8 +7913,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Via) { - output.CopyFrom(_headerBytes, 106, 7); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 106, 7); + count += output.CopyFromAscii(value); } } @@ -7921,8 +7922,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Warning) { - output.CopyFrom(_headerBytes, 113, 11); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 113, 11); + count += output.CopyFromAscii(value); } } @@ -7930,8 +7931,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Allow) { - output.CopyFrom(_headerBytes, 124, 9); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 124, 9); + count += output.CopyFromAscii(value); } } @@ -7939,12 +7940,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (_rawContentLength != null) { - output.CopyFrom(_rawContentLength, 0, _rawContentLength.Length); + count += output.CopyFrom(_rawContentLength, 0, _rawContentLength.Length); } else foreach(var value in _ContentLength) { - output.CopyFrom(_headerBytes, 133, 18); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 133, 18); + count += output.CopyFromAscii(value); } } @@ -7952,8 +7953,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentType) { - output.CopyFrom(_headerBytes, 151, 16); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 151, 16); + count += output.CopyFromAscii(value); } } @@ -7961,8 +7962,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentEncoding) { - output.CopyFrom(_headerBytes, 167, 20); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 167, 20); + count += output.CopyFromAscii(value); } } @@ -7970,8 +7971,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentLanguage) { - output.CopyFrom(_headerBytes, 187, 20); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 187, 20); + count += output.CopyFromAscii(value); } } @@ -7979,8 +7980,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentLocation) { - output.CopyFrom(_headerBytes, 207, 20); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 207, 20); + count += output.CopyFromAscii(value); } } @@ -7988,8 +7989,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentMD5) { - output.CopyFrom(_headerBytes, 227, 15); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 227, 15); + count += output.CopyFromAscii(value); } } @@ -7997,8 +7998,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentRange) { - output.CopyFrom(_headerBytes, 242, 17); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 242, 17); + count += output.CopyFromAscii(value); } } @@ -8006,8 +8007,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Expires) { - output.CopyFrom(_headerBytes, 259, 11); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 259, 11); + count += output.CopyFromAscii(value); } } @@ -8015,8 +8016,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _LastModified) { - output.CopyFrom(_headerBytes, 270, 17); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 270, 17); + count += output.CopyFromAscii(value); } } @@ -8024,8 +8025,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _AcceptRanges) { - output.CopyFrom(_headerBytes, 287, 17); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 287, 17); + count += output.CopyFromAscii(value); } } @@ -8033,8 +8034,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Age) { - output.CopyFrom(_headerBytes, 304, 7); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 304, 7); + count += output.CopyFromAscii(value); } } @@ -8042,8 +8043,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ETag) { - output.CopyFrom(_headerBytes, 311, 8); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 311, 8); + count += output.CopyFromAscii(value); } } @@ -8051,8 +8052,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Location) { - output.CopyFrom(_headerBytes, 319, 12); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 319, 12); + count += output.CopyFromAscii(value); } } @@ -8060,8 +8061,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ProxyAutheticate) { - output.CopyFrom(_headerBytes, 331, 21); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 331, 21); + count += output.CopyFromAscii(value); } } @@ -8069,8 +8070,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _RetryAfter) { - output.CopyFrom(_headerBytes, 352, 15); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 352, 15); + count += output.CopyFromAscii(value); } } @@ -8078,12 +8079,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (_rawServer != null) { - output.CopyFrom(_rawServer, 0, _rawServer.Length); + count += output.CopyFrom(_rawServer, 0, _rawServer.Length); } else foreach(var value in _Server) { - output.CopyFrom(_headerBytes, 367, 10); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 367, 10); + count += output.CopyFromAscii(value); } } @@ -8091,8 +8092,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _SetCookie) { - output.CopyFrom(_headerBytes, 377, 14); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 377, 14); + count += output.CopyFromAscii(value); } } @@ -8100,8 +8101,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Vary) { - output.CopyFrom(_headerBytes, 391, 8); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 391, 8); + count += output.CopyFromAscii(value); } } @@ -8109,11 +8110,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _WWWAuthenticate) { - output.CopyFrom(_headerBytes, 399, 20); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, 399, 20); + count += output.CopyFromAscii(value); } } + return count; } public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value) { diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/FrameResponseHeaders.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/FrameResponseHeaders.cs index 86c2a18554..30c75fe4e2 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/FrameResponseHeaders.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/FrameResponseHeaders.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { public partial class FrameResponseHeaders : FrameHeaders { - private static byte[] _CRLF = new[] { (byte)'\r', (byte)'\n' }; + private static byte[] _CrLf = new[] { (byte)'\r', (byte)'\n' }; private static byte[] _colonSpace = new[] { (byte)':', (byte)' ' }; public bool HasConnection => HeaderConnection.Count != 0; @@ -30,22 +30,23 @@ namespace Microsoft.AspNet.Server.Kestrel.Http return GetEnumerator(); } - public void CopyTo(ref MemoryPoolIterator2 output) + public int CopyTo(ref MemoryPoolIterator2 output) { - CopyToFast(ref output); + var count = CopyToFast(ref output); if (MaybeUnknown != null) { foreach (var kv in MaybeUnknown) { foreach (var value in kv.Value) { - output.CopyFrom(_CRLF, 0, 2); - output.CopyFromAscii(kv.Key); - output.CopyFrom(_colonSpace, 0, 2); - output.CopyFromAscii(value); + count += output.CopyFrom(_CrLf, 0, 2); + count += output.CopyFromAscii(kv.Key); + count += output.CopyFrom(_colonSpace, 0, 2); + count += output.CopyFromAscii(value); } } } + return count; } public partial struct Enumerator : IEnumerator> diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs index 404cb601d5..5f58fac22d 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs @@ -70,11 +70,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Http bool socketShutdownSend = false, bool socketDisconnect = false) { - var tail = ProducingStart(); - tail = tail.CopyFrom(buffer); - // We do our own accounting below - ProducingComplete(tail, count: 0); - + if (buffer.Count > 0) + { + var tail = ProducingStart(); + tail.CopyFrom(buffer); + // We do our own accounting below + ProducingComplete(tail, count: 0); + } TaskCompletionSource tcs = null; lock (_contextLock) diff --git a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs index a3b5e678c5..9af9d4428e 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs @@ -532,7 +532,17 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure } } - public MemoryPoolIterator2 CopyFrom(ArraySegment buffer) + public int CopyFrom(byte[] data) + { + return CopyFrom(new ArraySegment(data)); + } + + public int CopyFrom(byte[] data, int offset, int count) + { + return CopyFrom(new ArraySegment(data, offset, count)); + } + + public int CopyFrom(ArraySegment buffer) { Debug.Assert(_block != null); Debug.Assert(_block.Pool != null); @@ -545,11 +555,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure var bufferIndex = buffer.Offset; var remaining = buffer.Count; + var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex; while (remaining > 0) { - var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex; - if (bytesLeftInBlock == 0) { var nextBlock = pool.Lease(); @@ -560,93 +569,55 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure bytesLeftInBlock = block.Data.Count; } - var bytesToCopy = Math.Min(remaining, bytesLeftInBlock); + var bytesToCopy = remaining < bytesLeftInBlock ? remaining : bytesLeftInBlock; Buffer.BlockCopy(buffer.Array, bufferIndex, block.Array, blockIndex, bytesToCopy); blockIndex += bytesToCopy; bufferIndex += bytesToCopy; remaining -= bytesToCopy; + bytesLeftInBlock -= bytesToCopy; block.End = blockIndex; } - return new MemoryPoolIterator2(block, blockIndex); + _block = block; + _index = blockIndex; + + return buffer.Count; } - public void CopyFrom(byte[] data) - { - CopyFrom(data, 0, data.Length); - } - - public void CopyFrom(byte[] data, int offset, int count) + public unsafe int CopyFromAscii(string data) { + Debug.Assert(_block != null); + Debug.Assert(_block.Pool != null); Debug.Assert(_block.Next == null); Debug.Assert(_block.End == _index); + var pool = _block.Pool; var block = _block; + var blockIndex = _index; + var length = data.Length; - var sourceData = data; - var sourceStart = offset; - var sourceEnd = offset + count; - - var targetData = block.Array; - var targetStart = block.End; - var targetEnd = block.Data.Offset + block.Data.Count; - - while (true) - { - // actual count to copy is remaining data, or unused trailing space in the current block, whichever is smaller - var copyCount = Math.Min(sourceEnd - sourceStart, targetEnd - targetStart); - - Buffer.BlockCopy(sourceData, sourceStart, targetData, targetStart, copyCount); - sourceStart += copyCount; - targetStart += copyCount; - - // if this means all source data has been copied - if (sourceStart == sourceEnd) - { - // increase occupied space in the block, and adjust iterator at start of unused trailing space - block.End = targetStart; - _block = block; - _index = targetStart; - return; - } - - // otherwise another block needs to be allocated to follow this one - block.Next = block.Pool.Lease(); - block = block.Next; - - targetData = block.Array; - targetStart = block.End; - targetEnd = block.Data.Offset + block.Data.Count; - } - } - - public unsafe void CopyFromAscii(string data) - { - Debug.Assert(_block.Next == null); - Debug.Assert(_block.End == _index); - - var block = _block; - - var inputLength = data.Length; - var inputLengthMinusSpan = inputLength - 3; + var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex; + var bytesLeftInBlockMinusSpan = bytesLeftInBlock - 3; fixed (char* pData = data) { var input = pData; - var inputEnd = pData + data.Length; - var blockRemaining = block.Data.Offset + block.Data.Count - block.End; - var blockRemainingMinusSpan = blockRemaining - 3; + var inputEnd = pData + length; + var inputEndMinusSpan = inputEnd - 3; while (input < inputEnd) { - if (blockRemaining == 0) + if (bytesLeftInBlock == 0) { - block.Next = block.Pool.Lease(); - block = block.Next; - blockRemaining = block.Data.Count; - blockRemainingMinusSpan = blockRemaining - 3; + var nextBlock = pool.Lease(); + block.Next = nextBlock; + block = nextBlock; + + blockIndex = block.Data.Offset; + bytesLeftInBlock = block.Data.Count; + bytesLeftInBlockMinusSpan = bytesLeftInBlock - 3; } fixed (byte* pOutput = block.Data.Array) @@ -654,7 +625,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure var output = pOutput + block.End; var copied = 0; - for (; copied < inputLengthMinusSpan && copied < blockRemainingMinusSpan; copied += 4) + for (; input < inputEndMinusSpan && copied < bytesLeftInBlockMinusSpan; copied += 4) { *(output) = (byte)*(input); *(output + 1) = (byte)*(input + 1); @@ -662,19 +633,24 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure *(output + 3) = (byte)*(input + 3); output += 4; input += 4; - blockRemainingMinusSpan -= 4; } - for (; copied < inputLength && copied < blockRemaining; copied++) + for (; input < inputEnd && copied < bytesLeftInBlock; copied++) { *(output++) = (byte)*(input++); - blockRemaining--; } - block.End += copied; - _block = block; - _index = block.End; + + blockIndex += copied; + bytesLeftInBlockMinusSpan -= copied; + bytesLeftInBlock -= copied; } + block.End = blockIndex; } } + + _block = block; + _index = blockIndex; + + return length; } } } diff --git a/test/Microsoft.AspNet.Server.KestrelTests/MemoryPoolBlock2Tests.cs b/test/Microsoft.AspNet.Server.KestrelTests/MemoryPoolBlock2Tests.cs index 5f445ef487..239175e198 100644 --- a/test/Microsoft.AspNet.Server.KestrelTests/MemoryPoolBlock2Tests.cs +++ b/test/Microsoft.AspNet.Server.KestrelTests/MemoryPoolBlock2Tests.cs @@ -159,7 +159,8 @@ namespace Microsoft.AspNet.Server.KestrelTests using (var pool = new MemoryPool2()) { var block1 = pool.Lease(128); - var iterator = block1.GetIterator(); + var start = block1.GetIterator(); + var end = start; var bufferSize = block1.Data.Count * 3; var buffer = new byte[bufferSize]; @@ -170,18 +171,18 @@ namespace Microsoft.AspNet.Server.KestrelTests Assert.Null(block1.Next); - var end = iterator.CopyFrom(new ArraySegment(buffer)); + end.CopyFrom(new ArraySegment(buffer)); Assert.NotNull(block1.Next); for (int i = 0; i < bufferSize; i++) { - Assert.Equal(i % 73, iterator.Take()); + Assert.Equal(i % 73, start.Take()); } - Assert.Equal(-1, iterator.Take()); - Assert.Equal(iterator.Block, end.Block); - Assert.Equal(iterator.Index, end.Index); + Assert.Equal(-1, start.Take()); + Assert.Equal(start.Block, end.Block); + Assert.Equal(start.Index, end.Index); } } diff --git a/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/KnownHeaders.cs b/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/KnownHeaders.cs index ab20b6c2d9..214cf91f6b 100644 --- a/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/KnownHeaders.cs +++ b/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/KnownHeaders.cs @@ -380,22 +380,24 @@ namespace Microsoft.AspNet.Server.Kestrel.Http ((ICollection>)MaybeUnknown)?.CopyTo(array, arrayIndex); }} {(loop.ClassName == "FrameResponseHeaders" ? $@" - protected void CopyToFast(ref MemoryPoolIterator2 output) + protected int CopyToFast(ref MemoryPoolIterator2 output) {{ + var count = 0; {Each(loop.Headers, header => $@" if ({header.TestBit()}) {{ {(header.EnhancedSetter == false ? "" : $@" if (_raw{header.Identifier} != null) {{ - output.CopyFromAscii(_raw{header.Identifier}, 0, _raw{header.Identifier}.Length); + count += output.CopyFrom(_raw{header.Identifier}, 0, _raw{header.Identifier}.Length); }} else ")} foreach(var value in _{header.Identifier}) {{ - output.CopyFromAscii(_headerBytes, {header.BytesOffset}, {header.BytesCount}); - output.CopyFromAscii(value); + count += output.CopyFrom(_headerBytes, {header.BytesOffset}, {header.BytesCount}); + count += output.CopyFromAscii(value); }} }} ")} + return count; }}" : "")} public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value) {{