Skip to content

Commit 3d63475

Browse files
author
ladeak
committed
Using inlining to gain further performance in the simd case
1 parent bb92ac9 commit 3d63475

File tree

3 files changed

+37
-28
lines changed

3 files changed

+37
-28
lines changed

src/CHttpServer/CHttpServer/Http3/QPackIntegerDecoder.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Buffers;
22
using System.Diagnostics;
33
using System.Numerics;
4+
using System.Runtime.CompilerServices;
45
using System.Runtime.Intrinsics;
56
using System.Runtime.Intrinsics.X86;
67

@@ -99,6 +100,7 @@ public bool TryDecodeInteger(ReadOnlySequence<byte> data, ref int currentIndex,
99100
/// <param name="currentIndex">The already parsed section.</param>
100101
/// <param name="result">The result number.</param>
101102
/// <returns>Returns true when a number is successfully decoded, returns false if the input data is incomplete.</returns>
103+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
102104
public bool TryDecodeIntegerSimd(ReadOnlySpan<byte> buffer, ref int currentIndex, out int result)
103105
{
104106
if (Avx2.IsSupported && buffer.Length >= 32 + currentIndex)
@@ -118,7 +120,7 @@ public bool TryDecodeIntegerSimd(ReadOnlySequence<byte> data, ref int currentInd
118120
{
119121
// Fast path, process the first span.
120122
var buffer = data.FirstSpan;
121-
if (Avx2.IsSupported && buffer.Length >= 32 + currentIndex && buffer[currentIndex + 1] >= 128) // The last condition makes sure that at least there are 3 total bytes.
123+
if (Avx2.IsSupported && buffer.Length >= 32 + currentIndex)
122124
return TryDecodeSimd(buffer, ref currentIndex, out result);
123125
return TryDecodeInteger(buffer, ref currentIndex, out result);
124126
}
@@ -219,6 +221,7 @@ private bool TryDecode62Bits(byte b, out long result)
219221
return false;
220222
}
221223

224+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
222225
private bool TryDecodeSimd(ReadOnlySpan<byte> buffer, ref int currentIndex, out int result)
223226
{
224227
Debug.Assert(buffer.Length >= 32 + currentIndex);

tests/CHttp.Benchmarks/Program.cs

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,61 +7,53 @@
77

88
BenchmarkRunner.Run<IntegerDecoderBenchmarks>();
99

10-
[SimpleJob, DisassemblyDiagnoser]
10+
[SimpleJob]
1111
public class IntegerDecoderComparisonBenchmarks
1212
{
1313
/// <summary>
14-
/// 2147483647, 167321, 1433, 31
14+
/// 2147483647, 167321, 1433, 31, 1073741950
1515
/// </summary>
16-
public static byte[][] _inputPrefixedSource = [
16+
public static byte[][] InputPrefixedSource { get; } = [
1717
[0b01111111, 0b10000000, 0b11111111, 0b11111111, 0b11111111, 0b00000111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1818
[0b01111111, 0b10011010, 0b10011010, 0b00001010, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1919
[0b01111111, 0b10011010, 0b00001010, 0 , 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2020
[0b00011111, 0 , 0 , 0 , 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
21+
[0b01111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b00000011, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2122
];
2223

23-
public static byte[][] _inputVariableSource = [
24+
public static byte[][] InputVariableSource { get; } = [
2425
[0b11000000, 0b00000000, 0b00000000, 0b00000000, 0b01111111, 0b11111111, 0b11111111, 0b11111111],
2526
[0b10000000, 0b00000010, 0b10001101, 0b10011001],
2627
[0b01000101, 0b10011001],
2728
[0b00011111],
29+
[0b11000000, 0b00000000, 0b00000000, 0b00000000, 0b01000000, 0b00000000, 0b00000000, 0b01111110]
2830
];
2931

30-
[Params(0, 1, 2, 3)]
31-
public int InputIndex
32-
{
33-
get => field;
34-
set
35-
{
36-
field = value;
37-
_inputPrefixed = _inputPrefixedSource[value];
38-
_inputVariable = _inputVariableSource[value];
39-
}
40-
}
41-
42-
public byte[] _inputPrefixed;
32+
[ParamsSource(nameof(InputPrefixedSource))]
33+
public static byte[] _inputPrefixed;
4334

35+
[ParamsSource(nameof(InputVariableSource))]
4436
public byte[] _inputVariable;
4537

4638
[Benchmark]
47-
public int DecodeInteger()
39+
public int DecodeIntegerSimd()
4840
{
4941
QPackIntegerDecoder decoder = new();
5042
if (decoder.BeginTryDecode(_inputPrefixed[0], 7, out int result))
5143
return result;
5244
var index = 1;
53-
decoder.TryDecodeInteger(_inputPrefixed, ref index, out result);
45+
decoder.TryDecodeIntegerSimd(_inputPrefixed, ref index, out result);
5446
return result;
5547
}
5648

5749
[Benchmark]
58-
public int DecodeIntegerSimd()
50+
public int DecodeInteger()
5951
{
6052
QPackIntegerDecoder decoder = new();
6153
if (decoder.BeginTryDecode(_inputPrefixed[0], 7, out int result))
6254
return result;
6355
var index = 1;
64-
decoder.TryDecodeIntegerSimd(_inputPrefixed, ref index, out result);
56+
decoder.TryDecodeInteger(_inputPrefixed, ref index, out result);
6557
return result;
6658
}
6759

@@ -73,28 +65,30 @@ public int DecodeIntegerVariable()
7365
}
7466
}
7567

76-
[SimpleJob, DisassemblyDiagnoser]
68+
[SimpleJob]
7769
public class IntegerDecoderBenchmarks
7870
{
79-
public static byte[] _input = [0b0111_1111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b00000011, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
71+
public static byte[] _input = [0b01111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b00000011, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
8072

8173
[Benchmark]
8274
public int DecodeInteger()
8375
{
8476
QPackIntegerDecoder decoder = new();
85-
decoder.BeginTryDecode(_input[0], 7, out _);
77+
if (decoder.BeginTryDecode(_input[0], 7, out int result))
78+
return result;
8679
var index = 1;
87-
decoder.TryDecodeInteger(_input, ref index, out int result);
80+
decoder.TryDecodeInteger(_input, ref index, out result);
8881
return result;
8982
}
9083

9184
[Benchmark]
9285
public int DecodeIntegerSimd()
9386
{
9487
QPackIntegerDecoder decoder = new();
95-
decoder.BeginTryDecode(_input[0], 7, out _);
88+
if (decoder.BeginTryDecode(_input[0], 7, out int result))
89+
return result;
9690
var index = 1;
97-
decoder.TryDecodeIntegerSimd(_input, ref index, out int result);
91+
decoder.TryDecodeIntegerSimd(_input, ref index, out result);
9892
return result;
9993
}
10094
}

tests/CHttpServer.Tests/Http3/QPackIntegerDecoderTests.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,18 @@ public void DecodeWithMoreBytes_Simd()
216216
Assert.Equal(268435455, result);
217217
}
218218

219+
220+
[Fact]
221+
public void DecodeWithMoreBytes2_Simd()
222+
{
223+
byte[] b = [0b01111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b00000011, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
224+
QPackIntegerDecoder decoder = new();
225+
decoder.BeginTryDecode(b[0], 7, out _);
226+
var index = 1;
227+
decoder.TryDecodeIntegerSimd(b, ref index, out int result);
228+
Assert.Equal(1073741950, result);
229+
}
230+
219231
[Fact]
220232
public void DecodeLimits_Zeros_Simd()
221233
{

0 commit comments

Comments
 (0)