mirror of
https://github.com/google/flatbuffers.git
synced 2026-07-01 05:51:39 +00:00
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.
This commit is contained in:
@@ -44,6 +44,12 @@ namespace FlatBuffers
|
|||||||
|
|
||||||
public int position() { return _pos; }
|
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.
|
// Helper functions for the unsafe version.
|
||||||
static public ushort ReverseBytes(ushort input)
|
static public ushort ReverseBytes(ushort input)
|
||||||
{
|
{
|
||||||
@@ -71,24 +77,44 @@ namespace FlatBuffers
|
|||||||
|
|
||||||
#if !UNSAFE_BYTEBUFFER
|
#if !UNSAFE_BYTEBUFFER
|
||||||
// Helper functions for the safe (but slower) version.
|
// 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;
|
_pos = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] ReadLittleEndian(int offset, int count)
|
protected ulong ReadLittleEndian(int offset, int count)
|
||||||
{
|
{
|
||||||
AssertOffsetAndLength(offset, count);
|
AssertOffsetAndLength(offset, count);
|
||||||
var tmp = new byte[count];
|
ulong r = 0;
|
||||||
Buffer.BlockCopy(_buffer, offset, tmp, 0, count);
|
if (BitConverter.IsLittleEndian)
|
||||||
return (BitConverter.IsLittleEndian)
|
{
|
||||||
? tmp
|
for (int i = 0; i < count; i++)
|
||||||
: tmp.Reverse().ToArray();
|
{
|
||||||
|
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
|
#endif // !UNSAFE_BYTEBUFFER
|
||||||
|
|
||||||
@@ -207,49 +233,53 @@ namespace FlatBuffers
|
|||||||
public void PutShort(int offset, short value)
|
public void PutShort(int offset, short value)
|
||||||
{
|
{
|
||||||
AssertOffsetAndLength(offset, sizeof(short));
|
AssertOffsetAndLength(offset, sizeof(short));
|
||||||
WriteLittleEndian(offset, BitConverter.GetBytes(value));
|
WriteLittleEndian(offset, sizeof(short), (ulong)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PutUshort(int offset, ushort value)
|
public void PutUshort(int offset, ushort value)
|
||||||
{
|
{
|
||||||
AssertOffsetAndLength(offset, sizeof(ushort));
|
AssertOffsetAndLength(offset, sizeof(ushort));
|
||||||
WriteLittleEndian(offset, BitConverter.GetBytes(value));
|
WriteLittleEndian(offset, sizeof(ushort), (ulong)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PutInt(int offset, int value)
|
public void PutInt(int offset, int value)
|
||||||
{
|
{
|
||||||
AssertOffsetAndLength(offset, sizeof(int));
|
AssertOffsetAndLength(offset, sizeof(int));
|
||||||
WriteLittleEndian(offset, BitConverter.GetBytes(value));
|
WriteLittleEndian(offset, sizeof(int), (ulong)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PutUint(int offset, uint value)
|
public void PutUint(int offset, uint value)
|
||||||
{
|
{
|
||||||
AssertOffsetAndLength(offset, sizeof(uint));
|
AssertOffsetAndLength(offset, sizeof(uint));
|
||||||
WriteLittleEndian(offset, BitConverter.GetBytes(value));
|
WriteLittleEndian(offset, sizeof(uint), (ulong)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PutLong(int offset, long value)
|
public void PutLong(int offset, long value)
|
||||||
{
|
{
|
||||||
AssertOffsetAndLength(offset, sizeof(long));
|
AssertOffsetAndLength(offset, sizeof(long));
|
||||||
WriteLittleEndian(offset, BitConverter.GetBytes(value));
|
WriteLittleEndian(offset, sizeof(long), (ulong)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PutUlong(int offset, ulong value)
|
public void PutUlong(int offset, ulong value)
|
||||||
{
|
{
|
||||||
AssertOffsetAndLength(offset, sizeof(ulong));
|
AssertOffsetAndLength(offset, sizeof(ulong));
|
||||||
WriteLittleEndian(offset, BitConverter.GetBytes(value));
|
WriteLittleEndian(offset, sizeof(ulong), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PutFloat(int offset, float value)
|
public void PutFloat(int offset, float value)
|
||||||
{
|
{
|
||||||
AssertOffsetAndLength(offset, sizeof(float));
|
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)
|
public void PutDouble(int offset, double value)
|
||||||
{
|
{
|
||||||
AssertOffsetAndLength(offset, sizeof(double));
|
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
|
#endif // UNSAFE_BYTEBUFFER
|
||||||
@@ -353,58 +383,49 @@ namespace FlatBuffers
|
|||||||
// Slower versions of Get* for when unsafe code is not allowed.
|
// Slower versions of Get* for when unsafe code is not allowed.
|
||||||
public short GetShort(int index)
|
public short GetShort(int index)
|
||||||
{
|
{
|
||||||
var tmp = ReadLittleEndian(index, sizeof(short));
|
return (short)ReadLittleEndian(index, sizeof(short));
|
||||||
var value = BitConverter.ToInt16(tmp, 0);
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ushort GetUshort(int index)
|
public ushort GetUshort(int index)
|
||||||
{
|
{
|
||||||
var tmp = ReadLittleEndian(index, sizeof(ushort));
|
return (ushort)ReadLittleEndian(index, sizeof(ushort));
|
||||||
var value = BitConverter.ToUInt16(tmp, 0);
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetInt(int index)
|
public int GetInt(int index)
|
||||||
{
|
{
|
||||||
var tmp = ReadLittleEndian(index, sizeof(int));
|
return (int)ReadLittleEndian(index, sizeof(int));
|
||||||
var value = BitConverter.ToInt32(tmp, 0);
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GetUint(int index)
|
public uint GetUint(int index)
|
||||||
{
|
{
|
||||||
var tmp = ReadLittleEndian(index, sizeof(uint));
|
return (uint)ReadLittleEndian(index, sizeof(uint));
|
||||||
var value = BitConverter.ToUInt32(tmp, 0);
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetLong(int index)
|
public long GetLong(int index)
|
||||||
{
|
{
|
||||||
var tmp = ReadLittleEndian(index, sizeof(long));
|
return (long)ReadLittleEndian(index, sizeof(long));
|
||||||
var value = BitConverter.ToInt64(tmp, 0);
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong GetUlong(int index)
|
public ulong GetUlong(int index)
|
||||||
{
|
{
|
||||||
var tmp = ReadLittleEndian(index, sizeof(ulong));
|
return ReadLittleEndian(index, sizeof(ulong));
|
||||||
var value = BitConverter.ToUInt64(tmp, 0);
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetFloat(int index)
|
public float GetFloat(int index)
|
||||||
{
|
{
|
||||||
var tmp = ReadLittleEndian(index, sizeof(float));
|
int i = (int)ReadLittleEndian(index, sizeof(float));
|
||||||
var value = BitConverter.ToSingle(tmp, 0);
|
inthelper[0] = i;
|
||||||
return value;
|
Buffer.BlockCopy(inthelper, 0, floathelper, 0, sizeof(float));
|
||||||
|
return floathelper[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GetDouble(int index)
|
public double GetDouble(int index)
|
||||||
{
|
{
|
||||||
var tmp = ReadLittleEndian(index, sizeof(double));
|
ulong i = ReadLittleEndian(index, sizeof(double));
|
||||||
var value = BitConverter.ToDouble(tmp, 0);
|
// There's Int64BitsToDouble but it uses unsafe code internally.
|
||||||
return value;
|
ulonghelper[0] = i;
|
||||||
|
Buffer.BlockCopy(ulonghelper, 0, doublehelper, 0, sizeof(double));
|
||||||
|
return doublehelper[0];
|
||||||
}
|
}
|
||||||
#endif // UNSAFE_BYTEBUFFER
|
#endif // UNSAFE_BYTEBUFFER
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user