Merge branch 'anderman/FindFirstByteFast' into dev
This commit is contained in:
commit
7ef70bc145
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue