diff --git a/src/DotRecast.Core/Buffers/RcRentedArray.cs b/src/DotRecast.Core/Buffers/RcRentedArray.cs index 6e6cb11..85800c5 100644 --- a/src/DotRecast.Core/Buffers/RcRentedArray.cs +++ b/src/DotRecast.Core/Buffers/RcRentedArray.cs @@ -19,6 +19,7 @@ namespace DotRecast.Core.Buffers private T[] _array; public int Length { get; } + public bool IsDisposed => null == _owner || null == _array; internal RcRentedArray(ArrayPool owner, T[] array, int length) { @@ -37,6 +38,11 @@ namespace DotRecast.Core.Buffers } } + public T[] AsArray() + { + return _array; + } + public void Dispose() { diff --git a/test/DotRecast.Core.Test/RcArrayBenchmarkTests.cs b/test/DotRecast.Core.Test/RcArrayBenchmarkTests.cs new file mode 100644 index 0000000..1296d88 --- /dev/null +++ b/test/DotRecast.Core.Test/RcArrayBenchmarkTests.cs @@ -0,0 +1,101 @@ +using System; +using System.Buffers; +using System.Collections.Generic; +using DotRecast.Core.Buffers; +using DotRecast.Core.Collections; +using NUnit.Framework; + +namespace DotRecast.Core.Test; + +public class RcArrayBenchmarkTests +{ + private const int StepLength = 512; + private const int RandomLoop = 1000; + private readonly RcRand _rand = new RcRand(); + + private (string title, long ticks) Bench(string title, Action source) + { + var begin = RcFrequency.Ticks; + for (int step = StepLength; step > 0; --step) + { + for (int i = 0; i < RandomLoop; ++i) + { + source.Invoke(step); + } + } + + var end = RcFrequency.Ticks - begin; + return (title, end); + } + + + private void RoundForArray(int len) + { + var array = new int[len]; + for (int ii = 0; ii < len; ++ii) + { + array[ii] = _rand.NextInt32(); + } + } + + + private void RoundForPureRentArray(int len) + { + var array = ArrayPool.Shared.Rent(len); + for (int ii = 0; ii < array.Length; ++ii) + { + array[ii] = _rand.NextInt32(); + } + + ArrayPool.Shared.Return(array); + } + + + private void RoundForRcRentedArray(int len) + { + using var rentedArray = RcRentedArray.Rent(len); + var array = rentedArray.AsArray(); + for (int i = 0; i < rentedArray.Length; ++i) + { + array[i] = _rand.NextInt32(); + } + } + + + private void RoundForRcStackArray(int len) + { + var array = new RcStackArray512(); + for (int ii = 0; ii < len; ++ii) + { + array[ii] = _rand.NextInt32(); + } + } + + private void RoundForStackalloc(int len) + { + Span array = stackalloc int[len]; + for (int ii = 0; ii < len; ++ii) + { + array[ii] = _rand.NextInt32(); + } + } + + + [Test] + public void TestBenchmarkArrays() + { + var list = new List<(string title, long ticks)>(); + list.Add(Bench("new int[len]", RoundForArray)); + list.Add(Bench("ArrayPool.Shared.Rent(len)", RoundForPureRentArray)); + list.Add(Bench("RcRentedArray.Rent(len)", RoundForRcRentedArray)); + list.Add(Bench("new RcStackArray512()", RoundForRcStackArray)); + list.Add(Bench("stackalloc int[len]", RoundForStackalloc)); + + list.Sort((x, y) => x.ticks.CompareTo(y.ticks)); + + foreach (var t in list) + { + Console.WriteLine($"{t.title} {t.ticks / (double)TimeSpan.TicksPerMillisecond} ms"); + } + } +} \ No newline at end of file