perf: ordered behaviour collectors now use linked lists for performance
This commit is contained in:
@@ -7,6 +7,9 @@ public class ActiveBehaviourCollectorOrdered<T> : ActiveBehaviourCollector<T> wh
|
|||||||
{
|
{
|
||||||
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
||||||
|
|
||||||
|
private readonly LinkedList<T> behaviours = new();
|
||||||
|
private readonly List<T> sortList = [];
|
||||||
|
|
||||||
private IComparer<T>? _sortBy = null;
|
private IComparer<T>? _sortBy = null;
|
||||||
public IComparer<T>? SortBy
|
public IComparer<T>? SortBy
|
||||||
{
|
{
|
||||||
@@ -16,43 +19,81 @@ public class ActiveBehaviourCollectorOrdered<T> : ActiveBehaviourCollector<T> wh
|
|||||||
_sortBy = value;
|
_sortBy = value;
|
||||||
|
|
||||||
if (value is not null)
|
if (value is not null)
|
||||||
activeBehaviours.Sort(value);
|
Sort(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int Count => behaviours.Count;
|
||||||
|
|
||||||
|
public override T this[Index index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int actualIndex = index.IsFromEnd
|
||||||
|
? behaviours.Count - index.Value
|
||||||
|
: index.Value;
|
||||||
|
|
||||||
|
if (actualIndex < 0 || actualIndex >= behaviours.Count)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
int currentIndex = 0;
|
||||||
|
foreach (T item in behaviours)
|
||||||
|
if (currentIndex++ == actualIndex)
|
||||||
|
return item;
|
||||||
|
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool RemoveBehaviour(T tBehaviour) => behaviours.Remove(tBehaviour);
|
||||||
protected override void AddBehaviour(T behaviour)
|
protected override void AddBehaviour(T behaviour)
|
||||||
{
|
{
|
||||||
if (SortBy is null)
|
if (SortBy is null)
|
||||||
{
|
{
|
||||||
activeBehaviours.Add(behaviour);
|
behaviours.AddLast(behaviour);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int insertionIndex = activeBehaviours.BinarySearch(behaviour, SortBy);
|
LinkedListNode<T>? insertionNode = FindInsertionNodeFor(behaviour, SortBy);
|
||||||
|
|
||||||
if (insertionIndex < 0)
|
if (insertionNode is not null)
|
||||||
insertionIndex = ~insertionIndex;
|
behaviours.AddAfter(insertionNode, behaviour);
|
||||||
|
else
|
||||||
activeBehaviours.Insert(insertionIndex, behaviour);
|
behaviours.AddLast(behaviour);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnBehaviourAdd(IBehaviour behaviour)
|
private LinkedListNode<T>? FindInsertionNodeFor(T behaviour, IComparer<T> sortBy)
|
||||||
{
|
{
|
||||||
behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
LinkedListNode<T>? node = behaviours.First;
|
||||||
|
|
||||||
|
while (node is not null)
|
||||||
|
{
|
||||||
|
int compareValue = sortBy.Compare(node.Value, behaviour);
|
||||||
|
if (compareValue < 0)
|
||||||
|
return node.Previous;
|
||||||
|
node = node.Next;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnBehaviourRemove(IBehaviour behaviour)
|
protected override void OnBehaviourAdd(IBehaviour behaviour) => behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
||||||
{
|
protected override void OnBehaviourRemove(IBehaviour behaviour) => behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
||||||
behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
||||||
{
|
{
|
||||||
T behaviour = (T)sender;
|
T behaviour = (T)sender;
|
||||||
activeBehaviours.Remove(behaviour);
|
behaviours.Remove(behaviour);
|
||||||
AddBehaviour(behaviour);
|
AddBehaviour(behaviour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Sort(IComparer<T> comparer)
|
||||||
|
{
|
||||||
|
sortList.Sort(comparer);
|
||||||
|
behaviours.Clear();
|
||||||
|
foreach (T item in sortList)
|
||||||
|
behaviours.AddLast(item);
|
||||||
|
}
|
||||||
|
|
||||||
public ActiveBehaviourCollectorOrdered() => delegateOnPriorityChanged = OnPriorityChanged;
|
public ActiveBehaviourCollectorOrdered() => delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
public ActiveBehaviourCollectorOrdered(IUniverse universe, Comparison<T> sortBy) : base(universe)
|
public ActiveBehaviourCollectorOrdered(IUniverse universe, Comparison<T> sortBy) : base(universe)
|
||||||
{
|
{
|
||||||
|
@@ -3,10 +3,13 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class BehaviourCollectorOrdered<T> : BehaviourCollector<T> where T : class
|
public class BehaviourCollectorOrdered<T> : BehaviourCollectorBase<T> where T : class
|
||||||
{
|
{
|
||||||
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
||||||
|
|
||||||
|
private readonly LinkedList<T> behaviours = new();
|
||||||
|
private readonly List<T> sortList = [];
|
||||||
|
|
||||||
private IComparer<T>? _sortBy = null;
|
private IComparer<T>? _sortBy = null;
|
||||||
public IComparer<T>? SortBy
|
public IComparer<T>? SortBy
|
||||||
{
|
{
|
||||||
@@ -16,35 +19,64 @@ public class BehaviourCollectorOrdered<T> : BehaviourCollector<T> where T : clas
|
|||||||
_sortBy = value;
|
_sortBy = value;
|
||||||
|
|
||||||
if (value is not null)
|
if (value is not null)
|
||||||
behaviours.Sort(value);
|
Sort(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int Count => behaviours.Count;
|
||||||
|
public override T this[Index index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int actualIndex = index.IsFromEnd
|
||||||
|
? behaviours.Count - index.Value
|
||||||
|
: index.Value;
|
||||||
|
|
||||||
|
if (actualIndex < 0 || actualIndex >= behaviours.Count)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
int currentIndex = 0;
|
||||||
|
foreach (T item in behaviours)
|
||||||
|
if (currentIndex++ == actualIndex)
|
||||||
|
return item;
|
||||||
|
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool RemoveBehaviour(T tBehaviour) => behaviours.Remove(tBehaviour);
|
||||||
protected override void AddBehaviour(T behaviour)
|
protected override void AddBehaviour(T behaviour)
|
||||||
{
|
{
|
||||||
if (SortBy is null)
|
if (SortBy is null)
|
||||||
{
|
{
|
||||||
behaviours.Add(behaviour);
|
behaviours.AddLast(behaviour);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int insertionIndex = behaviours.BinarySearch(behaviour, SortBy);
|
LinkedListNode<T>? insertionNode = FindInsertionNodeFor(behaviour, SortBy);
|
||||||
|
|
||||||
if (insertionIndex < 0)
|
if (insertionNode is not null)
|
||||||
insertionIndex = ~insertionIndex;
|
behaviours.AddAfter(insertionNode, behaviour);
|
||||||
|
else
|
||||||
behaviours.Insert(insertionIndex, behaviour);
|
behaviours.AddLast(behaviour);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnBehaviourAdd(IBehaviour behaviour)
|
private LinkedListNode<T>? FindInsertionNodeFor(T behaviour, IComparer<T> sortBy)
|
||||||
{
|
{
|
||||||
behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
LinkedListNode<T>? node = behaviours.First;
|
||||||
|
|
||||||
|
while (node is not null)
|
||||||
|
{
|
||||||
|
int compareValue = sortBy.Compare(node.Value, behaviour);
|
||||||
|
if (compareValue < 0)
|
||||||
|
return node.Previous;
|
||||||
|
node = node.Next;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnBehaviourRemove(IBehaviour behaviour)
|
protected override void OnBehaviourAdd(IBehaviour behaviour) => behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
||||||
{
|
protected override void OnBehaviourRemove(IBehaviour behaviour) => behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
||||||
behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
||||||
{
|
{
|
||||||
@@ -53,6 +85,14 @@ public class BehaviourCollectorOrdered<T> : BehaviourCollector<T> where T : clas
|
|||||||
AddBehaviour(behaviour);
|
AddBehaviour(behaviour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Sort(IComparer<T> comparer)
|
||||||
|
{
|
||||||
|
sortList.Sort(comparer);
|
||||||
|
behaviours.Clear();
|
||||||
|
foreach (T item in sortList)
|
||||||
|
behaviours.AddLast(item);
|
||||||
|
}
|
||||||
|
|
||||||
public BehaviourCollectorOrdered() => delegateOnPriorityChanged = OnPriorityChanged;
|
public BehaviourCollectorOrdered() => delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
public BehaviourCollectorOrdered(IUniverse universe, Comparison<T> sortBy) : base(universe)
|
public BehaviourCollectorOrdered(IUniverse universe, Comparison<T> sortBy) : base(universe)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user