Skip to content

Commit

Permalink
Optimizing the big-endian binary reader/writer.
Browse files Browse the repository at this point in the history
Now requires fewer allocations.
  • Loading branch information
airbreather committed Dec 24, 2015
1 parent 0c67d84 commit c6d2ccd
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 93 deletions.
62 changes: 11 additions & 51 deletions NetTopologySuite/IO/BEBinaryReader.cs
@@ -1,8 +1,8 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using GeoAPI.IO;
using NetTopologySuite.Utilities;

namespace NetTopologySuite.IO
{
Expand Down Expand Up @@ -46,12 +46,7 @@ public class BEBinaryReader : BinaryReader
/// <exception cref="T:System.IO.EndOfStreamException">The end of the stream is reached. </exception>
public override short ReadInt16()
{
byte[] byteArray = new byte[2];
int iBytesRead = Read(byteArray, 0, 2);
Debug.Assert(iBytesRead == 2);

Array.Reverse(byteArray);
return BitConverter.ToInt16(byteArray, 0);
return BitTweaks.ReverseByteOrder(base.ReadInt16());
}

/// <summary>
Expand All @@ -67,12 +62,7 @@ public override short ReadInt16()
[CLSCompliant(false)]
public override ushort ReadUInt16()
{
byte[] byteArray = new byte[2];
int iBytesRead = Read(byteArray, 0, 2);
Debug.Assert(iBytesRead == 2);

Array.Reverse(byteArray);
return BitConverter.ToUInt16(byteArray, 0);
return BitTweaks.ReverseByteOrder(base.ReadUInt16());
}

/// <summary>
Expand All @@ -86,13 +76,8 @@ public override ushort ReadUInt16()
/// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
/// <exception cref="T:System.IO.EndOfStreamException">The end of the stream is reached. </exception>
public override int ReadInt32()
{
byte[] byteArray = new byte[4];
int iBytesRead = Read(byteArray, 0, 4);
Debug.Assert(iBytesRead == 4);

Array.Reverse(byteArray);
return BitConverter.ToInt32(byteArray, 0);
{
return BitTweaks.ReverseByteOrder(base.ReadInt32());
}

/// <summary>
Expand All @@ -108,12 +93,7 @@ public override int ReadInt32()
[CLSCompliant(false)]
public override uint ReadUInt32()
{
byte[] byteArray = new byte[4];
int iBytesRead = Read(byteArray, 0, 4);
Debug.Assert(iBytesRead == 4);

Array.Reverse(byteArray);
return BitConverter.ToUInt32(byteArray, 0);
return BitTweaks.ReverseByteOrder(base.ReadUInt32());
}

/// <summary>
Expand All @@ -128,12 +108,7 @@ public override uint ReadUInt32()
/// <exception cref="T:System.IO.EndOfStreamException">The end of the stream is reached. </exception>
public override long ReadInt64()
{
byte[] byteArray = new byte[8];
int iBytesRead = Read(byteArray, 0, 8);
Debug.Assert(iBytesRead == 8);

Array.Reverse(byteArray);
return BitConverter.ToInt64(byteArray, 0);
return BitTweaks.ReverseByteOrder(base.ReadInt64());
}


Expand All @@ -150,12 +125,7 @@ public override long ReadInt64()
[CLSCompliant(false)]
public override ulong ReadUInt64()
{
byte[] byteArray = new byte[8];
int iBytesRead = Read(byteArray, 0, 8);
Debug.Assert(iBytesRead == 8);

Array.Reverse(byteArray);
return BitConverter.ToUInt64(byteArray, 0);
return BitTweaks.ReverseByteOrder(base.ReadUInt64());
}

/// <summary>
Expand All @@ -170,12 +140,7 @@ public override ulong ReadUInt64()
/// <exception cref="T:System.IO.EndOfStreamException">The end of the stream is reached. </exception>
public override float ReadSingle()
{
byte[] byteArray = new byte[4];
int iBytesRead = Read(byteArray, 0, 4);
Debug.Assert(iBytesRead == 4);

Array.Reverse(byteArray);
return BitConverter.ToSingle(byteArray, 0);
return BitTweaks.ReverseByteOrder(base.ReadSingle());
}

/// <summary>
Expand All @@ -189,13 +154,8 @@ public override float ReadSingle()
/// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
/// <exception cref="T:System.IO.EndOfStreamException">The end of the stream is reached. </exception>
public override double ReadDouble()
{
byte[] byteArray = new byte[8];
int iBytesRead = Read(byteArray, 0, 8);
Debug.Assert(iBytesRead == 8);

Array.Reverse(byteArray);
return BitConverter.ToDouble(byteArray, 0);
{
return BitTweaks.ReverseByteOrder(base.ReadDouble());
}

/// <summary>
Expand Down
53 changes: 11 additions & 42 deletions NetTopologySuite/IO/BEBinaryWriter.cs
@@ -1,8 +1,9 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text;

using NetTopologySuite.Utilities;

namespace NetTopologySuite.IO
{

Expand Down Expand Up @@ -53,11 +54,7 @@ public class BEBinaryWriter : BinaryWriter
/// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
public override void Write(short value)
{
byte[] bytes = BitConverter.GetBytes(value);
Debug.Assert(bytes.Length == 2);

Array.Reverse(bytes, 0, 2);
Write(bytes);
base.Write(BitTweaks.ReverseByteOrder(value));
}

/// <summary>
Expand All @@ -69,12 +66,8 @@ public override void Write(short value)
/// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
[CLSCompliant(false)]
public override void Write(ushort value)
{
byte[] bytes = BitConverter.GetBytes(value);
Debug.Assert(bytes.Length == 2);

Array.Reverse(bytes, 0, 2);
Write(bytes);
{
base.Write(BitTweaks.ReverseByteOrder(value));
}

/// <summary>
Expand All @@ -86,11 +79,7 @@ public override void Write(ushort value)
/// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
public override void Write(int value)
{
byte[] bytes = BitConverter.GetBytes(value);
Debug.Assert(bytes.Length == 4);

Array.Reverse(bytes, 0, 4);
Write(bytes);
base.Write(BitTweaks.ReverseByteOrder(value));
}

/// <summary>
Expand All @@ -103,11 +92,7 @@ public override void Write(int value)
[CLSCompliant(false)]
public override void Write(uint value)
{
byte[] bytes = BitConverter.GetBytes(value);
Debug.Assert(bytes.Length == 4);

Array.Reverse(bytes, 0, 4);
Write(bytes);
base.Write(BitTweaks.ReverseByteOrder(value));
}

/// <summary>
Expand All @@ -119,11 +104,7 @@ public override void Write(uint value)
/// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
public override void Write(long value)
{
byte[] bytes = BitConverter.GetBytes(value);
Debug.Assert(bytes.Length == 8);

Array.Reverse(bytes, 0, 8);
Write(bytes);
base.Write(BitTweaks.ReverseByteOrder(value));
}

/// <summary>
Expand All @@ -136,11 +117,7 @@ public override void Write(long value)
[CLSCompliant(false)]
public override void Write(ulong value)
{
byte[] bytes = BitConverter.GetBytes(value);
Debug.Assert(bytes.Length == 8);

Array.Reverse(bytes, 0, 8);
Write(bytes);
base.Write(BitTweaks.ReverseByteOrder(value));
}

/// <summary>
Expand All @@ -152,11 +129,7 @@ public override void Write(ulong value)
/// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
public override void Write(float value)
{
byte[] bytes = BitConverter.GetBytes(value);
Debug.Assert(bytes.Length == 4);

Array.Reverse(bytes, 0, 4);
Write(bytes);
base.Write(BitTweaks.ReverseByteOrder(value));
}

/// <summary>
Expand All @@ -168,11 +141,7 @@ public override void Write(float value)
/// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
public override void Write(double value)
{
byte[] bytes = BitConverter.GetBytes(value);
Debug.Assert(bytes.Length == 8);

Array.Reverse(bytes, 0, 8);
Write(bytes);
base.Write(BitTweaks.ReverseByteOrder(value));
}

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions NetTopologySuite/NetTopologySuite.csproj
Expand Up @@ -491,6 +491,7 @@
<Compile Include="Utilities\Assert.cs" />
<Compile Include="Utilities\AssertionFailedException.cs" />
<Compile Include="Utilities\BitConverter.cs" />
<Compile Include="Utilities\BitTweaks.cs" />
<Compile Include="Utilities\Caster.cs" />
<Compile Include="Utilities\CollectionUtil.cs" />
<Compile Include="Utilities\CoordinateArrayFilter.cs" />
Expand Down
83 changes: 83 additions & 0 deletions NetTopologySuite/Utilities/BitTweaks.cs
@@ -0,0 +1,83 @@
using System;
using System.Diagnostics;

#if PCL
using DoubleBitsConverter = NetTopologySuite.Utilities.BitConverter;
#else
using DoubleBitsConverter = System.BitConverter;
#endif

namespace NetTopologySuite.Utilities
{
internal static class BitTweaks
{
internal static short ReverseByteOrder(short value)
{
unchecked
{
return (short)ReverseByteOrder((ushort)value);
}
}

internal static int ReverseByteOrder(int value)
{
unchecked
{
return (int)ReverseByteOrder((uint)value);
}
}

internal static long ReverseByteOrder(long value)
{
unchecked
{
return (long)ReverseByteOrder((ulong)value);
}
}

internal static float ReverseByteOrder(float value)
{
// TODO: BitConverter.SingleToInt32Bits will exist eventually
// see https://github.com/dotnet/coreclr/pull/833
byte[] bytes = System.BitConverter.GetBytes(value);
Debug.Assert(bytes.Length == 4);

Array.Reverse(bytes, 0, 4);
return System.BitConverter.ToSingle(bytes, 0);
}

internal static double ReverseByteOrder(double value)
{
return DoubleBitsConverter.Int64BitsToDouble(ReverseByteOrder(DoubleBitsConverter.DoubleToInt64Bits(value)));
}

internal static ushort ReverseByteOrder(ushort value)
{
unchecked
{
return (ushort)((value & 0x00FF) << 8 |
(value & 0xFF00) >> 8);
}
}

internal static uint ReverseByteOrder(uint value)
{
return (value & 0x000000FF) << 24 |
(value & 0x0000FF00) << 8 |
(value & 0x00FF0000) >> 8 |
(value & 0xFF000000) >> 24;
}

internal static ulong ReverseByteOrder(ulong value)
{
return (value & 0x00000000000000FF) << 56 |
(value & 0x000000000000FF00) << 40 |
(value & 0x0000000000FF0000) << 24 |
(value & 0x00000000FF000000) << 8 |
(value & 0x000000FF00000000) >> 8 |
(value & 0x0000FF0000000000) >> 24 |
(value & 0x00FF000000000000) >> 40 |
(value & 0xFF00000000000000) >> 56;
}
}
}
Expand Up @@ -1271,6 +1271,9 @@
<Compile Include="..\..\NetTopologySuite\Utilities\BitConverter.cs">
<Link>Utilities\BitConverter.cs</Link>
</Compile>
<Compile Include="..\..\NetTopologySuite\Utilities\BitTweaks.cs">
<Link>Utilities\BitTweaks.cs</Link>
</Compile>
<Compile Include="..\..\NetTopologySuite\Utilities\Caster.cs">
<Link>Utilities\Caster.cs</Link>
</Compile>
Expand Down

0 comments on commit c6d2ccd

Please sign in to comment.