Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions RLBotCS/ManagerTools/CircularBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ namespace RLBotCS.ManagerTools;

public class CircularBuffer<T>
{
private int _startIndex;
private int _currentIndex;
private int _size = 0;
private int _currentIndex = 0;
private readonly T[] _buffer;

public int Count => (_currentIndex - _startIndex + _buffer.Length) % _buffer.Length;
public int Count => _buffer.Length;

public CircularBuffer(int capacity)
{
Expand All @@ -16,16 +16,13 @@ public CircularBuffer(int capacity)
public void AddLast(T item)
{
_buffer[_currentIndex] = item;

// continuously overwrite the oldest item once full
_size = Math.Max(_currentIndex + 1, _size);
_currentIndex = (_currentIndex + 1) % _buffer.Length;
if (_currentIndex == _startIndex)
_startIndex = (_startIndex + 1) % _buffer.Length;
}

public IEnumerable<T> Iter()
{
for (int i = _startIndex; i != _currentIndex; i = (i + 1) % _buffer.Length)
yield return _buffer[i];
for (int i = 0; i < Math.Min(_buffer.Length, _size); i++)
yield return _buffer[(i + _currentIndex) % _buffer.Length];
}
}
46 changes: 39 additions & 7 deletions RLBotCS/ManagerTools/PerfMonitor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Bridge.State;
using RLBot.Flat;
using Deltas = (float GameTimeDelta, float ArrivalDelta);

namespace RLBotCS.ManagerTools;

Expand All @@ -25,13 +26,13 @@ public class PerfMonitor
B = 0,
};

private readonly CircularBuffer<float> _rlbotSamples = new(_maxSamples);
private readonly CircularBuffer<Deltas> _rlbotSamples = new(_maxSamples);
private readonly SortedDictionary<string, CircularBuffer<bool>> _samples = new();
private float time = 0;

public void AddRLBotSample(float timeDiff)
public void AddRLBotSample(Deltas deltas)
{
_rlbotSamples.AddLast(timeDiff);
_rlbotSamples.AddLast(deltas);
}

public void AddSample(string name, bool gotInput)
Expand All @@ -49,18 +50,49 @@ public void RemoveBot(string name)
_samples.Remove(name);
}

public static float GetPercentile(IEnumerable<float> data, float p)
{
var sorted = data.OrderBy(x => x).ToList();
int n = sorted.Count;
if (n == 0)
return default;

double rank = p * (n - 1);
int lower = (int)Math.Floor(rank);
int upper = (int)Math.Ceiling(rank);

return (float)(sorted[lower] + (rank - lower) * (sorted[upper] - sorted[lower]));
}

public void RenderSummary(Rendering rendering, GameState gameState, float deltaTime)
{
time += deltaTime;
if (time < _timeSkip)
return;
time = 0;

float averageTimeDiff = _rlbotSamples.Count > 0 ? _rlbotSamples.Iter().Average() : 1;
float timeDiffPercentage = 1 / (120f * averageTimeDiff);
var arrivalDeltas = _rlbotSamples.Iter().Select(t => t.ArrivalDelta);
var gameTimeDeltas = _rlbotSamples.Iter().Select(t => t.GameTimeDelta);

float averageTickDelta = gameTimeDeltas.Sum() / _maxSamples;
float averageTickRate = 1f / averageTickDelta;

// Find deltas larger than expected at 60hz, allowing 10% margin
float misses60 = arrivalDeltas.Count(d => (d - (1f / 60f)) > (0.1f / 60f));

// Find deltas larger than expected at 120hz, allowing 10% margin
float misses120 = arrivalDeltas.Count(d => (d - (1f / 120f)) > (0.1f / 120f));

string message = $"RLBot: {timeDiffPercentage * 100:0.0}%";
bool shouldRender = timeDiffPercentage < 0.9999 || timeDiffPercentage > 1.0001;
string message = $"""
RLBot @ {averageTickRate:0}hz {(1f - misses60 / 120f) * 100f:0}%|{(
1f - misses120 / 120f
) * 100f:0}%
p95 {GetPercentile(arrivalDeltas, 0.95f) * 1000f:0.0}ms p99 {GetPercentile(
arrivalDeltas,
0.99f
) * 1000f:0.0}ms
""";
bool shouldRender = misses120 > 1;

foreach (var (name, samples) in _samples)
{
Expand Down
12 changes: 11 additions & 1 deletion RLBotCS/Server/BridgeHandler.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Diagnostics;
using System.Threading.Channels;
using Bridge.Conversion;
using Bridge.TCP;
Expand Down Expand Up @@ -57,6 +58,7 @@ private async Task HandleServer()
_context.Logger.LogInformation("Connected to Rocket League");

bool isFirstTick = true;
long lastNewTickTimestamp = Stopwatch.GetTimestamp();

await foreach (var messageClump in _context.Messenger.ReadAllAsync())
{
Expand Down Expand Up @@ -95,7 +97,15 @@ private async Task HandleServer()
_context.ticksSinceMapLoad += 1;

if (timeAdvanced)
_context.PerfMonitor.AddRLBotSample(deltaTime);
{
// Only track ticks where time advanced, the api actually sends more
// clumps, but we don't care about those.
float arrivalDeltaTime = (float)
Stopwatch.GetElapsedTime(lastNewTickTimestamp).TotalSeconds;
lastNewTickTimestamp = Stopwatch.GetTimestamp();

_context.PerfMonitor.AddRLBotSample((deltaTime, arrivalDeltaTime));
}

ConsiderDistributingPacket(_context, timeAdvanced);

Expand Down
Loading