Merge branch 'benaadams/horizontal-initalize' into dev

This commit is contained in:
Cesar Blum Silveira 2015-12-17 14:37:48 -08:00
commit 717b355bfd
4 changed files with 114 additions and 100 deletions

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Numerics;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -39,6 +40,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
private static readonly byte[] _bytesDate = Encoding.ASCII.GetBytes("Date: "); private static readonly byte[] _bytesDate = Encoding.ASCII.GetBytes("Date: ");
private static readonly byte[] _bytesEndHeaders = Encoding.ASCII.GetBytes("\r\n\r\n"); private static readonly byte[] _bytesEndHeaders = Encoding.ASCII.GetBytes("\r\n\r\n");
private static readonly Vector<byte> _vectorCRs = new Vector<byte>((byte)'\r');
private static readonly Vector<byte> _vectorColons = new Vector<byte>((byte)':');
private static readonly Vector<byte> _vectorSpaces = new Vector<byte>((byte)' ');
private static readonly Vector<byte> _vectorQuestionMarks = new Vector<byte>((byte)'?');
private static readonly Vector<byte> _vectorPercentages = new Vector<byte>((byte)'%');
private readonly object _onStartingSync = new Object(); private readonly object _onStartingSync = new Object();
private readonly object _onCompletedSync = new Object(); private readonly object _onCompletedSync = new Object();
protected readonly FrameRequestHeaders _requestHeaders = new FrameRequestHeaders(); protected readonly FrameRequestHeaders _requestHeaders = new FrameRequestHeaders();
@ -704,7 +711,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
try try
{ {
var begin = scan; var begin = scan;
if (scan.Seek(' ') == -1) if (scan.Seek(_vectorSpaces) == -1)
{ {
return false; return false;
} }
@ -719,11 +726,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
begin = scan; begin = scan;
var needDecode = false; var needDecode = false;
var chFound = scan.Seek(' ', '?', '%'); var chFound = scan.Seek(_vectorSpaces, _vectorQuestionMarks, _vectorPercentages);
if (chFound == '%') if (chFound == '%')
{ {
needDecode = true; needDecode = true;
chFound = scan.Seek(' ', '?'); chFound = scan.Seek(_vectorSpaces, _vectorQuestionMarks);
} }
var pathBegin = begin; var pathBegin = begin;
@ -733,7 +740,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
if (chFound == '?') if (chFound == '?')
{ {
begin = scan; begin = scan;
if (scan.Seek(' ') != ' ') if (scan.Seek(_vectorSpaces) != ' ')
{ {
return false; return false;
} }
@ -742,7 +749,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
scan.Take(); scan.Take();
begin = scan; begin = scan;
if (scan.Seek('\r') == -1) if (scan.Seek(_vectorCRs) == -1)
{ {
return false; return false;
} }
@ -836,7 +843,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
while (!scan.IsEnd) while (!scan.IsEnd)
{ {
var beginName = scan; var beginName = scan;
scan.Seek(':', '\r'); scan.Seek(_vectorColons, _vectorCRs);
var endName = scan; var endName = scan;
chFirst = scan.Take(); chFirst = scan.Take();
@ -887,7 +894,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
var wrapping = false; var wrapping = false;
while (!scan.IsEnd) while (!scan.IsEnd)
{ {
if (scan.Seek('\r') == -1) if (scan.Seek(_vectorCRs) == -1)
{ {
// no "\r" in sight, burn used bytes and go back to await more data // no "\r" in sight, burn used bytes and go back to await more data
return false; return false;

View File

@ -168,16 +168,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
} }
} }
public int Seek(int char0) public int Seek(Vector<byte> byte0Vector)
{ {
if (IsDefault) if (IsDefault)
{ {
return -1; return -1;
} }
var byte0 = (byte)char0;
var ch0Vector = new Vector<byte>(byte0);
var block = _block; var block = _block;
var index = _index; var index = _index;
var array = block.Array; var array = block.Array;
@ -201,25 +198,28 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
if (following >= Vector<byte>.Count) if (following >= Vector<byte>.Count)
{ {
var data = new Vector<byte>(array, index); var data = new Vector<byte>(array, index);
var ch0Equals = Vector.Equals(data, ch0Vector); var byte0Equals = Vector.Equals(data, byte0Vector);
if (ch0Equals.Equals(Vector<byte>.Zero)) if (byte0Equals.Equals(Vector<byte>.Zero))
{ {
index += Vector<byte>.Count; index += Vector<byte>.Count;
continue; continue;
} }
_block = block; _block = block;
_index = index + FindFirstEqualByte(ch0Equals); _index = index + FindFirstEqualByte(byte0Equals);
return char0; return byte0Vector[0];
} }
var byte0 = byte0Vector[0];
while (following > 0) while (following > 0)
{ {
if (block.Array[index] == byte0) if (block.Array[index] == byte0)
{ {
_block = block; _block = block;
_index = index; _index = index;
return char0; return byte0;
} }
following--; following--;
index++; index++;
@ -228,18 +228,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
} }
} }
public int Seek(int char0, int char1) public int Seek(Vector<byte> byte0Vector, Vector<byte> byte1Vector)
{ {
if (IsDefault) if (IsDefault)
{ {
return -1; return -1;
} }
var byte0 = (byte)char0;
var byte1 = (byte)char1;
var ch0Vector = new Vector<byte>(byte0);
var ch1Vector = new Vector<byte>(byte1);
var block = _block; var block = _block;
var index = _index; var index = _index;
var array = block.Array; var array = block.Array;
@ -263,21 +258,21 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
if (following >= Vector<byte>.Count) if (following >= Vector<byte>.Count)
{ {
var data = new Vector<byte>(array, index); var data = new Vector<byte>(array, index);
var ch0Equals = Vector.Equals(data, ch0Vector); var byte0Equals = Vector.Equals(data, byte0Vector);
var ch1Equals = Vector.Equals(data, ch1Vector); var byte1Equals = Vector.Equals(data, byte1Vector);
int ch0Index = int.MaxValue; int byte0Index = int.MaxValue;
int ch1Index = int.MaxValue; int byte1Index = int.MaxValue;
if (!ch0Equals.Equals(Vector<byte>.Zero)) if (!byte0Equals.Equals(Vector<byte>.Zero))
{ {
ch0Index = FindFirstEqualByte(ch0Equals); byte0Index = FindFirstEqualByte(byte0Equals);
} }
if (!ch1Equals.Equals(Vector<byte>.Zero)) if (!byte1Equals.Equals(Vector<byte>.Zero))
{ {
ch1Index = FindFirstEqualByte(ch1Equals); byte1Index = FindFirstEqualByte(byte1Equals);
} }
if (ch0Index == int.MaxValue && ch1Index == int.MaxValue) if (byte0Index == int.MaxValue && byte1Index == int.MaxValue)
{ {
index += Vector<byte>.Count; index += Vector<byte>.Count;
continue; continue;
@ -285,15 +280,19 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
_block = block; _block = block;
if (ch0Index < ch1Index) if (byte0Index < byte1Index)
{ {
_index = index + ch0Index; _index = index + byte0Index;
return char0; return byte0Vector[0];
} }
_index = index + ch1Index; _index = index + byte1Index;
return char1; return byte1Vector[0];
} }
byte byte0 = byte0Vector[0];
byte byte1 = byte1Vector[0];
while (following > 0) while (following > 0)
{ {
var byteIndex = block.Array[index]; var byteIndex = block.Array[index];
@ -301,13 +300,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
{ {
_block = block; _block = block;
_index = index; _index = index;
return char0; return byte0;
} }
else if (byteIndex == byte1) else if (byteIndex == byte1)
{ {
_block = block; _block = block;
_index = index; _index = index;
return char1; return byte1;
} }
following--; following--;
index++; index++;
@ -316,20 +315,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
} }
} }
public int Seek(int char0, int char1, int char2) public int Seek(Vector<byte> byte0Vector, Vector<byte> byte1Vector, Vector<byte> byte2Vector)
{ {
if (IsDefault) if (IsDefault)
{ {
return -1; return -1;
} }
var byte0 = (byte)char0;
var byte1 = (byte)char1;
var byte2 = (byte)char2;
var ch0Vector = new Vector<byte>(byte0);
var ch1Vector = new Vector<byte>(byte1);
var ch2Vector = new Vector<byte>(byte2);
var block = _block; var block = _block;
var index = _index; var index = _index;
var array = block.Array; var array = block.Array;
@ -353,57 +345,57 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
if (following >= Vector<byte>.Count) if (following >= Vector<byte>.Count)
{ {
var data = new Vector<byte>(array, index); var data = new Vector<byte>(array, index);
var ch0Equals = Vector.Equals(data, ch0Vector); var byte0Equals = Vector.Equals(data, byte0Vector);
var ch1Equals = Vector.Equals(data, ch1Vector); var byte1Equals = Vector.Equals(data, byte1Vector);
var ch2Equals = Vector.Equals(data, ch2Vector); var byte2Equals = Vector.Equals(data, byte2Vector);
int ch0Index = int.MaxValue; int byte0Index = int.MaxValue;
int ch1Index = int.MaxValue; int byte1Index = int.MaxValue;
int ch2Index = int.MaxValue; int byte2Index = int.MaxValue;
if (!ch0Equals.Equals(Vector<byte>.Zero)) if (!byte0Equals.Equals(Vector<byte>.Zero))
{ {
ch0Index = FindFirstEqualByte(ch0Equals); byte0Index = FindFirstEqualByte(byte0Equals);
} }
if (!ch1Equals.Equals(Vector<byte>.Zero)) if (!byte1Equals.Equals(Vector<byte>.Zero))
{ {
ch1Index = FindFirstEqualByte(ch1Equals); byte1Index = FindFirstEqualByte(byte1Equals);
} }
if (!ch2Equals.Equals(Vector<byte>.Zero)) if (!byte2Equals.Equals(Vector<byte>.Zero))
{ {
ch2Index = FindFirstEqualByte(ch2Equals); byte2Index = FindFirstEqualByte(byte2Equals);
} }
if (ch0Index == int.MaxValue && ch1Index == int.MaxValue && ch2Index == int.MaxValue) if (byte0Index == int.MaxValue && byte1Index == int.MaxValue && byte2Index == int.MaxValue)
{ {
index += Vector<byte>.Count; index += Vector<byte>.Count;
continue; continue;
} }
int toReturn, toMove; int toReturn, toMove;
if (ch0Index < ch1Index) if (byte0Index < byte1Index)
{ {
if (ch0Index < ch2Index) if (byte0Index < byte2Index)
{ {
toReturn = char0; toReturn = byte0Vector[0];
toMove = ch0Index; toMove = byte0Index;
} }
else else
{ {
toReturn = char2; toReturn = byte2Vector[0];
toMove = ch2Index; toMove = byte2Index;
} }
} }
else else
{ {
if (ch1Index < ch2Index) if (byte1Index < byte2Index)
{ {
toReturn = char1; toReturn = byte1Vector[0];
toMove = ch1Index; toMove = byte1Index;
} }
else else
{ {
toReturn = char2; toReturn = byte2Vector[0];
toMove = ch2Index; toMove = byte2Index;
} }
} }
@ -412,6 +404,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
return toReturn; return toReturn;
} }
var byte0 = byte0Vector[0];
var byte1 = byte1Vector[0];
var byte2 = byte2Vector[0];
while (following > 0) while (following > 0)
{ {
var byteIndex = block.Array[index]; var byteIndex = block.Array[index];
@ -419,19 +415,19 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
{ {
_block = block; _block = block;
_index = index; _index = index;
return char0; return byte0;
} }
else if (byteIndex == byte1) else if (byteIndex == byte1)
{ {
_block = block; _block = block;
_index = index; _index = index;
return char1; return byte1;
} }
else if (byteIndex == byte2) else if (byteIndex == byte2)
{ {
_block = block; _block = block;
_index = index; _index = index;
return char2; return byte2;
} }
following--; following--;
index++; index++;
@ -440,10 +436,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
} }
} }
private static int FindFirstEqualByte(Vector<byte> chEquals) private static int FindFirstEqualByte(Vector<byte> byteEquals)
{ {
// Quasi-tree search // Quasi-tree search
var vector64 = Vector.AsVectorInt64(chEquals); var vector64 = Vector.AsVectorInt64(byteEquals);
for (var i = 0; i < Vector<long>.Count; i++) for (var i = 0; i < Vector<long>.Count; i++)
{ {
var longValue = vector64[i]; var longValue = vector64[i];
@ -451,18 +447,18 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
var shift = i << 1; var shift = i << 1;
var offset = shift << 2; var offset = shift << 2;
var vector32 = Vector.AsVectorInt32(chEquals); var vector32 = Vector.AsVectorInt32(byteEquals);
if (vector32[shift] != 0) if (vector32[shift] != 0)
{ {
if (chEquals[offset] != 0) return offset; if (byteEquals[offset] != 0) return offset;
if (chEquals[++offset] != 0) return offset; if (byteEquals[++offset] != 0) return offset;
if (chEquals[++offset] != 0) return offset; if (byteEquals[++offset] != 0) return offset;
return ++offset; return ++offset;
} }
offset += 4; offset += 4;
if (chEquals[offset] != 0) return offset; if (byteEquals[offset] != 0) return offset;
if (chEquals[++offset] != 0) return offset; if (byteEquals[++offset] != 0) return offset;
if (chEquals[++offset] != 0) return offset; if (byteEquals[++offset] != 0) return offset;
return ++offset; return ++offset;
} }
throw new InvalidOperationException(); throw new InvalidOperationException();

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using Microsoft.AspNet.Server.Kestrel.Infrastructure; using Microsoft.AspNet.Server.Kestrel.Infrastructure;
using System.Numerics;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.KestrelTests namespace Microsoft.AspNet.Server.KestrelTests
@ -17,31 +18,36 @@ namespace Microsoft.AspNet.Server.KestrelTests
{ {
block.Array[block.End++] = ch; block.Array[block.End++] = ch;
} }
var vectorMaxValues = new Vector<byte>(byte.MaxValue);
var iterator = block.GetIterator(); var iterator = block.GetIterator();
foreach (var ch in Enumerable.Range(0, 256).Select(x => (char)x)) foreach (var ch in Enumerable.Range(0, 256).Select(x => (byte)x))
{ {
var vectorCh = new Vector<byte>(ch);
var hit = iterator; var hit = iterator;
hit.Seek(ch); hit.Seek(vectorCh);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
hit = iterator; hit = iterator;
hit.Seek(ch, byte.MaxValue); hit.Seek(vectorCh, vectorMaxValues);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
hit = iterator; hit = iterator;
hit.Seek(byte.MaxValue, ch); hit.Seek(vectorMaxValues, vectorCh);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
hit = iterator; hit = iterator;
hit.Seek(ch, byte.MaxValue, byte.MaxValue); hit.Seek(vectorCh, vectorMaxValues, vectorMaxValues);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
hit = iterator; hit = iterator;
hit.Seek(byte.MaxValue, ch, byte.MaxValue); hit.Seek(vectorMaxValues, vectorCh, vectorMaxValues);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
hit = iterator; hit = iterator;
hit.Seek(ch, byte.MaxValue, byte.MaxValue); hit.Seek(vectorCh, vectorMaxValues, vectorMaxValues);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
} }
} }
@ -69,31 +75,35 @@ namespace Microsoft.AspNet.Server.KestrelTests
block3.Array[block3.End++] = ch; block3.Array[block3.End++] = ch;
} }
var vectorMaxValues = new Vector<byte>(byte.MaxValue);
var iterator = block1.GetIterator(); var iterator = block1.GetIterator();
foreach (var ch in Enumerable.Range(0, 256).Select(x => (char)x)) foreach (var ch in Enumerable.Range(0, 256).Select(x => (byte)x))
{ {
var vectorCh = new Vector<byte>(ch);
var hit = iterator; var hit = iterator;
hit.Seek(ch); hit.Seek(vectorCh);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
hit = iterator; hit = iterator;
hit.Seek(ch, byte.MaxValue); hit.Seek(vectorCh, vectorMaxValues);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
hit = iterator; hit = iterator;
hit.Seek(byte.MaxValue, ch); hit.Seek(vectorMaxValues, vectorCh);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
hit = iterator; hit = iterator;
hit.Seek(ch, byte.MaxValue, byte.MaxValue); hit.Seek(vectorCh, vectorMaxValues, vectorMaxValues);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
hit = iterator; hit = iterator;
hit.Seek(byte.MaxValue, ch, byte.MaxValue); hit.Seek(vectorMaxValues, vectorCh, vectorMaxValues);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
hit = iterator; hit = iterator;
hit.Seek(ch, byte.MaxValue, byte.MaxValue); hit.Seek(vectorMaxValues, vectorMaxValues, vectorCh);
Assert.Equal(ch, iterator.GetLength(hit)); Assert.Equal(ch, iterator.GetLength(hit));
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using Microsoft.AspNet.Server.Kestrel.Infrastructure; using Microsoft.AspNet.Server.Kestrel.Infrastructure;
using System.Numerics;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.KestrelTests namespace Microsoft.AspNet.Server.KestrelTests
@ -52,15 +53,15 @@ namespace Microsoft.AspNet.Server.KestrelTests
int found = -1; int found = -1;
if (searchFor.Length == 1) if (searchFor.Length == 1)
{ {
found = begin.Seek(searchFor[0]); found = begin.Seek(new Vector<byte>((byte)searchFor[0]));
} }
else if (searchFor.Length == 2) else if (searchFor.Length == 2)
{ {
found = begin.Seek(searchFor[0], searchFor[1]); found = begin.Seek(new Vector<byte>((byte)searchFor[0]), new Vector<byte>((byte)searchFor[1]));
} }
else if (searchFor.Length == 3) else if (searchFor.Length == 3)
{ {
found = begin.Seek(searchFor[0], searchFor[1], searchFor[2]); found = begin.Seek(new Vector<byte>((byte)searchFor[0]), new Vector<byte>((byte)searchFor[1]), new Vector<byte>((byte)searchFor[2]));
} }
else else
{ {
@ -217,7 +218,7 @@ namespace Microsoft.AspNet.Server.KestrelTests
block.End += chars.Length; block.End += chars.Length;
var begin = block.GetIterator(); var begin = block.GetIterator();
var end = begin; var end = begin;
end.Seek(endChar); end.Seek(new Vector<byte>((byte)endChar));
string knownString; string knownString;
// Act // Act