From e344091c332cc8b3ef99c18310b63a0abe55db27 Mon Sep 17 00:00:00 2001 From: mischa Date: Mon, 24 Jul 2023 20:24:46 +0800 Subject: [PATCH] HistoryBounds data structure - wip --- .../Core/LagCompensation/HistoryBounds.cs | 34 +++++++++++++++---- .../LagCompensation/HistoryBoundsTests.cs | 31 ++++++++--------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/Assets/Mirror/Core/LagCompensation/HistoryBounds.cs b/Assets/Mirror/Core/LagCompensation/HistoryBounds.cs index 2e45145c8..82403d1fe 100644 --- a/Assets/Mirror/Core/LagCompensation/HistoryBounds.cs +++ b/Assets/Mirror/Core/LagCompensation/HistoryBounds.cs @@ -8,30 +8,50 @@ namespace Mirror { - public static class HistoryBounds + public class HistoryBounds + { + public readonly Queue history; // TODO not public + public int Count => history.Count; + + public readonly int limit; + + public HistoryBounds(int limit) + { + // initialize queue with maximum capacity to avoid runtime resizing + this.limit = limit; + history = new Queue(limit); + } + + public void Reset() + { + history.Clear(); + // TODO reset total etc. + } + } + + public static class HistoryBoundsAlgo { // insert current bounds into history. returns new total bounds. // Queue.Dequeue() always has the oldest bounds. public static Bounds Insert( - Queue history, - int limit, + HistoryBounds history, Bounds bounds) { // optimization: only insert if // remove oldest if limit reached - if (history.Count >= limit) - history.Dequeue(); + if (history.Count >= history.limit) + history.history.Dequeue(); // insert the new bounds - history.Enqueue(bounds); + history.history.Enqueue(bounds); // summarize total bounds. // starting at latest bounds, not at 'new Bounds' because that would // encapsulate (0,0) too. // TODO make this not be O(N) Bounds total = bounds; - foreach (Bounds b in history) + foreach (Bounds b in history.history) total.Encapsulate(b); return total; diff --git a/Assets/Mirror/Tests/Editor/LagCompensation/HistoryBoundsTests.cs b/Assets/Mirror/Tests/Editor/LagCompensation/HistoryBoundsTests.cs index a45a324cf..fce97c005 100644 --- a/Assets/Mirror/Tests/Editor/LagCompensation/HistoryBoundsTests.cs +++ b/Assets/Mirror/Tests/Editor/LagCompensation/HistoryBoundsTests.cs @@ -6,13 +6,8 @@ namespace Mirror.Tests.LagCompensationTests { public class HistoryBoundsTests { - Queue history; - [SetUp] - public void SetUp() - { - history = new Queue(); - } + public void SetUp() {} // helper function to construct (min, max) bounds public static Bounds MinMax(Vector3 min, Vector3 max) @@ -34,6 +29,8 @@ public static Bounds MinMax(float min, float max) => [TestCase(10_000, 64, 8)] public void Benchmark(int iterations, int insertions, int limit) { + HistoryBounds history = new HistoryBounds(limit); + // always use the same seed so we get the same test. Random.InitState(0); @@ -42,13 +39,13 @@ public void Benchmark(int iterations, int insertions, int limit) { // each test captures 'insertions' bounds, // with a history of 'limit' bounds. - history.Clear(); + history.Reset(); for (int i = 0; i < insertions; ++i) { float min = Random.Range(-1, 1); float max = Random.Range(min, 1); Bounds bounds = MinMax(min, max); - Bounds total = HistoryBounds.Insert(history, limit, bounds); + Bounds total = HistoryBoundsAlgo.Insert(history, bounds); } } } @@ -58,30 +55,31 @@ public void Benchmark(int iterations, int insertions, int limit) public void Insert_Basic() { const int limit = 3; + HistoryBounds history = new HistoryBounds(limit); // insert initial [-1, 1]. // should calculate new bounds == initial. - Bounds total = HistoryBounds.Insert(history, limit, MinMax(-1, 1)); + Bounds total = HistoryBoundsAlgo.Insert(history, MinMax(-1, 1)); Assert.That(history.Count, Is.EqualTo(1)); Assert.That(total, Is.EqualTo(MinMax(-1, 1))); // insert [0, 2] // should calculate new bounds == [-1, 2]. - total = HistoryBounds.Insert(history, limit, MinMax(0, 2)); + total = HistoryBoundsAlgo.Insert(history, MinMax(0, 2)); Assert.That(history.Count, Is.EqualTo(2)); Assert.That(total, Is.EqualTo(MinMax(-1, 2))); // insert one that's smaller than current bounds [-.5, 0] // history needs to contain it even if smaller, because once the oldest // largest one gets removed, this one matters too. - total = HistoryBounds.Insert(history, limit, MinMax(-0.5f, 0)); + total = HistoryBoundsAlgo.Insert(history, MinMax(-0.5f, 0)); Assert.That(history.Count, Is.EqualTo(3)); Assert.That(total, Is.EqualTo(MinMax(-1, 2))); // insert more than 'limit': [0, 0] // the oldest one [-1, 1] should be discarded. // new bounds should be [-0.5, 2] - total = HistoryBounds.Insert(history, limit, MinMax(0, 0)); + total = HistoryBoundsAlgo.Insert(history, MinMax(0, 0)); Assert.That(history.Count, Is.EqualTo(3)); Assert.That(total, Is.EqualTo(MinMax(-0.5f, 2))); } @@ -92,28 +90,29 @@ public void Insert_Basic() public void Insert_Revisit() { const int limit = 3; + HistoryBounds history = new HistoryBounds(limit); // insert initial [-1, 1]. // should calculate new bounds == initial. - Bounds total = HistoryBounds.Insert(history, limit, MinMax(-1, 1)); + Bounds total = HistoryBoundsAlgo.Insert(history, MinMax(-1, 1)); Assert.That(history.Count, Is.EqualTo(1)); Assert.That(total, Is.EqualTo(MinMax(-1, 1))); // insert [0, 2] // should calculate new bounds == [-1, 2]. - total = HistoryBounds.Insert(history, limit, MinMax(0, 2)); + total = HistoryBoundsAlgo.Insert(history, MinMax(0, 2)); Assert.That(history.Count, Is.EqualTo(2)); Assert.That(total, Is.EqualTo(MinMax(-1, 2))); // visit [-1, 1] again - total = HistoryBounds.Insert(history, limit, MinMax(-1, 1)); + total = HistoryBoundsAlgo.Insert(history, MinMax(-1, 1)); Assert.That(history.Count, Is.EqualTo(3)); Assert.That(total, Is.EqualTo(MinMax(-1, 2))); // insert beyond limit. // oldest one [-1, 1] should be removed. // total should still include it because we revisited [1, 1]. - total = HistoryBounds.Insert(history, limit, MinMax(0, 0)); + total = HistoryBoundsAlgo.Insert(history, MinMax(0, 0)); Assert.That(history.Count, Is.EqualTo(3)); Assert.That(total, Is.EqualTo(MinMax(-1, 2))); }