Find First Byte Fast
This commit is contained in:
parent
849ff2016c
commit
1b09a76ebb
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
|
||||||
{
|
{
|
||||||
public struct MemoryPoolIterator2
|
public struct MemoryPoolIterator2
|
||||||
{
|
{
|
||||||
private readonly static int _vectorSpan = Vector<byte>.Count;
|
private static readonly int _vectorSpan = Vector<byte>.Count;
|
||||||
|
|
||||||
private MemoryPoolBlock2 _block;
|
private MemoryPoolBlock2 _block;
|
||||||
private int _index;
|
private int _index;
|
||||||
|
|
@ -203,7 +203,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
|
||||||
long nextLong;
|
long nextLong;
|
||||||
fixed (byte* ptr = &_block.Next.Array[_block.Next.Start])
|
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);
|
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
|
// Quasi-tree search
|
||||||
var vector64 = Vector.AsVectorInt64(byteEquals);
|
var vector64 = Vector.AsVectorInt64(byteEquals);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,34 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
_pool.Dispose();
|
_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]
|
[Theory]
|
||||||
[InlineData("a", "a", 'a', 0)]
|
[InlineData("a", "a", 'a', 0)]
|
||||||
[InlineData("ab", "a", 'a', 0)]
|
[InlineData("ab", "a", 'a', 0)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue