瀏覽代碼

Performance fix for float/double write bytes. Performance fix, do not use Array.Copy.

csharptest 14 年之前
父節點
當前提交
2772dfe8a1

+ 3 - 2
src/ProtoBench/Program.cs

@@ -87,6 +87,7 @@ namespace Google.ProtocolBuffers.ProtoBench
                 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 @@ namespace Google.ProtocolBuffers.ProtoBench
             }
             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 @@ namespace Google.ProtocolBuffers.ProtoBench
                         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)
                         {

+ 3 - 3
src/ProtocolBuffers/ByteString.cs

@@ -123,7 +123,7 @@ namespace Google.ProtocolBuffers
         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 @@ namespace Google.ProtocolBuffers
         /// <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>

+ 32 - 0
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];
+        }
+    }
+}

+ 6 - 6
src/ProtocolBuffers/CodedInputStream.cs

@@ -1225,7 +1225,7 @@ namespace Google.ProtocolBuffers
             {
                 // 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 @@ namespace Google.ProtocolBuffers
                 // 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 @@ namespace Google.ProtocolBuffers
 
                 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 @@ namespace Google.ProtocolBuffers
 
                 // 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;
                 }
 

+ 28 - 5
src/ProtocolBuffers/CodedOutputStream.cs

@@ -38,6 +38,7 @@ using System;
 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 @@ namespace Google.ProtocolBuffers
             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 @@ namespace Google.ProtocolBuffers
             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 @@ namespace Google.ProtocolBuffers
         {
             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 @@ namespace Google.ProtocolBuffers
                 // 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 @@ namespace Google.ProtocolBuffers
                 if (length <= limit)
                 {
                     // Fits in new buffer.
-                    Array.Copy(value, offset, buffer, 0, length);
+                    Bytes.Copy(value, offset, buffer, 0, length);
                     position = length;
                 }
                 else

+ 1 - 0
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" />

+ 1 - 0
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" />