mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
recalculate every nth
This commit is contained in:
parent
9cc3b32730
commit
61243a9fbd
@ -17,14 +17,21 @@ public class HistoryBounds
|
|||||||
// history limit. oldest bounds will be removed.
|
// history limit. oldest bounds will be removed.
|
||||||
public readonly int limit;
|
public readonly int limit;
|
||||||
|
|
||||||
|
// only remove old entries every n-th insertion.
|
||||||
|
// new entries are still encapsulated on every insertion.
|
||||||
|
// for example, every 2nd insertion is enough, and 2x as fast.
|
||||||
|
public readonly int recalculateEveryNth;
|
||||||
|
int recalculateCounter = 0;
|
||||||
|
|
||||||
// total bounds encapsulating all of the bounds history
|
// total bounds encapsulating all of the bounds history
|
||||||
public Bounds total;
|
public Bounds total;
|
||||||
|
|
||||||
public HistoryBounds(int limit)
|
public HistoryBounds(int limit, int recalculateEveryNth)
|
||||||
{
|
{
|
||||||
// initialize queue with maximum capacity to avoid runtime resizing
|
// initialize queue with maximum capacity to avoid runtime resizing
|
||||||
// +1 because it makes the code easier if we insert first, and then remove.
|
// +1 because it makes the code easier if we insert first, and then remove.
|
||||||
this.limit = limit;
|
this.limit = limit;
|
||||||
|
this.recalculateEveryNth = recalculateEveryNth;
|
||||||
history = new Queue<Bounds>(limit + 1);
|
history = new Queue<Bounds>(limit + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +54,14 @@ public void Insert(Bounds bounds)
|
|||||||
// remove oldest
|
// remove oldest
|
||||||
history.Dequeue();
|
history.Dequeue();
|
||||||
|
|
||||||
|
// optimization: only recalculate every n-th removal.
|
||||||
|
// accurate enough, and N times faster.
|
||||||
|
if (++recalculateCounter < recalculateEveryNth)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// reset counter
|
||||||
|
recalculateCounter = 0;
|
||||||
|
|
||||||
// recalculate total bounds
|
// recalculate total bounds
|
||||||
// (only needed after removing the oldest)
|
// (only needed after removing the oldest)
|
||||||
total = bounds;
|
total = bounds;
|
||||||
|
@ -23,12 +23,13 @@ public static Bounds MinMax(float min, float max) =>
|
|||||||
// 64 entries are much more than we would usually use.
|
// 64 entries are much more than we would usually use.
|
||||||
//
|
//
|
||||||
// Unity 2021.3 LTS, release mode: 10x000 x 65; limit=8
|
// Unity 2021.3 LTS, release mode: 10x000 x 65; limit=8
|
||||||
// O(N) Queue<Bounds> implementation: 1045 ms
|
// O(N) Queue<Bounds> implementation: 1045 ms
|
||||||
|
// O(N) Queue and recalculate every 2nd: 640 ms
|
||||||
[Test]
|
[Test]
|
||||||
[TestCase(10_000, 64, 8)]
|
[TestCase(10_000, 64, 8, 2)]
|
||||||
public void Benchmark(int iterations, int insertions, int limit)
|
public void Benchmark(int iterations, int insertions, int limit, int recalculate)
|
||||||
{
|
{
|
||||||
HistoryBounds history = new HistoryBounds(limit);
|
HistoryBounds history = new HistoryBounds(limit, recalculate);
|
||||||
|
|
||||||
// always use the same seed so we get the same test.
|
// always use the same seed so we get the same test.
|
||||||
Random.InitState(0);
|
Random.InitState(0);
|
||||||
@ -58,7 +59,7 @@ public void Benchmark(int iterations, int insertions, int limit)
|
|||||||
public void Insert_Basic()
|
public void Insert_Basic()
|
||||||
{
|
{
|
||||||
const int limit = 3;
|
const int limit = 3;
|
||||||
HistoryBounds history = new HistoryBounds(limit);
|
HistoryBounds history = new HistoryBounds(limit, recalculateEveryNth: 1);
|
||||||
|
|
||||||
// insert initial [-1, 1].
|
// insert initial [-1, 1].
|
||||||
// should calculate new bounds == initial.
|
// should calculate new bounds == initial.
|
||||||
@ -93,7 +94,7 @@ public void Insert_Basic()
|
|||||||
public void Insert_Revisit()
|
public void Insert_Revisit()
|
||||||
{
|
{
|
||||||
const int limit = 3;
|
const int limit = 3;
|
||||||
HistoryBounds history = new HistoryBounds(limit);
|
HistoryBounds history = new HistoryBounds(limit, recalculateEveryNth: 1);
|
||||||
|
|
||||||
// insert initial [-1, 1].
|
// insert initial [-1, 1].
|
||||||
// should calculate new bounds == initial.
|
// should calculate new bounds == initial.
|
||||||
@ -123,10 +124,10 @@ public void Insert_Revisit()
|
|||||||
// by default, HistoryBounds.total is new Bounds() which is (0,0).
|
// by default, HistoryBounds.total is new Bounds() which is (0,0).
|
||||||
// make sure this isn't included in results by default.
|
// make sure this isn't included in results by default.
|
||||||
[Test]
|
[Test]
|
||||||
public void InsertFar()
|
public void Insert_Far()
|
||||||
{
|
{
|
||||||
const int limit = 3;
|
const int limit = 3;
|
||||||
HistoryBounds history = new HistoryBounds(limit);
|
HistoryBounds history = new HistoryBounds(limit, recalculateEveryNth: 1);
|
||||||
|
|
||||||
// insert initial [2, 3].
|
// insert initial [2, 3].
|
||||||
// should calculate new bounds == initial.
|
// should calculate new bounds == initial.
|
||||||
@ -154,12 +155,71 @@ public void InsertFar()
|
|||||||
Assert.That(history.Count, Is.EqualTo(3));
|
Assert.That(history.Count, Is.EqualTo(3));
|
||||||
Assert.That(history.total, Is.EqualTo(MinMax(0.5f, 4)));
|
Assert.That(history.total, Is.EqualTo(MinMax(0.5f, 4)));
|
||||||
}
|
}
|
||||||
|
// test to check if recalculate works as expected
|
||||||
|
[Test]
|
||||||
|
public void Insert_Recalculate()
|
||||||
|
{
|
||||||
|
const int limit = 3;
|
||||||
|
HistoryBounds history = new HistoryBounds(limit, recalculateEveryNth: 2);
|
||||||
|
|
||||||
|
// insert initial [-1, 1].
|
||||||
|
// should calculate new bounds == initial.
|
||||||
|
history.Insert(MinMax(-1, 1));
|
||||||
|
Assert.That(history.Count, Is.EqualTo(1));
|
||||||
|
Assert.That(history.total, Is.EqualTo(MinMax(-1, 1)));
|
||||||
|
|
||||||
|
// insert [0, 2]
|
||||||
|
// should calculate new bounds == [-1, 2].
|
||||||
|
history.Insert(MinMax(0, 2));
|
||||||
|
Assert.That(history.Count, Is.EqualTo(2));
|
||||||
|
Assert.That(history.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.
|
||||||
|
history.Insert(MinMax(-0.5f, 1));
|
||||||
|
Assert.That(history.Count, Is.EqualTo(3));
|
||||||
|
Assert.That(history.total, Is.EqualTo(MinMax(-1, 2)));
|
||||||
|
|
||||||
|
// insert more than 'limit': [0, 0]
|
||||||
|
// the oldest one [-1, 1] should be discarded.
|
||||||
|
// recalculate counter is 0+=1. nothing is recalculated yet.
|
||||||
|
history.Insert(MinMax(0, 0));
|
||||||
|
Assert.That(history.Count, Is.EqualTo(3));
|
||||||
|
Assert.That(history.total, Is.EqualTo(MinMax(-1, 2)));
|
||||||
|
|
||||||
|
// insert more than 'limit': [0, 0]
|
||||||
|
// the oldest one [0, 2] should be discarded.
|
||||||
|
// recalculate counter is 1+=1. new bounds are recalculated.
|
||||||
|
// recalculate counter should be reset to 0.
|
||||||
|
history.Insert(MinMax(0, 0));
|
||||||
|
Assert.That(history.Count, Is.EqualTo(3));
|
||||||
|
Assert.That(history.total, Is.EqualTo(MinMax(-0.5f, 1)));
|
||||||
|
|
||||||
|
// ... test another iteration to ensure recalculate counter was
|
||||||
|
// reset properly ...
|
||||||
|
|
||||||
|
// insert more than 'limit': [0, 0]
|
||||||
|
// the oldest one [-0.5, 1] should be discarded.
|
||||||
|
// recalculate counter is 0+=1. nothing is recalculated yet.
|
||||||
|
history.Insert(MinMax(0, 0));
|
||||||
|
Assert.That(history.Count, Is.EqualTo(3));
|
||||||
|
Assert.That(history.total, Is.EqualTo(MinMax(-0.5f, 1)));
|
||||||
|
|
||||||
|
// insert more than 'limit': [0, 0]
|
||||||
|
// the oldest one [0, 0] should be discarded.
|
||||||
|
// recalculate counter is 1+=1. new bounds are recalculated.
|
||||||
|
// recalculate counter should be reset to 0.
|
||||||
|
history.Insert(MinMax(0, 0));
|
||||||
|
Assert.That(history.Count, Is.EqualTo(3));
|
||||||
|
Assert.That(history.total, Is.EqualTo(MinMax(0, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
const int limit = 3;
|
const int limit = 3;
|
||||||
HistoryBounds history = new HistoryBounds(limit);
|
HistoryBounds history = new HistoryBounds(limit, recalculateEveryNth: 1);
|
||||||
|
|
||||||
history.Insert(MinMax(1, 2));
|
history.Insert(MinMax(1, 2));
|
||||||
history.Insert(MinMax(2, 3));
|
history.Insert(MinMax(2, 3));
|
||||||
|
Loading…
Reference in New Issue
Block a user