From 59284450fa2a85f9f355b4de5a733323af094dcf Mon Sep 17 00:00:00 2001 From: WilliamWhispell Date: Fri, 8 Mar 2019 17:35:21 -0500 Subject: [PATCH] Use fixed size for bool, float and double field in codec (#5810) * 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 --- .../v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs | 6 +++--- csharp/src/Google.Protobuf.Test/FieldCodecTest.cs | 6 +++--- .../Google.Protobuf/CodedOutputStream.ComputeSize.cs | 10 +++++++--- csharp/src/Google.Protobuf/FieldCodec.cs | 6 +++--- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs index 0e2bad59e5..3907666827 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs @@ -43,7 +43,7 @@ namespace Google.Protobuf #pragma warning disable 0414 // Used by tests via reflection - do not remove! private static readonly List Codecs = new List { - new FieldCodecTestData(FieldCodec.ForBool(100), true, "Bool"), + new FieldCodecTestData(FieldCodec.ForBool(100), true, "FixedBool"), new FieldCodecTestData(FieldCodec.ForString(100), "sample", "String"), new FieldCodecTestData(FieldCodec.ForBytes(100), ByteString.CopyFrom(1, 2, 3), "Bytes"), new FieldCodecTestData(FieldCodec.ForInt32(100), -1000, "Int32"), @@ -56,8 +56,8 @@ namespace Google.Protobuf new FieldCodecTestData(FieldCodec.ForSFixed64(100), -1000, "SFixed64"), new FieldCodecTestData(FieldCodec.ForUInt64(100), 1234, "UInt64"), new FieldCodecTestData(FieldCodec.ForFixed64(100), 1234, "Fixed64"), - new FieldCodecTestData(FieldCodec.ForFloat(100), 1234.5f, "Float"), - new FieldCodecTestData(FieldCodec.ForDouble(100), 1234567890.5d, "Double"), + new FieldCodecTestData(FieldCodec.ForFloat(100), 1234.5f, "FixedFloat"), + new FieldCodecTestData(FieldCodec.ForDouble(100), 1234567890.5d, "FixedDouble"), new FieldCodecTestData( FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.ForeignBaz, "Enum"), new FieldCodecTestData( diff --git a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs index 77641163c0..b20ecccde2 100644 --- a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs +++ b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs @@ -43,7 +43,7 @@ namespace Google.Protobuf #pragma warning disable 0414 // Used by tests via reflection - do not remove! private static readonly List Codecs = new List { - new FieldCodecTestData(FieldCodec.ForBool(100), true, "Bool"), + new FieldCodecTestData(FieldCodec.ForBool(100), true, "FixedBool"), new FieldCodecTestData(FieldCodec.ForString(100), "sample", "String"), new FieldCodecTestData(FieldCodec.ForBytes(100), ByteString.CopyFrom(1, 2, 3), "Bytes"), new FieldCodecTestData(FieldCodec.ForInt32(100), -1000, "Int32"), @@ -56,8 +56,8 @@ namespace Google.Protobuf new FieldCodecTestData(FieldCodec.ForSFixed64(100), -1000, "SFixed64"), new FieldCodecTestData(FieldCodec.ForUInt64(100), 1234, "UInt64"), new FieldCodecTestData(FieldCodec.ForFixed64(100), 1234, "Fixed64"), - new FieldCodecTestData(FieldCodec.ForFloat(100), 1234.5f, "Float"), - new FieldCodecTestData(FieldCodec.ForDouble(100), 1234567890.5d, "Double"), + new FieldCodecTestData(FieldCodec.ForFloat(100), 1234.5f, "FixedFloat"), + new FieldCodecTestData(FieldCodec.ForDouble(100), 1234567890.5d, "FixedDouble"), new FieldCodecTestData( FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.ForeignBaz, "Enum"), new FieldCodecTestData( diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs b/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs index bf221c9c0a..aa7932470b 100644 --- a/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs +++ b/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs @@ -42,13 +42,17 @@ namespace Google.Protobuf 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; + /// /// Computes the number of bytes that would be needed to encode a /// double field, including the tag. /// public static int ComputeDoubleSize(double value) { - return LittleEndian64Size; + return DoubleSize; } /// @@ -57,7 +61,7 @@ namespace Google.Protobuf /// public static int ComputeFloatSize(float value) { - return LittleEndian32Size; + return FloatSize; } /// @@ -119,7 +123,7 @@ namespace Google.Protobuf /// public static int ComputeBoolSize(bool value) { - return 1; + return BoolSize; } /// diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs index 0610521dd6..7044ded93c 100644 --- a/csharp/src/Google.Protobuf/FieldCodec.cs +++ b/csharp/src/Google.Protobuf/FieldCodec.cs @@ -72,7 +72,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForBool(uint tag) { - return new FieldCodec(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.ComputeBoolSize, tag); + return new FieldCodec(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.BoolSize, tag); } /// @@ -182,7 +182,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForFloat(uint tag) { - return new FieldCodec(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.ComputeFloatSize, tag); + return new FieldCodec(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag); } /// @@ -192,7 +192,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForDouble(uint tag) { - return new FieldCodec(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.ComputeDoubleSize, tag); + return new FieldCodec(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,