Compare commits

...

3 Commits

Author SHA1 Message Date
wrenge 592ecebe1e Proximity grid list reuse 2024-11-13 13:25:13 +03:00
wrenge b2a217d4a3 Object pool 2024-11-13 13:21:41 +03:00
wrenge 5c0ba9dba1 Reuse grid instead of creating new 2024-11-13 13:14:32 +03:00
3 changed files with 39 additions and 3 deletions

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
namespace DotRecast.Core.Buffers
{
// This implementation is thread unsafe
public class RcObjectPool<T> where T : class
{
private readonly Queue<T> _items = new Queue<T>();
private readonly Func<T> _createFunc;
public RcObjectPool(Func<T> createFunc)
{
_createFunc = createFunc;
}
public T Get()
{
if (_items.TryDequeue(out var result))
return result;
return _createFunc();
}
public void Return(T obj)
{
_items.Enqueue(obj);
}
}
}

View File

@ -129,7 +129,7 @@ namespace DotRecast.Detour.Crowd
private readonly DtObstacleAvoidanceParams[] _obstacleQueryParams; private readonly DtObstacleAvoidanceParams[] _obstacleQueryParams;
private readonly DtObstacleAvoidanceQuery _obstacleQuery; private readonly DtObstacleAvoidanceQuery _obstacleQuery;
private DtProximityGrid _grid; private readonly DtProximityGrid _grid;
private int _maxPathResult; private int _maxPathResult;
private readonly RcVec3f _agentPlacementHalfExtents; private readonly RcVec3f _agentPlacementHalfExtents;
@ -174,6 +174,7 @@ namespace DotRecast.Detour.Crowd
_agentIdx = new RcAtomicInteger(0); _agentIdx = new RcAtomicInteger(0);
_agents = new Dictionary<int, DtCrowdAgent>(); _agents = new Dictionary<int, DtCrowdAgent>();
_activeAgents = new List<DtCrowdAgent>(); _activeAgents = new List<DtCrowdAgent>();
_grid = new DtProximityGrid(_config.maxAgentRadius * 3);
// The navQuery is mostly used for local searches, no need for large node pool. // The navQuery is mostly used for local searches, no need for large node pool.
SetNavMesh(nav); SetNavMesh(nav);
@ -864,7 +865,7 @@ namespace DotRecast.Detour.Crowd
{ {
using var timer = _telemetry.ScopedTimer(DtCrowdTimerLabel.BuildProximityGrid); using var timer = _telemetry.ScopedTimer(DtCrowdTimerLabel.BuildProximityGrid);
_grid = new DtProximityGrid(_config.maxAgentRadius * 3); _grid.Clear();
for (var i = 0; i < agents.Count; i++) for (var i = 0; i < agents.Count; i++)
{ {

View File

@ -22,6 +22,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using DotRecast.Core.Buffers;
namespace DotRecast.Detour.Crowd namespace DotRecast.Detour.Crowd
{ {
@ -30,12 +31,14 @@ namespace DotRecast.Detour.Crowd
private readonly float _cellSize; private readonly float _cellSize;
private readonly float _invCellSize; private readonly float _invCellSize;
private readonly Dictionary<long, List<DtCrowdAgent>> _items; private readonly Dictionary<long, List<DtCrowdAgent>> _items;
private readonly RcObjectPool<List<DtCrowdAgent>> _listPool;
public DtProximityGrid(float cellSize) public DtProximityGrid(float cellSize)
{ {
_cellSize = cellSize; _cellSize = cellSize;
_invCellSize = 1.0f / cellSize; _invCellSize = 1.0f / cellSize;
_items = new Dictionary<long, List<DtCrowdAgent>>(); _items = new Dictionary<long, List<DtCrowdAgent>>();
_listPool = new RcObjectPool<List<DtCrowdAgent>>(() => new List<DtCrowdAgent>());
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -57,6 +60,8 @@ namespace DotRecast.Detour.Crowd
public void Clear() public void Clear()
{ {
foreach (var pair in _items)
_listPool.Return(pair.Value);
_items.Clear(); _items.Clear();
} }
@ -74,7 +79,7 @@ namespace DotRecast.Detour.Crowd
long key = CombineKey(x, y); long key = CombineKey(x, y);
if (!_items.TryGetValue(key, out var ids)) if (!_items.TryGetValue(key, out var ids))
{ {
ids = new List<DtCrowdAgent>(); ids = _listPool.Get();
_items.Add(key, ids); _items.Add(key, ids);
} }