diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs index a93b0794ee..6f2ea40f27 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs @@ -144,7 +144,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http return handle.Libuv.buf_init( result.Pin() + result.End, - result.BlockEndOffset - result.End); + result.Data.Offset + result.Data.Count - result.End); } private static void ReadCallback(UvStreamHandle handle, int status, object state) diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/SocketInput.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/SocketInput.cs index 37641d7df4..944457af60 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/SocketInput.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/SocketInput.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { const int minimumSize = 2048; - if (_tail != null && minimumSize <= _tail.BlockEndOffset - _tail.End) + if (_tail != null && minimumSize <= _tail.Data.Offset + _tail.Data.Count - _tail.End) { _pinned = _tail; } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs index c1b5bd0e63..cf3f8dc528 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs @@ -400,7 +400,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http return; } - bytes = start.Block.BlockEndOffset - start.Index; + bytes = start.Block.Data.Offset + start.Block.Data.Count - start.Index; buffers = 1; for (var block = start.Block.Next; block != end.Block; block = block.Next) diff --git a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolBlock2.cs b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolBlock2.cs index 920b4e9e49..26156c6cc0 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolBlock2.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolBlock2.cs @@ -52,11 +52,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure /// public byte[] Array => Data.Array; - /// - /// Fixed end offset of the block - /// - public int BlockEndOffset { get; private set; } - /// /// The Start represents the offset into Array where the range of "active" bytes begins. At the point when the block is leased /// the Start is guaranteed to be equal to Array.Offset. The value of Start may be assigned anywhere between Data.Offset and @@ -149,7 +144,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure Slab = slab, Start = data.Offset, End = data.Offset, - BlockEndOffset = data.Offset + data.Count }; } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs index 193df3ea62..37e18389ff 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs @@ -722,52 +722,46 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure CopyFrom(buffer.Array, buffer.Offset, buffer.Count); } - public unsafe void CopyFrom(byte[] data, int offset, int count) + public void CopyFrom(byte[] data, int offset, int count) { Debug.Assert(_block != null); Debug.Assert(_block.Next == null); Debug.Assert(_block.End == _index); - + + var pool = _block.Pool; var block = _block; var blockIndex = _index; - var bytesLeftInBlock = block.BlockEndOffset - blockIndex; - if (bytesLeftInBlock >= count) - { - _index = blockIndex + count; - Buffer.BlockCopy(data, offset, block.Array, blockIndex, count); - block.End = _index; - return; - } + var bufferIndex = offset; + var remaining = count; + var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex; - do + while (remaining > 0) { if (bytesLeftInBlock == 0) { - var nextBlock = block.Pool.Lease(); - blockIndex = nextBlock.Data.Offset; - bytesLeftInBlock = nextBlock.Data.Count; + var nextBlock = pool.Lease(); + block.End = blockIndex; block.Next = nextBlock; block = nextBlock; + + blockIndex = block.Data.Offset; + bytesLeftInBlock = block.Data.Count; } - if (count > bytesLeftInBlock) - { - count -= bytesLeftInBlock; - Buffer.BlockCopy(data, offset, block.Array, blockIndex, bytesLeftInBlock); - offset += bytesLeftInBlock; - block.End = blockIndex + bytesLeftInBlock; - bytesLeftInBlock = 0; - } - else - { - _index = blockIndex + count; - Buffer.BlockCopy(data, offset, block.Array, blockIndex, count); - block.End = _index; - _block = block; - return; - } - } while (true); + var bytesToCopy = remaining < bytesLeftInBlock ? remaining : bytesLeftInBlock; + + Buffer.BlockCopy(data, bufferIndex, block.Array, blockIndex, bytesToCopy); + + blockIndex += bytesToCopy; + bufferIndex += bytesToCopy; + remaining -= bytesToCopy; + bytesLeftInBlock -= bytesToCopy; + } + + block.End = blockIndex; + _block = block; + _index = blockIndex; } public unsafe void CopyFromAscii(string data) @@ -776,123 +770,64 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure Debug.Assert(_block.Next == null); Debug.Assert(_block.End == _index); + var pool = _block.Pool; var block = _block; var blockIndex = _index; - var count = data.Length; + var length = data.Length; - var blockRemaining = block.BlockEndOffset - blockIndex; + var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex; + var bytesLeftInBlockMinusSpan = bytesLeftInBlock - 3; - fixed (char* pInput = data) + fixed (char* pData = data) { - if (blockRemaining >= count) + var input = pData; + var inputEnd = pData + length; + var inputEndMinusSpan = inputEnd - 3; + + while (input < inputEnd) { - _index = blockIndex + count; - - fixed (byte* pOutput = &block.Data.Array[blockIndex]) + if (bytesLeftInBlock == 0) { - CopyFromAscii(pInput, pOutput, count); - } - - block.End = _index; - return; - } - - var input = pInput; - do - { - if (blockRemaining == 0) - { - var nextBlock = block.Pool.Lease(); - blockIndex = nextBlock.Data.Offset; - blockRemaining = nextBlock.Data.Count; + var nextBlock = pool.Lease(); + block.End = blockIndex; block.Next = nextBlock; block = nextBlock; + + blockIndex = block.Data.Offset; + bytesLeftInBlock = block.Data.Count; + bytesLeftInBlockMinusSpan = bytesLeftInBlock - 3; } - if (count > blockRemaining) + fixed (byte* pOutput = &block.Data.Array[block.End]) { - count -= blockRemaining; + //this line is needed to allow output be an register var + var output = pOutput; - fixed (byte* pOutput = &block.Data.Array[blockIndex]) + var copied = 0; + for (; input < inputEndMinusSpan && copied < bytesLeftInBlockMinusSpan; copied += 4) { - CopyFromAscii(input, pOutput, blockRemaining); + *(output) = (byte)*(input); + *(output + 1) = (byte)*(input + 1); + *(output + 2) = (byte)*(input + 2); + *(output + 3) = (byte)*(input + 3); + output += 4; + input += 4; + } + for (; input < inputEnd && copied < bytesLeftInBlock; copied++) + { + *(output++) = (byte)*(input++); } - block.End = blockIndex + blockRemaining; - input += blockRemaining; - blockRemaining = 0; + blockIndex += copied; + bytesLeftInBlockMinusSpan -= copied; + bytesLeftInBlock -= copied; } - else - { - _index = blockIndex + count; + } + } - fixed (byte* pOutput = &block.Data.Array[blockIndex]) - { - CopyFromAscii(input, pOutput, count); - } - - block.End = _index; - _block = block; - return; - } - } while (true); - } - } - - private unsafe static void CopyFromAscii(char* pInput, byte* pOutput, int count) - { - var i = 0; - //these line is needed to allow input/output be an register var - var input = pInput; - var output = pOutput; - - while (i < count - 11) - { - i += 12; - *(output) = (byte)*(input); - *(output + 1) = (byte)*(input + 1); - *(output + 2) = (byte)*(input + 2); - *(output + 3) = (byte)*(input + 3); - *(output + 4) = (byte)*(input + 4); - *(output + 5) = (byte)*(input + 5); - *(output + 6) = (byte)*(input + 6); - *(output + 7) = (byte)*(input + 7); - *(output + 8) = (byte)*(input + 8); - *(output + 9) = (byte)*(input + 9); - *(output + 10) = (byte)*(input + 10); - *(output + 11) = (byte)*(input + 11); - output += 12; - input += 12; - } - if (i < count - 5) - { - i += 6; - *(output) = (byte)*(input); - *(output + 1) = (byte)*(input + 1); - *(output + 2) = (byte)*(input + 2); - *(output + 3) = (byte)*(input + 3); - *(output + 4) = (byte)*(input + 4); - *(output + 5) = (byte)*(input + 5); - output += 6; - input += 6; - } - if (i < count - 3) - { - i += 4; - *(output) = (byte)*(input); - *(output + 1) = (byte)*(input + 1); - *(output + 2) = (byte)*(input + 2); - *(output + 3) = (byte)*(input + 3); - output += 4; - input += 4; - } - while (i < count) - { - i++; - *output = (byte)*input; - output++; - input++; - } + block.End = blockIndex; + _block = block; + _index = blockIndex; } } } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Networking/UvWriteReq.cs b/src/Microsoft.AspNet.Server.Kestrel/Networking/UvWriteReq.cs index af8d334d27..21a1aaf778 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Networking/UvWriteReq.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Networking/UvWriteReq.cs @@ -66,7 +66,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking for (var index = 0; index < nBuffers; index++) { var blockStart = block == start.Block ? start.Index : block.Data.Offset; - var blockEnd = block == end.Block ? end.Index : block.BlockEndOffset; + var blockEnd = block == end.Block ? end.Index : block.Data.Offset + block.Data.Count; // create and pin each segment being written pBuffers[index] = Libuv.buf_init( diff --git a/test/Microsoft.AspNet.Server.KestrelTests/MemoryPoolBlock2Tests.cs b/test/Microsoft.AspNet.Server.KestrelTests/MemoryPoolBlock2Tests.cs index 6edb835841..2cbd077180 100644 --- a/test/Microsoft.AspNet.Server.KestrelTests/MemoryPoolBlock2Tests.cs +++ b/test/Microsoft.AspNet.Server.KestrelTests/MemoryPoolBlock2Tests.cs @@ -248,7 +248,7 @@ namespace Microsoft.AspNet.Server.KestrelTests Assert.Null(block1.Next); - end.CopyFrom(buffer, 0, buffer.Length); + end.CopyFrom(new ArraySegment(buffer)); Assert.NotNull(block1.Next); diff --git a/test/Microsoft.AspNet.Server.KestrelTests/SocketOutputTests.cs b/test/Microsoft.AspNet.Server.KestrelTests/SocketOutputTests.cs index 927194ac5c..bda6bfb651 100644 --- a/test/Microsoft.AspNet.Server.KestrelTests/SocketOutputTests.cs +++ b/test/Microsoft.AspNet.Server.KestrelTests/SocketOutputTests.cs @@ -308,11 +308,11 @@ namespace Microsoft.AspNet.Server.KestrelTests // block 1 var start = socketOutput.ProducingStart(); - start.Block.End = start.Block.BlockEndOffset; + start.Block.End = start.Block.Data.Offset + start.Block.Data.Count; // block 2 var block2 = memory.Lease(); - block2.End = block2.BlockEndOffset; + block2.End = block2.Data.Offset + block2.Data.Count; start.Block.Next = block2; var end = new MemoryPoolIterator2(block2, block2.End);