Performance fix for float/double write bytes.  Performance fix, do not use Array.Copy.
diff --git a/src/ProtoBench/Program.cs b/src/ProtoBench/Program.cs
index 7d91bbe..36f7850 100644
--- a/src/ProtoBench/Program.cs
+++ b/src/ProtoBench/Program.cs
@@ -87,6 +87,7 @@
                 Console.Error.WriteLine("(You can specify multiple pairs of descriptor type name and input data.)");

                 return 1;

             }

+

             bool success = true;

             for (int i = 0; i < args.Length; i += 2)

             {

@@ -94,7 +95,7 @@
             }

             return success ? 0 : 1;

         }

-

+        

         /// <summary>

         /// Runs a single test. Error messages are displayed to Console.Error, and the return value indicates

         /// general success/failure.

@@ -185,7 +186,7 @@
                         double first = (iterations * dataSize) / (elapsed.TotalSeconds * 1024 * 1024);

                         if (Verbose) Console.WriteLine("Round ---: Count = {1,6}, Bps = {2,8:f3}", 0, iterations, first);

                         elapsed = TimeSpan.Zero;

-                        int max = FastTest ? 30 : 100;

+                        int max = FastTest ? 10 : 30;

 

                         while (runs < max)

                         {

diff --git a/src/ProtocolBuffers/ByteString.cs b/src/ProtocolBuffers/ByteString.cs
index e645a9f..06708af 100644
--- a/src/ProtocolBuffers/ByteString.cs
+++ b/src/ProtocolBuffers/ByteString.cs
@@ -123,7 +123,7 @@
         public static ByteString CopyFrom(byte[] bytes, int offset, int count)

         {

             byte[] portion = new byte[count];

-            Array.Copy(bytes, offset, portion, 0, count);

+            Bytes.Copy(bytes, offset, portion, 0, count);

             return new ByteString(portion);

         }

 

@@ -259,9 +259,9 @@
         /// <summary>

         /// Copies the entire byte array to the destination array provided at the offset specified.

         /// </summary>

-        public void CopyTo(Array array, int position)

+        public void CopyTo(byte[] array, int position)

         {

-            Array.Copy(bytes, 0, array, position, bytes.Length);

+            Bytes.Copy(bytes, 0, array, position, bytes.Length);

         }

 

         /// <summary>

diff --git a/src/ProtocolBuffers/Bytes.cs b/src/ProtocolBuffers/Bytes.cs
new file mode 100644
index 0000000..88bc16f
--- /dev/null
+++ b/src/ProtocolBuffers/Bytes.cs
@@ -0,0 +1,32 @@
+namespace Google.ProtocolBuffers

+{

+    /// <summary>

+    /// Provides a utility routine to copy small arrays much more quickly than Buffer.BlockCopy

+    /// </summary>

+    static class Bytes

+    {

+        /// <summary>

+        /// The threshold above which you should use Buffer.BlockCopy rather than Bytes.Copy

+        /// </summary>

+        const int CopyThreshold = 12;

+        /// <summary>

+        /// Determines which copy routine to use based on the number of bytes to be copied.

+        /// </summary>

+        public static void Copy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)

+        {

+            if (count > CopyThreshold)

+                global::System.Buffer.BlockCopy(src, srcOffset, dst, dstOffset, count);

+            else

+                ByteCopy(src, srcOffset, dst, dstOffset, count);

+        }

+        /// <summary>

+        /// Copyies the bytes provided with a for loop, faster when there are only a few bytes to copy

+        /// </summary>

+        public static void ByteCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)

+        {

+            int stop = srcOffset + count;

+            for (int i = srcOffset; i < stop; i++)

+                dst[dstOffset++] = src[i];

+        }

+    }

+}
\ No newline at end of file
diff --git a/src/ProtocolBuffers/CodedInputStream.cs b/src/ProtocolBuffers/CodedInputStream.cs
index 74fa947..4f9bdc2 100644
--- a/src/ProtocolBuffers/CodedInputStream.cs
+++ b/src/ProtocolBuffers/CodedInputStream.cs
@@ -1225,7 +1225,7 @@
             {

                 // We have all the bytes we need already.

                 byte[] bytes = new byte[size];

-                Array.Copy(buffer, bufferPos, bytes, 0, size);

+                Bytes.Copy(buffer, bufferPos, bytes, 0, size);

                 bufferPos += size;

                 return bytes;

             }

@@ -1237,7 +1237,7 @@
                 // First copy what we have.

                 byte[] bytes = new byte[size];

                 int pos = bufferSize - bufferPos;

-                Array.Copy(buffer, bufferPos, bytes, 0, pos);

+                Bytes.Copy(buffer, bufferPos, bytes, 0, pos);

                 bufferPos = bufferSize;

 

                 // We want to use RefillBuffer() and then copy from the buffer into our

@@ -1247,13 +1247,13 @@
 

                 while (size - pos > bufferSize)

                 {

-                    Array.Copy(buffer, 0, bytes, pos, bufferSize);

+                    Buffer.BlockCopy(buffer, 0, bytes, pos, bufferSize);

                     pos += bufferSize;

                     bufferPos = bufferSize;

                     RefillBuffer(true);

                 }

 

