Skip to content

Commit

Permalink
Use fixed size for bool, float and double field in codec (#5810)
Browse files Browse the repository at this point in the history
* Improve C# serialization performance of repeated fields for primitives.

* Changes based on feedback.

* Change compatibility tests to chec float, bool and double are fixed

* Changes based on feedback.

* In the compute methods use the newly created constants
  • Loading branch information
WilliamWhispell authored and anandolee committed Mar 8, 2019
1 parent 35c9a5f commit 5928445
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class FieldCodecTest
#pragma warning disable 0414 // Used by tests via reflection - do not remove!
private static readonly List<ICodecTestData> Codecs = new List<ICodecTestData>
{
new FieldCodecTestData<bool>(FieldCodec.ForBool(100), true, "Bool"),
new FieldCodecTestData<bool>(FieldCodec.ForBool(100), true, "FixedBool"),
new FieldCodecTestData<string>(FieldCodec.ForString(100), "sample", "String"),
new FieldCodecTestData<ByteString>(FieldCodec.ForBytes(100), ByteString.CopyFrom(1, 2, 3), "Bytes"),
new FieldCodecTestData<int>(FieldCodec.ForInt32(100), -1000, "Int32"),
Expand All @@ -56,8 +56,8 @@ public class FieldCodecTest
new FieldCodecTestData<long>(FieldCodec.ForSFixed64(100), -1000, "SFixed64"),
new FieldCodecTestData<ulong>(FieldCodec.ForUInt64(100), 1234, "UInt64"),
new FieldCodecTestData<ulong>(FieldCodec.ForFixed64(100), 1234, "Fixed64"),
new FieldCodecTestData<float>(FieldCodec.ForFloat(100), 1234.5f, "Float"),
new FieldCodecTestData<double>(FieldCodec.ForDouble(100), 1234567890.5d, "Double"),
new FieldCodecTestData<float>(FieldCodec.ForFloat(100), 1234.5f, "FixedFloat"),
new FieldCodecTestData<double>(FieldCodec.ForDouble(100), 1234567890.5d, "FixedDouble"),
new FieldCodecTestData<ForeignEnum>(
FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.ForeignBaz, "Enum"),
new FieldCodecTestData<ForeignMessage>(
Expand Down
6 changes: 3 additions & 3 deletions csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class FieldCodecTest
#pragma warning disable 0414 // Used by tests via reflection - do not remove!
private static readonly List<ICodecTestData> Codecs = new List<ICodecTestData>
{
new FieldCodecTestData<bool>(FieldCodec.ForBool(100), true, "Bool"),
new FieldCodecTestData<bool>(FieldCodec.ForBool(100), true, "FixedBool"),
new FieldCodecTestData<string>(FieldCodec.ForString(100), "sample", "String"),
new FieldCodecTestData<ByteString>(FieldCodec.ForBytes(100), ByteString.CopyFrom(1, 2, 3), "Bytes"),
new FieldCodecTestData<int>(FieldCodec.ForInt32(100), -1000, "Int32"),
Expand All @@ -56,8 +56,8 @@ public class FieldCodecTest
new FieldCodecTestData<long>(FieldCodec.ForSFixed64(100), -1000, "SFixed64"),
new FieldCodecTestData<ulong>(FieldCodec.ForUInt64(100), 1234, "UInt64"),
new FieldCodecTestData<ulong>(FieldCodec.ForFixed64(100), 1234, "Fixed64"),
new FieldCodecTestData<float>(FieldCodec.ForFloat(100), 1234.5f, "Float"),
new FieldCodecTestData<double>(FieldCodec.ForDouble(100), 1234567890.5d, "Double"),
new FieldCodecTestData<float>(FieldCodec.ForFloat(100), 1234.5f, "FixedFloat"),
new FieldCodecTestData<double>(FieldCodec.ForDouble(100), 1234567890.5d, "FixedDouble"),
new FieldCodecTestData<ForeignEnum>(
FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.ForeignBaz, "Enum"),
new FieldCodecTestData<ForeignMessage>(
Expand Down
10 changes: 7 additions & 3 deletions csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,17 @@ public sealed partial class CodedOutputStream
private const int LittleEndian64Size = 8;
private const int LittleEndian32Size = 4;

internal const int DoubleSize = LittleEndian64Size;
internal const int FloatSize = LittleEndian32Size;
internal const int BoolSize = 1;

/// <summary>
/// Computes the number of bytes that would be needed to encode a
/// double field, including the tag.
/// </summary>
public static int ComputeDoubleSize(double value)
{
return LittleEndian64Size;
return DoubleSize;
}

/// <summary>
Expand All @@ -57,7 +61,7 @@ public static int ComputeDoubleSize(double value)
/// </summary>
public static int ComputeFloatSize(float value)
{
return LittleEndian32Size;
return FloatSize;
}

/// <summary>
Expand Down Expand Up @@ -119,7 +123,7 @@ public static int ComputeFixed32Size(uint value)
/// </summary>
public static int ComputeBoolSize(bool value)
{
return 1;
return BoolSize;
}

/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions csharp/src/Google.Protobuf/FieldCodec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static FieldCodec<ByteString> ForBytes(uint tag)
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<bool> ForBool(uint tag)
{
return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.ComputeBoolSize, tag);
return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.BoolSize, tag);
}

/// <summary>
Expand Down Expand Up @@ -182,7 +182,7 @@ public static FieldCodec<ulong> ForUInt64(uint tag)
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<float> ForFloat(uint tag)
{
return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.ComputeFloatSize, tag);
return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag);
}

/// <summary>
Expand All @@ -192,7 +192,7 @@ public static FieldCodec<float> ForFloat(uint tag)
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<double> ForDouble(uint tag)
{
return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.ComputeDoubleSize, tag);
return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag);
}

// Enums are tricky. We can probably use expression trees to build these delegates automatically,
Expand Down

0 comments on commit 5928445

Please sign in to comment.