[OTLP] Refactor ProtobufSerializer.WriteReservedLength() to improve performance (#6367)

This commit is contained in:
Martin Costello 2025-07-21 14:16:07 +01:00 committed by GitHub
parent 361a1655b9
commit d8dfaa84a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 12 additions and 62 deletions

View File

@ -83,7 +83,7 @@
These packages are referenced as "PrivateAssets" or used in tests/examples.
-->
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="[0.13.12,0.14)" />
<PackageVersion Include="BenchmarkDotNet" Version="0.15.2" />
<PackageVersion Include="CommandLineParser" Version="[2.9.1,3.0)" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
<PackageVersion Include="Grpc.AspNetCore" Version="[2.59.0,3.0)" />

View File

@ -201,8 +201,8 @@ internal static class GrpcStatusDeserializer
throw new EndOfStreamException();
}
result |= (long)(b & 0x7F) << shift;
if ((b & 0x80) == 0)
result |= (long)(b & 0b_0111_1111) << shift;
if ((b & 0b_1000_0000) == 0)
{
return result;
}

View File

@ -18,6 +18,8 @@ internal static class ProtobufSerializer
private const ulong ULong128 = 0x80;
private const int Fixed32Size = 4;
private const int Fixed64Size = 8;
private const int MaskBitsLow = 0b_0111_1111;
private const int MaskBitHigh = 0b_1000_0000;
private static readonly Encoding Utf8Encoding = Encoding.UTF8;
@ -42,63 +44,11 @@ internal static class ProtobufSerializer
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void WriteReservedLength(byte[] buffer, int writePosition, int length)
{
int byteLength = 0;
int? firstByte = null;
int? secondByte = null;
int? thirdByte = null;
int? fourthByte = null;
do
{
switch (byteLength)
{
case 0:
firstByte = length & 0x7F;
break;
case 1:
secondByte = length & 0x7F;
break;
case 2:
thirdByte = length & 0x7F;
break;
case 3:
fourthByte = length & 0x7F;
break;
}
length >>= 7;
byteLength++;
}
while (length > 0);
if (fourthByte.HasValue)
{
buffer[writePosition++] = (byte)(firstByte!.Value | 0x80);
buffer[writePosition++] = (byte)(secondByte!.Value | 0x80);
buffer[writePosition++] = (byte)(thirdByte!.Value | 0x80);
buffer[writePosition++] = (byte)fourthByte!.Value;
}
else if (thirdByte.HasValue)
{
buffer[writePosition++] = (byte)(firstByte!.Value | 0x80);
buffer[writePosition++] = (byte)(secondByte!.Value | 0x80);
buffer[writePosition++] = (byte)(thirdByte!.Value | 0x80);
buffer[writePosition++] = 0;
}
else if (secondByte.HasValue)
{
buffer[writePosition++] = (byte)(firstByte!.Value | 0x80);
buffer[writePosition++] = (byte)(secondByte!.Value | 0x80);
buffer[writePosition++] = 0x80;
buffer[writePosition++] = 0;
}
else
{
buffer[writePosition++] = (byte)(firstByte!.Value | 0x80);
buffer[writePosition++] = 0x80;
buffer[writePosition++] = 0x80;
buffer[writePosition++] = 0;
}
var slice = buffer.AsSpan(writePosition, 4);
slice[0] = (byte)((length & MaskBitsLow) | MaskBitHigh);
slice[1] = (byte)(((length >> 7) & MaskBitsLow) | MaskBitHigh);
slice[2] = (byte)(((length >> 14) & MaskBitsLow) | MaskBitHigh);
slice[3] = (byte)((length >> 21) & MaskBitsLow);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -171,7 +121,7 @@ internal static class ProtobufSerializer
{
while (value >= UInt128)
{
buffer[writePosition++] = (byte)(0x80 | (value & 0x7F));
buffer[writePosition++] = (byte)(MaskBitHigh | (value & MaskBitsLow));
value >>= 7;
}
@ -184,7 +134,7 @@ internal static class ProtobufSerializer
{
while (value >= ULong128)
{
buffer[writePosition++] = (byte)(0x80 | (value & 0x7F));
buffer[writePosition++] = (byte)(MaskBitHigh | (value & MaskBitsLow));
value >>= 7;
}