Merge branch 'anderman/FindFirstByteFast' into dev

This commit is contained in:
Stephen Halter 2016-01-12 12:51:50 -08:00
commit 7ef70bc145
2 changed files with 61 additions and 3 deletions

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
{
public struct MemoryPoolIterator2
{
private readonly static int _vectorSpan = Vector<byte>.Count;
private static readonly int _vectorSpan = Vector<byte>.Count;
private MemoryPoolBlock2 _block;
private int _index;
@ -203,7 +203,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
long nextLong;
fixed (byte* ptr = &_block.Next.Array[_block.Next.Start])
{
nextLong = *(long*)(ptr );
nextLong = *(long*)(ptr);
}
return (blockLong >> (sizeof(long) - blockBytes) * 8) | (nextLong << (sizeof(long) - nextBytes) * 8);
@ -537,7 +537,37 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
}
}
private static int FindFirstEqualByte(ref Vector<byte> byteEquals)
/// <summary>
/// Find first byte
/// </summary>
/// <param name="byteEquals"></param >
/// <returns>The first index of the result vector</returns>
/// <exception cref="InvalidOperationException">byteEquals = 0</exception>
internal static int FindFirstEqualByte(ref Vector<byte> byteEquals)
{
if (!BitConverter.IsLittleEndian) return FindFirstEqualByteSlow(ref byteEquals);
// Quasi-tree search
var vector64 = Vector.AsVectorInt64(byteEquals);
for (var i = 0; i < Vector<long>.Count; i++)
{
var longValue = vector64[i];
if (longValue == 0) continue;
return (i << 3) +
((longValue & 0x00000000ffffffff) > 0
? (longValue & 0x000000000000ffff) > 0
? (longValue & 0x00000000000000ff) > 0 ? 0 : 1
: (longValue & 0x0000000000ff0000) > 0 ? 2 : 3
: (longValue & 0x0000ffff00000000) > 0
? (longValue & 0x000000ff00000000) > 0 ? 4 : 5
: (longValue & 0x00ff000000000000) > 0 ? 6 : 7);
}
throw new InvalidOperationException();
}
// Internal for testing
internal static int FindFirstEqualByteSlow(ref Vector<byte> byteEquals)
{
// Quasi-tree search
var vector64 = Vector.AsVectorInt64(byteEquals);

View File

@ -20,6 +20,34 @@ namespace Microsoft.AspNet.Server.KestrelTests
_pool.Dispose();
}
[Fact]
public void FindFirstByte()
{
var bytes = new byte[] {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
for (int i = 0; i < Vector<byte>.Count; i++)
{
Vector<byte> vector = new Vector<byte>(bytes);
Assert.Equal(i, MemoryPoolIterator2.FindFirstEqualByte(ref vector));
bytes[i] = 0;
}
}
[Fact]
public void _FindFirstByte()
{
var bytes = new byte[] {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
for (int i = 0; i < Vector<byte>.Count; i++)
{
Vector<byte> vector = new Vector<byte>(bytes);
Assert.Equal(i, MemoryPoolIterator2.FindFirstEqualByteSlow(ref vector));
bytes[i] = 0;
}
}
[Theory]
[InlineData("a", "a", 'a', 0)]
[InlineData("ab", "a", 'a', 0)]