-                Array.Copy(buffer, 0, bytes, pos, size - pos);

+                Bytes.Copy(buffer, 0, bytes, pos, size - pos);

                 bufferPos = size - pos;

 

                 return bytes;

@@ -1305,12 +1305,12 @@
 

                 // Start by copying the leftover bytes from this.buffer.

                 int newPos = originalBufferSize - originalBufferPos;

-                Array.Copy(buffer, originalBufferPos, bytes, 0, newPos);

+                Bytes.Copy(buffer, originalBufferPos, bytes, 0, newPos);

 

                 // And now all the chunks.

                 foreach (byte[] chunk in chunks)

                 {

-                    Array.Copy(chunk, 0, bytes, newPos, chunk.Length);

+                    Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length);

                     newPos += chunk.Length;

                 }

 

diff --git a/src/ProtocolBuffers/CodedOutputStream.cs b/src/ProtocolBuffers/CodedOutputStream.cs
index 3103205..bd50866 100644
--- a/src/ProtocolBuffers/CodedOutputStream.cs
+++ b/src/ProtocolBuffers/CodedOutputStream.cs
@@ -38,6 +38,7 @@
 using System.Collections.Generic;

 using System.Globalization;

 using System.IO;

+using System.Runtime.InteropServices;

 using System.Text;

 using Google.ProtocolBuffers.Descriptors;

 

@@ -648,7 +649,20 @@
             byte[] rawBytes = BitConverter.GetBytes(value);

             if (!BitConverter.IsLittleEndian) 

                 Array.Reverse(rawBytes);

-            WriteRawBytes(rawBytes, 0, 8);

+            

+            if (limit - position >= 8)

+            {

+                buffer[position++] = rawBytes[0];

+                buffer[position++] = rawBytes[1];

+                buffer[position++] = rawBytes[2];

+                buffer[position++] = rawBytes[3];

+                buffer[position++] = rawBytes[4];

+                buffer[position++] = rawBytes[5];

+                buffer[position++] = rawBytes[6];

+                buffer[position++] = rawBytes[7];

+            }

+            else

+                WriteRawBytes(rawBytes, 0, 8);

 #else

             WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value));

 #endif

@@ -662,7 +676,16 @@
             byte[] rawBytes = BitConverter.GetBytes(value);

             if (!BitConverter.IsLittleEndian) 

                 Array.Reverse(rawBytes);

-            WriteRawBytes(rawBytes, 0, 4);

+

+            if (limit - position >= 4)

+            {

+                buffer[position++] = rawBytes[0];

+                buffer[position++] = rawBytes[1];

+                buffer[position++] = rawBytes[2];

+                buffer[position++] = rawBytes[3];

+            }

+            else

+                WriteRawBytes(rawBytes, 0, 4);

         }

 

         /// <summary>

@@ -985,7 +1008,7 @@
         {

             if (limit - position >= length)

             {

-                Array.Copy(value, offset, buffer, position, length);

+                Bytes.Copy(value, offset, buffer, position, length);

                 // We have room in the current buffer.

                 position += length;

             }

@@ -994,7 +1017,7 @@
                 // Write extends past current buffer.  Fill the rest of this buffer and

                 // flush.

                 int bytesWritten = limit - position;

-                Array.Copy(value, offset, buffer, position, bytesWritten);

+                Bytes.Copy(value, offset, buffer, position, bytesWritten);

                 offset += bytesWritten;

                 length -= bytesWritten;

                 position = limit;

@@ -1006,7 +1029,7 @@
                 if (length <= limit)

                 {

                     // Fits in new buffer.

-                    Array.Copy(value, offset, buffer, 0, length);

+                    Bytes.Copy(value, offset, buffer, 0, length);

                     position = length;

                 }

                 else

diff --git a/src/ProtocolBuffers/ProtocolBuffers.csproj b/src/ProtocolBuffers/ProtocolBuffers.csproj
index a059ca3..cf21290 100644
--- a/src/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/src/ProtocolBuffers/ProtocolBuffers.csproj
@@ -99,6 +99,7 @@
     <Compile Include="AbstractMessageLite.cs">

       <SubType>Code</SubType>

     </Compile>

+    <Compile Include="Bytes.cs" />

     <Compile Include="ByteString.cs" />

     <Compile Include="Collections\Enumerables.cs" />

     <Compile Include="Collections\IPopsicleList.cs" />

diff --git a/src/ProtocolBuffers/ProtocolBuffersLite.csproj b/src/ProtocolBuffers/ProtocolBuffersLite.csproj
index 936a695..fc1c7f6 100644
--- a/src/ProtocolBuffers/ProtocolBuffersLite.csproj
+++ b/src/ProtocolBuffers/ProtocolBuffersLite.csproj
@@ -78,6 +78,7 @@
   <ItemGroup>

     <Compile Include="AbstractBuilderLite.cs" />

     <Compile Include="AbstractMessageLite.cs" />

+    <Compile Include="Bytes.cs" />

     <Compile Include="CodedOutputStream.ComputeSize.cs" />

     <Compile Include="Collections\Dictionaries.cs" />

     <Compile Include="Collections\Enumerables.cs" />