From 4802e8a285e20a1403c6570690ea02813c967f0b Mon Sep 17 00:00:00 2001 From: Oli Wilkinson Date: Mon, 14 Dec 2015 19:55:10 -0500 Subject: [PATCH] C# added BYTEBUFFER_NO_BOUNDS_CHECK #define Removes the bounds checking on the ByteBuffer Get/Put operations. Can be dangerous when used with UNSAFE_BYTEBUFFER but results in increased performance. Use at your own risk! --- net/FlatBuffers/ByteBuffer.cs | 22 +++++++++++++++++----- tests/FlatBuffers.Test/ByteBufferTests.cs | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/net/FlatBuffers/ByteBuffer.cs b/net/FlatBuffers/ByteBuffer.cs index 37779b593..3dd21a2bf 100755 --- a/net/FlatBuffers/ByteBuffer.cs +++ b/net/FlatBuffers/ByteBuffer.cs @@ -14,7 +14,20 @@ * limitations under the License. */ -//#define UNSAFE_BYTEBUFFER // uncomment this line to use faster ByteBuffer +// There are 2 #defines that have an impact on performance of this ByteBuffer implementation +// +// UNSAFE_BYTEBUFFER +// This will use unsafe code to manipulate the underlying byte array. This +// can yield a reasonable performance increase. +// +// BYTEBUFFER_NO_BOUNDS_CHECK +// This will disable the bounds check asserts to the byte array. This can +// yield a small performance gain in normal code.. +// +// Using UNSAFE_BYTEBUFFER and BYTEBUFFER_NO_BOUNDS_CHECK together can yield a +// performance gain of ~15% for some operations, however doing so is potentially +// dangerous. Do so at your own risk! +// using System; @@ -22,9 +35,6 @@ namespace FlatBuffers { /// /// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers. - /// If your execution environment allows unsafe code, you should enable - /// unsafe code in your project and #define UNSAFE_BYTEBUFFER to use a - /// MUCH faster version of ByteBuffer. /// public class ByteBuffer { @@ -126,12 +136,15 @@ namespace FlatBuffers } #endif // !UNSAFE_BYTEBUFFER + private void AssertOffsetAndLength(int offset, int length) { + #if !BYTEBUFFER_NO_BOUNDS_CHECK if (offset < 0 || offset >= _buffer.Length || offset + length > _buffer.Length) throw new ArgumentOutOfRangeException(); + #endif } public void PutSbyte(int offset, sbyte value) @@ -201,7 +214,6 @@ namespace FlatBuffers public unsafe void PutUlong(int offset, ulong value) { AssertOffsetAndLength(offset, sizeof(ulong)); - fixed (byte* ptr = _buffer) { *(ulong*)(ptr + offset) = BitConverter.IsLittleEndian diff --git a/tests/FlatBuffers.Test/ByteBufferTests.cs b/tests/FlatBuffers.Test/ByteBufferTests.cs index 0241e96e2..5becbcc26 100644 --- a/tests/FlatBuffers.Test/ByteBufferTests.cs +++ b/tests/FlatBuffers.Test/ByteBufferTests.cs @@ -40,6 +40,7 @@ namespace FlatBuffers.Test Assert.AreEqual((byte)99, buffer[0]); } +#if !BYTEBUFFER_NO_BOUNDS_CHECK [FlatBuffersTestMethod] public void ByteBuffer_PutByteCannotPutAtOffsetPastLength() { @@ -47,6 +48,7 @@ namespace FlatBuffers.Test var uut = new ByteBuffer(buffer); Assert.Throws(() => uut.PutByte(1, 99)); } +#endif [FlatBuffersTestMethod] public void ByteBuffer_PutShortPopulatesBufferCorrectly() @@ -60,6 +62,7 @@ namespace FlatBuffers.Test Assert.AreEqual((byte)0, buffer[1]); } +#if !BYTEBUFFER_NO_BOUNDS_CHECK [FlatBuffersTestMethod] public void ByteBuffer_PutShortCannotPutAtOffsetPastLength() { @@ -67,7 +70,9 @@ namespace FlatBuffers.Test var uut = new ByteBuffer(buffer); Assert.Throws(() => uut.PutShort(2, 99)); } +#endif +#if !BYTEBUFFER_NO_BOUNDS_CHECK [FlatBuffersTestMethod] public void ByteBuffer_PutShortChecksLength() { @@ -83,6 +88,7 @@ namespace FlatBuffers.Test var uut = new ByteBuffer(buffer); Assert.Throws(() => uut.PutShort(1, 99)); } +#endif [FlatBuffersTestMethod] public void ByteBuffer_PutIntPopulatesBufferCorrectly() @@ -98,6 +104,7 @@ namespace FlatBuffers.Test Assert.AreEqual(0x0A, buffer[3]); } + #if !BYTEBUFFER_NO_BOUNDS_CHECK [FlatBuffersTestMethod] public void ByteBuffer_PutIntCannotPutAtOffsetPastLength() { @@ -121,6 +128,7 @@ namespace FlatBuffers.Test var uut = new ByteBuffer(buffer); Assert.Throws(() => uut.PutInt(2, 0x0A0B0C0D)); } +#endif [FlatBuffersTestMethod] public void ByteBuffer_PutLongPopulatesBufferCorrectly() @@ -140,6 +148,7 @@ namespace FlatBuffers.Test Assert.AreEqual(0x01, buffer[7]); } +#if !BYTEBUFFER_NO_BOUNDS_CHECK [FlatBuffersTestMethod] public void ByteBuffer_PutLongCannotPutAtOffsetPastLength() { @@ -163,6 +172,7 @@ namespace FlatBuffers.Test var uut = new ByteBuffer(buffer); Assert.Throws(() => uut.PutLong(2, 0x010203040A0B0C0D)); } +#endif [FlatBuffersTestMethod] public void ByteBuffer_GetByteReturnsCorrectData() @@ -173,6 +183,7 @@ namespace FlatBuffers.Test Assert.AreEqual((byte)99, uut.Get(0)); } +#if !BYTEBUFFER_NO_BOUNDS_CHECK [FlatBuffersTestMethod] public void ByteBuffer_GetByteChecksOffset() { @@ -180,6 +191,7 @@ namespace FlatBuffers.Test var uut = new ByteBuffer(buffer); Assert.Throws(()=>uut.Get(1)); } +#endif [FlatBuffersTestMethod] public void ByteBuffer_GetShortReturnsCorrectData() @@ -191,6 +203,7 @@ namespace FlatBuffers.Test Assert.AreEqual(1, uut.GetShort(0)); } +#if !BYTEBUFFER_NO_BOUNDS_CHECK [FlatBuffersTestMethod] public void ByteBuffer_GetShortChecksOffset() { @@ -206,6 +219,7 @@ namespace FlatBuffers.Test var uut = new ByteBuffer(buffer); Assert.Throws(() => uut.GetShort(1)); } +#endif [FlatBuffersTestMethod] public void ByteBuffer_GetIntReturnsCorrectData() @@ -219,6 +233,7 @@ namespace FlatBuffers.Test Assert.AreEqual(0x0A0B0C0D, uut.GetInt(0)); } +#if !BYTEBUFFER_NO_BOUNDS_CHECK [FlatBuffersTestMethod] public void ByteBuffer_GetIntChecksOffset() { @@ -234,6 +249,7 @@ namespace FlatBuffers.Test var uut = new ByteBuffer(buffer); Assert.Throws(() => uut.GetInt(0)); } +#endif [FlatBuffersTestMethod] public void ByteBuffer_GetLongReturnsCorrectData() @@ -251,6 +267,7 @@ namespace FlatBuffers.Test Assert.AreEqual(0x010203040A0B0C0D, uut.GetLong(0)); } +#if !BYTEBUFFER_NO_BOUNDS_CHECK [FlatBuffersTestMethod] public void ByteBuffer_GetLongChecksOffset() { @@ -266,6 +283,7 @@ namespace FlatBuffers.Test var uut = new ByteBuffer(buffer); Assert.Throws(() => uut.GetLong(0)); } +#endif [FlatBuffersTestMethod] public void ByteBuffer_ReverseBytesUshort()