summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorWouter van Oortmerssen <wvo@google.com>2015-03-13 16:59:29 -0700
committerWouter van Oortmerssen <wvo@google.com>2015-03-13 16:59:29 -0700
commitf7818d83d7f04f4ca1ef85764812740f9dd08ff6 (patch)
tree083c911a1975e960a7d02c01c640594ce0a352d5 /net
parent7ef2fc251735f019a21b5e0aa88053a1faffd7c7 (diff)
downloadflatbuffers-f7818d83d7f04f4ca1ef85764812740f9dd08ff6.tar.gz
flatbuffers-f7818d83d7f04f4ca1ef85764812740f9dd08ff6.tar.bz2
flatbuffers-f7818d83d7f04f4ca1ef85764812740f9dd08ff6.zip
Changed C# ByteBuffer to use bit shifts instead of BitConverter
BitConverter was excessively slow since it allocates a byte array at each access. Bug: 18702381 Change-Id: I47be9c38e1d04287ba4c10bc369848f3e13a2a2f Tested: on Windows.
Diffstat (limited to 'net')
-rwxr-xr-xnet/FlatBuffers/ByteBuffer.cs105
1 files changed, 63 insertions, 42 deletions
diff --git a/net/FlatBuffers/ByteBuffer.cs b/net/FlatBuffers/ByteBuffer.cs
index b591b74b..ee79b1c9 100755
--- a/net/FlatBuffers/ByteBuffer.cs
+++ b/net/FlatBuffers/ByteBuffer.cs
@@ -44,6 +44,12 @@ namespace FlatBuffers
public int position() { return _pos; }
+ // Pre-allocated helper arrays for convertion.
+ private float[] floathelper = new[] { 0.0f };
+ private int[] inthelper = new[] { 0 };
+ private double[] doublehelper = new[] { 0.0 };
+ private ulong[] ulonghelper = new[] { 0UL };
+
// Helper functions for the unsafe version.
static public ushort ReverseBytes(ushort input)
{
@@ -71,24 +77,44 @@ namespace FlatBuffers
#if !UNSAFE_BYTEBUFFER
// Helper functions for the safe (but slower) version.
- protected void WriteLittleEndian(int offset, byte[] data)
+ protected void WriteLittleEndian(int offset, int count, ulong data)
{
- if (!BitConverter.IsLittleEndian)
+ if (BitConverter.IsLittleEndian)
{
- Array.Reverse(data, 0, data.Length);
+ for (int i = 0; i < count; i++)
+ {
+ _buffer[offset + i] = (byte)(data >> i * 8);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < count; i++)
+ {
+ _buffer[offset + count - 1 - i] = (byte)(data >> i * 8);
+ }
}
- Buffer.BlockCopy(data, 0, _buffer, offset, data.Length);
_pos = offset;
}
- protected byte[] ReadLittleEndian(int offset, int count)
+ protected ulong ReadLittleEndian(int offset, int count)
{
AssertOffsetAndLength(offset, count);
- var tmp = new byte[count];
- Buffer.BlockCopy(_buffer, offset, tmp, 0, count);
- return (BitConverter.IsLittleEndian)
- ? tmp
- : tmp.Reverse().ToArray();
+ ulong r = 0;
+ if (BitConverter.IsLittleEndian)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ r |= (ulong)_buffer[offset + i] << i * 8;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < count; i++)
+ {
+ r |= (ulong)_buffer[offset + count - 1 - i] << i * 8;
+ }
+ }
+ return r;
}
#endif // !UNSAFE_BYTEBUFFER
@@ -207,49 +233,53 @@ namespace FlatBuffers
public void PutShort(int offset, short value)
{
AssertOffsetAndLength(offset, sizeof(short));
- WriteLittleEndian(offset, BitConverter.GetBytes(value));
+ WriteLittleEndian(offset, sizeof(short), (ulong)value);
}
public void PutUshort(int offset, ushort value)
{
AssertOffsetAndLength(offset, sizeof(ushort));
- WriteLittleEndian(offset, BitConverter.GetBytes(value));
+ WriteLittleEndian(offset, sizeof(ushort), (ulong)value);
}
public void PutInt(int offset, int value)
{
AssertOffsetAndLength(offset, sizeof(int));
- WriteLittleEndian(offset, BitConverter.GetBytes(value));
+ WriteLittleEndian(offset, sizeof(int), (ulong)value);
}
public void PutUint(int offset, uint value)
{
AssertOffsetAndLength(offset, sizeof(uint));
- WriteLittleEndian(offset, BitConverter.GetBytes(value));
+ WriteLittleEndian(offset, sizeof(uint), (ulong)value);
}
public void PutLong(int offset, long value)
{
AssertOffsetAndLength(offset, sizeof(long));
- WriteLittleEndian(offset, BitConverter.GetBytes(value));
+ WriteLittleEndian(offset, sizeof(long), (ulong)value);
}
public void PutUlong(int offset, ulong value)
{
AssertOffsetAndLength(offset, sizeof(ulong));
- WriteLittleEndian(offset, BitConverter.GetBytes(value));
+ WriteLittleEndian(offset, sizeof(ulong), value);
}
public void PutFloat(int offset, float value)
{
AssertOffsetAndLength(offset, sizeof(float));
- WriteLittleEndian(offset, BitConverter.GetBytes(value));
+ floathelper[0] = value;
+ Buffer.BlockCopy(floathelper, 0, inthelper, 0, sizeof(float));
+ WriteLittleEndian(offset, sizeof(float), (ulong)inthelper[0]);
}
public void PutDouble(int offset, double value)
{
AssertOffsetAndLength(offset, sizeof(double));
- WriteLittleEndian(offset, BitConverter.GetBytes(value));
+ doublehelper[0] = value;
+ Buffer.BlockCopy(doublehelper, 0, ulonghelper, 0, sizeof(double));
+ WriteLittleEndian(offset, sizeof(double), ulonghelper[0]);
}
#endif // UNSAFE_BYTEBUFFER
@@ -353,58 +383,49 @@ namespace FlatBuffers
// Slower versions of Get* for when unsafe code is not allowed.
public short GetShort(int index)
{
- var tmp = ReadLittleEndian(index, sizeof(short));
- var value = BitConverter.ToInt16(tmp, 0);
- return value;
+ return (short)ReadLittleEndian(index, sizeof(short));
}
public ushort GetUshort(int index)
{
- var tmp = ReadLittleEndian(index, sizeof(ushort));
- var value = BitConverter.ToUInt16(tmp, 0);
- return value;
+ return (ushort)ReadLittleEndian(index, sizeof(ushort));
}
public int GetInt(int index)
{
- var tmp = ReadLittleEndian(index, sizeof(int));
- var value = BitConverter.ToInt32(tmp, 0);
- return value;
+ return (int)ReadLittleEndian(index, sizeof(int));
}
public uint GetUint(int index)
{
- var tmp = ReadLittleEndian(index, sizeof(uint));
- var value = BitConverter.ToUInt32(tmp, 0);
- return value;
+ return (uint)ReadLittleEndian(index, sizeof(uint));
}
public long GetLong(int index)
{
- var tmp = ReadLittleEndian(index, sizeof(long));
- var value = BitConverter.ToInt64(tmp, 0);
- return value;
+ return (long)ReadLittleEndian(index, sizeof(long));
}
public ulong GetUlong(int index)
{
- var tmp = ReadLittleEndian(index, sizeof(ulong));
- var value = BitConverter.ToUInt64(tmp, 0);
- return value;
+ return ReadLittleEndian(index, sizeof(ulong));
}
public float GetFloat(int index)
{
- var tmp = ReadLittleEndian(index, sizeof(float));
- var value = BitConverter.ToSingle(tmp, 0);
- return value;
+ int i = (int)ReadLittleEndian(index, sizeof(float));
+ inthelper[0] = i;
+ Buffer.BlockCopy(inthelper, 0, floathelper, 0, sizeof(float));
+ return floathelper[0];
}
public double GetDouble(int index)
{
- var tmp = ReadLittleEndian(index, sizeof(double));
- var value = BitConverter.ToDouble(tmp, 0);
- return value;
+ ulong i = ReadLittleEndian(index, sizeof(double));
+ // There's Int64BitsToDouble but it uses unsafe code internally.
+ ulonghelper[0] = i;
+ Buffer.BlockCopy(ulonghelper, 0, doublehelper, 0, sizeof(double));
+ return doublehelper[0];
}
#endif // UNSAFE_BYTEBUFFER
}