TechTree.GatherOwnedPrerequisites performance improvements.

- Consuming methods cared only about the count and not the actual actors, so only counts the actors rather that creating lists.
- ProvidesPrerequisites implementations return cached objects rather then allocating new enumerables on each call.
This commit is contained in:
RoosterDragon
2023-05-05 19:10:05 +01:00
committed by Gustas
parent 65c0cf1065
commit 0b4a54ab54
4 changed files with 26 additions and 38 deletions

View File

@@ -43,6 +43,7 @@ namespace OpenRA.Mods.Cnc.Traits
public class GrantPrerequisiteChargeDrainPower : SupportPower, ITechTreePrerequisite, INotifyOwnerChanged public class GrantPrerequisiteChargeDrainPower : SupportPower, ITechTreePrerequisite, INotifyOwnerChanged
{ {
readonly GrantPrerequisiteChargeDrainPowerInfo info; readonly GrantPrerequisiteChargeDrainPowerInfo info;
readonly string[] prerequisites;
TechTree techTree; TechTree techTree;
bool active; bool active;
@@ -50,6 +51,7 @@ namespace OpenRA.Mods.Cnc.Traits
: base(self, info) : base(self, info)
{ {
this.info = info; this.info = info;
prerequisites = new[] { info.Prerequisite };
} }
protected override void Created(Actor self) protected override void Created(Actor self)
@@ -82,16 +84,7 @@ namespace OpenRA.Mods.Cnc.Traits
techTree.ActorChanged(self); techTree.ActorChanged(self);
} }
IEnumerable<string> ITechTreePrerequisite.ProvidesPrerequisites IEnumerable<string> ITechTreePrerequisite.ProvidesPrerequisites => active ? prerequisites : Enumerable.Empty<string>();
{
get
{
if (!active)
yield break;
yield return info.Prerequisite;
}
}
public class DischargeableSupportPowerInstance : SupportPowerInstance public class DischargeableSupportPowerInstance : SupportPowerInstance
{ {

View File

@@ -11,6 +11,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
@@ -39,7 +40,7 @@ namespace OpenRA.Mods.Common.Traits
public class ProvidesPrerequisite : ConditionalTrait<ProvidesPrerequisiteInfo>, ITechTreePrerequisite, INotifyOwnerChanged, INotifyCreated public class ProvidesPrerequisite : ConditionalTrait<ProvidesPrerequisiteInfo>, ITechTreePrerequisite, INotifyOwnerChanged, INotifyCreated
{ {
readonly string prerequisite; readonly string[] prerequisites;
bool enabled; bool enabled;
TechTree techTree; TechTree techTree;
@@ -48,24 +49,15 @@ namespace OpenRA.Mods.Common.Traits
public ProvidesPrerequisite(ActorInitializer init, ProvidesPrerequisiteInfo info) public ProvidesPrerequisite(ActorInitializer init, ProvidesPrerequisiteInfo info)
: base(info) : base(info)
{ {
prerequisite = info.Prerequisite; if (string.IsNullOrEmpty(info.Prerequisite))
prerequisites = new[] { init.Self.Info.Name };
if (string.IsNullOrEmpty(prerequisite)) else
prerequisite = init.Self.Info.Name; prerequisites = new[] { info.Prerequisite };
faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName); faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
} }
public IEnumerable<string> ProvidesPrerequisites public IEnumerable<string> ProvidesPrerequisites => enabled ? prerequisites : Enumerable.Empty<string>();
{
get
{
if (!enabled)
yield break;
yield return prerequisite;
}
}
protected override void Created(Actor self) protected override void Created(Actor self)
{ {

View File

@@ -11,6 +11,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
@@ -38,11 +39,9 @@ namespace OpenRA.Mods.Common.Traits
readonly ProvidesTechPrerequisiteInfo info; readonly ProvidesTechPrerequisiteInfo info;
readonly bool enabled; readonly bool enabled;
static readonly string[] NoPrerequisites = Array.Empty<string>();
public string Name => info.Name; public string Name => info.Name;
public IEnumerable<string> ProvidesPrerequisites => enabled ? info.Prerequisites : NoPrerequisites; public IEnumerable<string> ProvidesPrerequisites => enabled ? info.Prerequisites : Enumerable.Empty<string>();
public ProvidesTechPrerequisite(ProvidesTechPrerequisiteInfo info, ActorInitializer init) public ProvidesTechPrerequisite(ProvidesTechPrerequisiteInfo info, ActorInitializer init)
{ {

View File

@@ -12,7 +12,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
@@ -71,9 +70,9 @@ namespace OpenRA.Mods.Common.Traits
^ !ownedPrereqs.ContainsKey(p.Replace("!", "").Replace("~", "")))); ^ !ownedPrereqs.ContainsKey(p.Replace("!", "").Replace("~", ""))));
} }
static Cache<string, List<Actor>> GatherOwnedPrerequisites(Player player) static Dictionary<string, int> GatherOwnedPrerequisites(Player player)
{ {
var ret = new Cache<string, List<Actor>>(x => new List<Actor>()); var ret = new Dictionary<string, int>();
if (player == null) if (player == null)
return ret; return ret;
@@ -89,7 +88,8 @@ namespace OpenRA.Mods.Common.Traits
if (p == null) if (p == null)
continue; continue;
ret[p].Add(b.Actor); ret.TryGetValue(p, out var count);
ret[p] = count + 1;
} }
} }
@@ -103,7 +103,11 @@ namespace OpenRA.Mods.Common.Traits
a.Actor.Info.TraitInfo<BuildableInfo>().BuildLimit > 0); a.Actor.Info.TraitInfo<BuildableInfo>().BuildLimit > 0);
foreach (var buildable in buildables) foreach (var buildable in buildables)
ret[buildable.Actor.Info.Name].Add(buildable.Actor); {
var name = buildable.Actor.Info.Name;
ret.TryGetValue(name, out var count);
ret[name] = count + 1;
}
return ret; return ret;
} }
@@ -132,7 +136,7 @@ namespace OpenRA.Mods.Common.Traits
hidden = false; hidden = false;
} }
bool HasPrerequisites(Cache<string, List<Actor>> ownedPrerequisites) bool HasPrerequisites(Dictionary<string, int> ownedPrerequisites)
{ {
// PERF: Avoid LINQ. // PERF: Avoid LINQ.
foreach (var prereq in prerequisites) foreach (var prereq in prerequisites)
@@ -145,7 +149,7 @@ namespace OpenRA.Mods.Common.Traits
return true; return true;
} }
bool IsHidden(Cache<string, List<Actor>> ownedPrerequisites) bool IsHidden(Dictionary<string, int> ownedPrerequisites)
{ {
// PERF: Avoid LINQ. // PERF: Avoid LINQ.
foreach (var prereq in prerequisites) foreach (var prereq in prerequisites)
@@ -160,12 +164,12 @@ namespace OpenRA.Mods.Common.Traits
return false; return false;
} }
public void Update(Cache<string, List<Actor>> ownedPrerequisites) public void Update(Dictionary<string, int> ownedPrerequisites)
{ {
var hasReachedLimit = limit > 0 && ownedPrerequisites.ContainsKey(Key) && ownedPrerequisites[Key].Count >= limit; var hasReachedLimit = limit > 0 && ownedPrerequisites.TryGetValue(Key, out var count) && count >= limit;
// The '!' annotation inverts prerequisites: "I'm buildable if this prerequisite *isn't* met" // The '!' annotation inverts prerequisites: "I'm buildable if this prerequisite *isn't* met"
var nowHasPrerequisites = HasPrerequisites(ownedPrerequisites) && !hasReachedLimit; var nowHasPrerequisites = !hasReachedLimit && HasPrerequisites(ownedPrerequisites);
var nowHidden = IsHidden(ownedPrerequisites); var nowHidden = IsHidden(ownedPrerequisites);
if (initialized == false) if (initialized == false)