forked from bit/DotRecastNetSim
Compare commits
4 Commits
pr/accepta
...
main
Author | SHA1 | Date |
---|---|---|
ikpil | b81a5923a3 | |
ikpil | 3fbfb968d0 | |
ikpil | 3c4723c907 | |
ikpil | 7836b78bb4 |
|
@ -6,7 +6,7 @@ namespace DotRecast.Core.Buffers
|
|||
{
|
||||
public static class RcRentedArray
|
||||
{
|
||||
public static RcRentedArray<T> RentDisposableArray<T>(int minimumLength)
|
||||
public static RcRentedArray<T> Rent<T>(int minimumLength)
|
||||
{
|
||||
var array = ArrayPool<T>.Shared.Rent(minimumLength);
|
||||
return new RcRentedArray<T>(ArrayPool<T>.Shared, array, minimumLength);
|
||||
|
@ -17,44 +17,41 @@ namespace DotRecast.Core.Buffers
|
|||
{
|
||||
private ArrayPool<T> _owner;
|
||||
private T[] _array;
|
||||
private readonly RcAtomicInteger _disposed;
|
||||
|
||||
public int Length { get; }
|
||||
public bool IsDisposed => null == _owner || null == _array;
|
||||
|
||||
internal RcRentedArray(ArrayPool<T> owner, T[] array, int length)
|
||||
{
|
||||
_owner = owner;
|
||||
_array = array;
|
||||
Length = length;
|
||||
_disposed = new RcAtomicInteger(0);
|
||||
}
|
||||
|
||||
public T this[int index]
|
||||
public ref T this[int index]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
RcThrowHelper.ThrowExceptionIfIndexOutOfRange(index, Length);
|
||||
return _array[index];
|
||||
return ref _array[index];
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set
|
||||
public T[] AsArray()
|
||||
{
|
||||
RcThrowHelper.ThrowExceptionIfIndexOutOfRange(index, Length);
|
||||
_array[index] = value;
|
||||
}
|
||||
return _array;
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (1 != _disposed.IncrementAndGet())
|
||||
return;
|
||||
|
||||
_owner?.Return(_array, true);
|
||||
_array = null;
|
||||
if (null != _owner && null != _array)
|
||||
{
|
||||
_owner.Return(_array, true);
|
||||
_owner = null;
|
||||
_array = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -168,7 +168,7 @@ namespace DotRecast.Detour.Crowd
|
|||
}
|
||||
|
||||
// Allocate temp buffer for merging paths.
|
||||
_maxPathResult = 256;
|
||||
_maxPathResult = DtCrowdConst.MAX_PATH_RESULT;
|
||||
_pathQ = new DtPathQueue(config);
|
||||
_agents = new List<DtCrowdAgent>();
|
||||
|
||||
|
|
|
@ -30,5 +30,6 @@
|
|||
public const int MAX_ITERS_PER_UPDATE = 100;
|
||||
public const int MAX_PATHQUEUE_NODES = 4096;
|
||||
public const int MAX_COMMON_NODES = 512;
|
||||
public const int MAX_PATH_RESULT = 256;
|
||||
}
|
||||
}
|
|
@ -215,7 +215,7 @@ namespace DotRecast.Detour.Crowd
|
|||
{
|
||||
if (res.Count > 1 && t > 0.99f)
|
||||
{
|
||||
m_path = DtPathUtils.MergeCorridorStartShortcut(m_path, m_maxPath, res);
|
||||
m_path = DtPathUtils.MergeCorridorStartShortcut(m_path, m_path.Count, m_maxPath, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -241,13 +241,13 @@ namespace DotRecast.Detour.Crowd
|
|||
}
|
||||
|
||||
var res = new List<long>();
|
||||
navquery.InitSlicedFindPath(m_path[0], m_path[m_path.Count - 1], m_pos, m_target, filter, 0);
|
||||
navquery.InitSlicedFindPath(m_path[0], m_path[^1], m_pos, m_target, filter, 0);
|
||||
navquery.UpdateSlicedFindPath(maxIterations, out var _);
|
||||
var status = navquery.FinalizeSlicedFindPathPartial(m_path, ref res);
|
||||
|
||||
if (status.Succeeded() && res.Count > 0)
|
||||
{
|
||||
m_path = DtPathUtils.MergeCorridorStartShortcut(m_path, m_maxPath, res);
|
||||
m_path = DtPathUtils.MergeCorridorStartShortcut(m_path, m_path.Count, m_maxPath, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -316,7 +316,7 @@ namespace DotRecast.Detour.Crowd
|
|||
var status = navquery.MoveAlongSurface(m_path[0], m_pos, npos, filter, out var result, ref visited);
|
||||
if (status.Succeeded())
|
||||
{
|
||||
m_path = DtPathUtils.MergeCorridorStartMoved(m_path, m_maxPath, visited);
|
||||
m_path = DtPathUtils.MergeCorridorStartMoved(m_path, m_path.Count, m_maxPath, visited);
|
||||
|
||||
// Adjust the position to stay on top of the navmesh.
|
||||
m_pos = result;
|
||||
|
@ -355,10 +355,10 @@ namespace DotRecast.Detour.Crowd
|
|||
{
|
||||
// Move along navmesh and update new position.
|
||||
var visited = new List<long>();
|
||||
var status = navquery.MoveAlongSurface(m_path[m_path.Count - 1], m_target, npos, filter, out var result, ref visited);
|
||||
var status = navquery.MoveAlongSurface(m_path[^1], m_target, npos, filter, out var result, ref visited);
|
||||
if (status.Succeeded())
|
||||
{
|
||||
m_path = DtPathUtils.MergeCorridorEndMoved(m_path, m_maxPath, visited);
|
||||
m_path = DtPathUtils.MergeCorridorEndMoved(m_path, m_path.Count, m_maxPath, visited);
|
||||
// TODO: should we do that?
|
||||
// Adjust the position to stay on top of the navmesh.
|
||||
/*
|
||||
|
|
|
@ -141,7 +141,7 @@ namespace DotRecast.Detour
|
|||
return path;
|
||||
}
|
||||
|
||||
public static List<long> MergeCorridorStartMoved(List<long> path, int maxPath, List<long> visited)
|
||||
public static List<long> MergeCorridorStartMoved(List<long> path, int npath, int maxPath, List<long> visited)
|
||||
{
|
||||
int furthestPath = -1;
|
||||
int furthestVisited = -1;
|
||||
|
@ -186,7 +186,7 @@ namespace DotRecast.Detour
|
|||
return result;
|
||||
}
|
||||
|
||||
public static List<long> MergeCorridorEndMoved(List<long> path, int maxPath, List<long> visited)
|
||||
public static List<long> MergeCorridorEndMoved(List<long> path, int npath, int maxPath, List<long> visited)
|
||||
{
|
||||
int furthestPath = -1;
|
||||
int furthestVisited = -1;
|
||||
|
@ -223,7 +223,7 @@ namespace DotRecast.Detour
|
|||
return result;
|
||||
}
|
||||
|
||||
public static List<long> MergeCorridorStartShortcut(List<long> path, int maxPath, List<long> visited)
|
||||
public static List<long> MergeCorridorStartShortcut(List<long> path, int npath, int maxPath, List<long> visited)
|
||||
{
|
||||
int furthestPath = -1;
|
||||
int furthestVisited = -1;
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
|||
|
||||
iterPos = result;
|
||||
|
||||
pathIterPolys = DtPathUtils.MergeCorridorStartMoved(pathIterPolys, MAX_POLYS, visited);
|
||||
pathIterPolys = DtPathUtils.MergeCorridorStartMoved(pathIterPolys, pathIterPolys.Count, MAX_POLYS, visited);
|
||||
pathIterPolys = DtPathUtils.FixupShortcuts(pathIterPolys, navQuery);
|
||||
|
||||
var status = navQuery.GetPolyHeight(pathIterPolys[0], result, out var h);
|
||||
|
|
|
@ -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<int> 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<int>.Shared.Rent(len);
|
||||
for (int ii = 0; ii < array.Length; ++ii)
|
||||
{
|
||||
array[ii] = _rand.NextInt32();
|
||||
}
|
||||
|
||||
ArrayPool<int>.Shared.Return(array);
|
||||
}
|
||||
|
||||
|
||||
private void RoundForRcRentedArray(int len)
|
||||
{
|
||||
using var rentedArray = RcRentedArray.Rent<int>(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<int>();
|
||||
for (int ii = 0; ii < len; ++ii)
|
||||
{
|
||||
array[ii] = _rand.NextInt32();
|
||||
}
|
||||
}
|
||||
|
||||
private void RoundForStackalloc(int len)
|
||||
{
|
||||
Span<int> 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<int>.Shared.Rent(len)", RoundForPureRentArray));
|
||||
list.Add(Bench("RcRentedArray.Rent<int>(len)", RoundForRcRentedArray));
|
||||
list.Add(Bench("new RcStackArray512<int>()", 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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ public class RcRentedArrayTest
|
|||
{
|
||||
int length = Math.Max(2, (int)(rand.Next() * 2048));
|
||||
var values = RandomValues(length);
|
||||
using var array = RcRentedArray.RentDisposableArray<int>(length);
|
||||
using var array = RcRentedArray.Rent<int>(length);
|
||||
|
||||
for (int i = 0; i < array.Length; ++i)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue