Performance fix for double/float on read

pull/288/head
csharptest 14 years ago committed by rogerk
parent 2772dfe8a1
commit 4ba365d793
  1. 101
      src/ProtocolBuffers.Test/CompatTests/CompatibilityTests.cs
  2. 23
      src/ProtocolBuffers.Test/CompatTests/TextCompatibilityTests.cs
  3. 35
      src/ProtocolBuffers/CodedInputStream.cs

@ -15,107 +15,6 @@ namespace Google.ProtocolBuffers.CompatTests
where TMessage : IMessageLite<TMessage, TBuilder> where TMessage : IMessageLite<TMessage, TBuilder>
where TBuilder : IBuilderLite<TMessage, TBuilder>; where TBuilder : IBuilderLite<TMessage, TBuilder>;
#region RunBenchmark
protected void RunBenchmark<TMessage, TBuilder>(byte[] buffer, bool write)
where TMessage : IMessageLite<TMessage, TBuilder>
where TBuilder : IBuilderLite<TMessage, TBuilder>, new()
{
TBuilder builder = new TBuilder();
TMessage message = new TBuilder().MergeFrom(buffer).Build();
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
//simple warm-up
object content = SerializeMessage<TMessage, TBuilder>(message);
Assert.AreEqual(message, DeerializeMessage<TMessage, TBuilder>(content, new TBuilder(), ExtensionRegistry.Empty).Build());
//timming
long time = 0, sample = 1;
while (time < 100)
{
sample *= 10;
watch.Reset();
watch.Start();
if (write)
{
for (int i = 0; i < sample; i++)
SerializeMessage<TMessage, TBuilder>(message);
}
else
{
for (int i = 0; i < sample; i++)
DeerializeMessage<TMessage, TBuilder>(content, builder, ExtensionRegistry.Empty);
}
watch.Stop();
time = watch.ElapsedMilliseconds;
}
ulong rounds = (ulong)((100.0 / watch.ElapsedMilliseconds) * sample);
//test
watch.Reset();
watch.Start();
if (write)
{
for (ulong i = 0; i < rounds; i++)
SerializeMessage<TMessage, TBuilder>(message);
}
else
{
for (ulong i = 0; i < rounds; i++)
DeerializeMessage<TMessage, TBuilder>(content, builder, ExtensionRegistry.Empty);
}
watch.Stop();
System.Diagnostics.Trace.TraceInformation(
"\r\n{0} {4} {5} {3:n0} rps ({1:n0} rounds in {2:n0} ms)", typeof(TMessage).Name, rounds,
watch.ElapsedMilliseconds, (1000.0 / watch.ElapsedMilliseconds) * (double)rounds, TestName, write ? " write" : " read");
GC.GetTotalMemory(true);
GC.WaitForPendingFinalizers();
}
[Test]
public virtual void Message1OptimizeSizeWriterPerf()
{
RunBenchmark<SizeMessage1, SizeMessage1.Builder>(TestResources.google_message1, true);
}
[Test]
public virtual void Message1OptimizeSpeedWriterPerf()
{
RunBenchmark<SpeedMessage1, SpeedMessage1.Builder>(TestResources.google_message1, true);
}
[Test]
public virtual void Message2OptimizeSizeWriterPerf()
{
RunBenchmark<SizeMessage2, SizeMessage2.Builder>(TestResources.google_message2, true);
}
[Test]
public virtual void Message2OptimizeSpeedWriterPerf()
{
RunBenchmark<SpeedMessage2, SpeedMessage2.Builder>(TestResources.google_message2, true);
}
[Test]
public virtual void Message1OptimizeSizeReadPerf()
{
RunBenchmark<SizeMessage1, SizeMessage1.Builder>(TestResources.google_message1, false);
}
[Test]
public virtual void Message1OptimizeSpeedReadPerf()
{
RunBenchmark<SpeedMessage1, SpeedMessage1.Builder>(TestResources.google_message1, false);
}
[Test]
public virtual void Message2OptimizeSizeReadPerf()
{
RunBenchmark<SizeMessage2, SizeMessage2.Builder>(TestResources.google_message2, false);
}
[Test]
public virtual void Message2OptimizeSpeedReadPerf()
{
RunBenchmark<SpeedMessage2, SpeedMessage2.Builder>(TestResources.google_message2, false);
}
#endregion
[Test] [Test]
public virtual void RoundTripMessage1OptimizeSize() public virtual void RoundTripMessage1OptimizeSize()
{ {

@ -22,17 +22,6 @@ namespace Google.ProtocolBuffers.CompatTests
return builder; return builder;
} }
[Test, Explicit, Description("This test can take a very long time to run.")]
public override void Message2OptimizeSizeReadPerf()
{
base.Message2OptimizeSizeReadPerf();
}
[Test, Explicit, Description("This test can take a very long time to run.")]
public override void Message2OptimizeSpeedReadPerf()
{
base.Message2OptimizeSpeedReadPerf();
}
[Test, Explicit, Description("This test can take a very long time to run.")] [Test, Explicit, Description("This test can take a very long time to run.")]
public override void RoundTripMessage2OptimizeSize() public override void RoundTripMessage2OptimizeSize()
{ {
@ -44,17 +33,5 @@ namespace Google.ProtocolBuffers.CompatTests
{ {
base.RoundTripMessage2OptimizeSpeed(); base.RoundTripMessage2OptimizeSpeed();
} }
[Test, Explicit, Description("This test can take a very long time to run.")]
public override void Message2OptimizeSizeWriterPerf()
{
base.Message2OptimizeSizeWriterPerf();
}
[Test, Explicit, Description("This test can take a very long time to run.")]
public override void Message2OptimizeSpeedWriterPerf()
{
base.Message2OptimizeSpeedWriterPerf();
}
} }
} }

@ -204,15 +204,22 @@ namespace Google.ProtocolBuffers
public bool ReadDouble(ref double value) public bool ReadDouble(ref double value)
{ {
#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35 #if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
byte[] rawBytes = ReadRawBytes(8); if (BitConverter.IsLittleEndian && 8 <= bufferSize - bufferPos)
if (!BitConverter.IsLittleEndian) {
Array.Reverse(rawBytes); value = BitConverter.ToDouble(buffer, bufferPos);
value = BitConverter.ToDouble(rawBytes, 0); bufferPos += 8;
return true; }
else
{
byte[] rawBytes = ReadRawBytes(8);
if (!BitConverter.IsLittleEndian)
Array.Reverse(rawBytes);
value = BitConverter.ToDouble(rawBytes, 0);
}
#else #else
value = BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64()); value = BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
return true;
#endif #endif
return true;
} }
/// <summary> /// <summary>
@ -220,10 +227,18 @@ namespace Google.ProtocolBuffers
/// </summary> /// </summary>
public bool ReadFloat(ref float value) public bool ReadFloat(ref float value)
{ {
byte[] rawBytes = ReadRawBytes(4); if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos)
if (!BitConverter.IsLittleEndian) {
Array.Reverse(rawBytes); value = BitConverter.ToSingle(buffer, bufferPos);
value = BitConverter.ToSingle(rawBytes, 0); bufferPos += 4;
}
else
{
byte[] rawBytes = ReadRawBytes(4);
if (!BitConverter.IsLittleEndian)
Array.Reverse(rawBytes);
value = BitConverter.ToSingle(rawBytes, 0);
}
return true; return true;
} }

Loading…
Cancel
Save