Explorar o código

optimize WriteFloat

Jan Tattermusch %!s(int64=5) %!d(string=hai) anos
pai
achega
a296413b5a
Modificáronse 1 ficheiros con 24 adicións e 13 borrados
  1. 24 13
      csharp/src/Google.Protobuf/WritingPrimitives.cs

+ 24 - 13
csharp/src/Google.Protobuf/WritingPrimitives.cs

@@ -32,6 +32,7 @@
 
 using System;
 using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
 using System.Security;
 using System.Text;
 
@@ -61,25 +62,35 @@ namespace Google.Protobuf
         /// Writes a float field value, without a tag, to the stream.
         /// </summary>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void WriteFloat(ref Span<byte> buffer, ref WriterInternalState state, float value)
+        public static unsafe void WriteFloat(ref Span<byte> buffer, ref WriterInternalState state, float value)
         {
-            // TODO: avoid allocating a byte array!!!
-            byte[] rawBytes = BitConverter.GetBytes(value);
-            if (!BitConverter.IsLittleEndian)
+            const int length = sizeof(float);
+            if (state.limit - state.position >= length)
             {
-                ByteArray.Reverse(rawBytes);
-            }
+                // if there's enough space in the buffer, write the float directly into the buffer
+                var floatSpan = buffer.Slice(state.position, length);
+                Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(floatSpan), value);
 
-            if (state.limit - state.position >= 4)
-            {
-                buffer[state.position++] = rawBytes[0];
-                buffer[state.position++] = rawBytes[1];
-                buffer[state.position++] = rawBytes[2];
-                buffer[state.position++] = rawBytes[3];
+                if (!BitConverter.IsLittleEndian)
+                {
+                    floatSpan.Reverse();
+                }
+                state.position += length;
             }
             else
             {
-                WriteRawBytes(ref buffer, ref state, rawBytes, 0, 4);
+                Span<byte> floatSpan = stackalloc byte[length];
+                Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(floatSpan), value);
+
+                if (!BitConverter.IsLittleEndian)
+                {
+                    floatSpan.Reverse();
+                }
+
+                WriteRawByte(ref buffer, ref state, floatSpan[0]);
+                WriteRawByte(ref buffer, ref state, floatSpan[1]);
+                WriteRawByte(ref buffer, ref state, floatSpan[2]);
+                WriteRawByte(ref buffer, ref state, floatSpan[3]);
             }
         }