diff --git a/src/DotRecast.Core/Buffers/RcCyclicBuffer.cs b/src/DotRecast.Core/Buffers/RcCyclicBuffer.cs new file mode 100644 index 0000000..0dc6ffd --- /dev/null +++ b/src/DotRecast.Core/Buffers/RcCyclicBuffer.cs @@ -0,0 +1,48 @@ +using System; + +namespace DotRecast.Core.Buffers +{ + public class RcCyclicBuffer + { + public int MinIndex { get; private set; } + public int MaxIndex { get; private set; } + public int Count => MaxIndex - MinIndex + 1; + public readonly int Size; + + public T this[int index] => Get(index); + + private readonly T[] _buffer; + + public RcCyclicBuffer(in int size) + { + _buffer = new T[size]; + Size = size; + MinIndex = 0; + MaxIndex = -1; + } + + public void Add(in T item) + { + MaxIndex++; + var index = MaxIndex % Size; + + if (MaxIndex >= Size) + MinIndex = MaxIndex - Size + 1; + + _buffer[index] = item; + } + + public T Get(in int index) + { + if (index < MinIndex || index > MaxIndex) + throw new ArgumentOutOfRangeException(); + + return _buffer[index % Size]; + } + + public Span AsSpan() + { + return _buffer.AsSpan(0, Count); + } + } +} \ No newline at end of file diff --git a/src/DotRecast.Detour.Crowd/DtCrowdTelemetry.cs b/src/DotRecast.Detour.Crowd/DtCrowdTelemetry.cs index aadfb79..dbc3086 100644 --- a/src/DotRecast.Detour.Crowd/DtCrowdTelemetry.cs +++ b/src/DotRecast.Detour.Crowd/DtCrowdTelemetry.cs @@ -23,6 +23,7 @@ using System.Diagnostics; using System.Linq; using System.Reflection.Emit; using DotRecast.Core; +using DotRecast.Core.Buffers; using DotRecast.Core.Numerics; namespace DotRecast.Detour.Crowd @@ -34,7 +35,7 @@ namespace DotRecast.Detour.Crowd private float _maxTimeToFindPath; private readonly Dictionary _executionTimings = new Dictionary(); - private readonly Dictionary> _executionTimingSamples = new Dictionary>(); + private readonly Dictionary> _executionTimingSamples = new Dictionary>(); public float MaxTimeToEnqueueRequest() { @@ -87,17 +88,23 @@ namespace DotRecast.Detour.Crowd long duration = RcFrequency.Ticks - _executionTimings[name]; if (!_executionTimingSamples.TryGetValue(name, out var s)) { - s = new List(); + s = new RcCyclicBuffer(TIMING_SAMPLES); _executionTimingSamples.Add(name, s); } - if (s.Count == TIMING_SAMPLES) + s.Add(duration); + _executionTimings[name] = CalculateAverage(s.AsSpan()); + } + + private static long CalculateAverage(Span buffer) + { + long sum = 0L; + foreach (var item in buffer) { - s.RemoveAt(0); + sum += item; } - s.Add(duration); - _executionTimings[name] = (long)s.Average(); + return sum / buffer.Length; } } } \ No newline at end of file