From 85734defec799271d8838485a4aa003e095bdc3a Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Sat, 14 Jun 2014 08:20:12 +0100 Subject: [PATCH] Improve trait enumeration speed for All and GetMultiple. Use a hand-rolled enumerators to avoid the overhead from compiler generated enumerable blocks. This trades terseness for some minor performance gains. --- OpenRA.Game/TraitDictionary.cs | 61 ++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/OpenRA.Game/TraitDictionary.cs b/OpenRA.Game/TraitDictionary.cs index 06086b317e..eb055959c7 100755 --- a/OpenRA.Game/TraitDictionary.cs +++ b/OpenRA.Game/TraitDictionary.cs @@ -162,19 +162,68 @@ namespace OpenRA public IEnumerable GetMultiple(uint actor) { ++Queries; - var index = actors.BinarySearchMany(actor); - while (index < actors.Count && actors[index].ActorID == actor) + return new MultipleEnumerable(this, actor); + } + + class MultipleEnumerable : IEnumerable + { + readonly TraitContainer container; + readonly uint actor; + public MultipleEnumerable(TraitContainer container, uint actor) { this.container = container; this.actor = actor; } + public IEnumerator GetEnumerator() { return new MultipleEnumerator(container, actor); } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } + } + + class MultipleEnumerator : IEnumerator + { + readonly List actors; + readonly List traits; + readonly uint actor; + int index; + public MultipleEnumerator(TraitContainer container, uint actor) { - yield return traits[index]; - ++index; + actors = container.actors; + traits = container.traits; + this.actor = actor; + Reset(); } + public void Reset() { index = actors.BinarySearchMany(actor) - 1; } + public bool MoveNext() { return ++index < actors.Count && actors[index].ActorID == actor; } + public T Current { get { return traits[index]; } } + object System.Collections.IEnumerator.Current { get { return Current; } } + public void Dispose() { } } public IEnumerable> All() { ++Queries; - for (var i = 0; i < actors.Count; i++) - yield return new TraitPair { Actor = actors[i], Trait = traits[i] }; + return new AllEnumerable(this); + } + + class AllEnumerable : IEnumerable> + { + readonly TraitContainer container; + public AllEnumerable(TraitContainer container) { this.container = container; } + public IEnumerator> GetEnumerator() { return new AllEnumerator(container); } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } + } + + class AllEnumerator : IEnumerator> + { + readonly List actors; + readonly List traits; + int index; + public AllEnumerator(TraitContainer container) + { + actors = container.actors; + traits = container.traits; + Reset(); + } + public void Reset() { index = -1; } + public bool MoveNext() { return ++index < actors.Count; } + public TraitPair Current { get { return new TraitPair { Actor = actors[index], Trait = traits[index] }; } } + object System.Collections.IEnumerator.Current { get { return Current; } } + public void Dispose() { } } public void RemoveActor(uint actor)