Add FirstEnabledTraitOrDefault helper method.

This avoids the allocations caused by LINQ when using traits.FirstOrDefault(Exts.IsTraitEnabled). This is important in FrozenActorLayer.RefreshState which is called very often. We apply the new helper method to all areas using the old pattern. An overload that takes an array allows arrays to be enumerated without causing allocations.
This commit is contained in:
RoosterDragon
2017-11-17 19:10:03 +00:00
committed by Paul Chote
parent cb670d83b3
commit 7a7eed4fb7
8 changed files with 32 additions and 12 deletions

View File

@@ -503,6 +503,26 @@ namespace OpenRA
{
return IsTraitEnabled(t as object);
}
public static T FirstEnabledTraitOrDefault<T>(this IEnumerable<T> ts)
{
// PERF: Avoid LINQ.
foreach (var t in ts)
if (t.IsTraitEnabled())
return t;
return default(T);
}
public static T FirstEnabledTraitOrDefault<T>(this T[] ts)
{
// PERF: Avoid LINQ.
foreach (var t in ts)
if (t.IsTraitEnabled())
return t;
return default(T);
}
}
public static class Enum<T>

View File

@@ -103,7 +103,7 @@ namespace OpenRA.Traits
DamageState = health.DamageState;
}
var tooltip = tooltips.FirstOrDefault(Exts.IsTraitEnabled);
var tooltip = tooltips.FirstEnabledTraitOrDefault();
if (tooltip != null)
{
TooltipInfo = tooltip.TooltipInfo;

View File

@@ -26,7 +26,7 @@ namespace OpenRA.Mods.Common.Lint
if (buildable == null)
continue;
var tooltip = actorInfo.Value.TraitInfos<TooltipInfo>().FirstOrDefault(Exts.IsTraitEnabled);
var tooltip = actorInfo.Value.TraitInfos<TooltipInfo>().FirstEnabledTraitOrDefault();
if (tooltip == null)
emitError("The following buildable actor has no (enabled) Tooltip: " + actorInfo.Key);
}

View File

@@ -60,7 +60,7 @@ namespace OpenRA.Mods.Common.Traits.Render
if (conditionManager != null && !string.IsNullOrEmpty(info.Condition) && token == ConditionManager.InvalidConditionToken)
token = conditionManager.GrantCondition(self, info.Condition);
var wsb = wsbs.FirstOrDefault(Exts.IsTraitEnabled);
var wsb = wsbs.FirstEnabledTraitOrDefault();
if (wsb == null)
return;
@@ -80,7 +80,7 @@ namespace OpenRA.Mods.Common.Traits.Render
if (conditionManager != null && !string.IsNullOrEmpty(info.Condition) && token == ConditionManager.InvalidConditionToken)
token = conditionManager.GrantCondition(self, info.Condition);
var wsb = wsbs.FirstOrDefault(Exts.IsTraitEnabled);
var wsb = wsbs.FirstEnabledTraitOrDefault();
if (wsb == null)
return;
@@ -99,7 +99,7 @@ namespace OpenRA.Mods.Common.Traits.Render
{
Reverse(self, () =>
{
var wsb = wsbs.FirstOrDefault(Exts.IsTraitEnabled);
var wsb = wsbs.FirstEnabledTraitOrDefault();
// HACK: The actor remains alive and active for one tick before the followup activity
// (sell/transform/etc) runs. This causes visual glitches that we attempt to minimize

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Mods.Common.Traits.Render
var haveNeighbour = false;
foreach (var n in kv.Value)
{
var rb = init.World.Map.Rules.Actors[n].TraitInfos<IWallConnectorInfo>().FirstOrDefault(Exts.IsTraitEnabled);
var rb = init.World.Map.Rules.Actors[n].TraitInfos<IWallConnectorInfo>().FirstEnabledTraitOrDefault();
if (rb != null && rb.GetWallConnectionType() == Type)
{
haveNeighbour = true;
@@ -119,7 +119,7 @@ namespace OpenRA.Mods.Common.Traits.Render
foreach (var a in adjacentActors)
{
CVec facing;
var wc = a.TraitsImplementing<IWallConnector>().FirstOrDefault(Exts.IsTraitEnabled);
var wc = a.TraitsImplementing<IWallConnector>().FirstEnabledTraitOrDefault();
if (wc == null || !wc.AdjacentWallCanConnect(a, self.Location, wallInfo.Type, out facing))
continue;

View File

@@ -70,8 +70,8 @@ namespace OpenRA.Mods.Common.Traits
Footprint = new ReadOnlyDictionary<CPos, SubCell>(footprint);
}
var tooltip = Info.TraitInfos<EditorOnlyTooltipInfo>().FirstOrDefault(Exts.IsTraitEnabled) as TooltipInfoBase
?? Info.TraitInfos<TooltipInfo>().FirstOrDefault(Exts.IsTraitEnabled);
var tooltip = Info.TraitInfos<EditorOnlyTooltipInfo>().FirstEnabledTraitOrDefault() as TooltipInfoBase
?? Info.TraitInfos<TooltipInfo>().FirstEnabledTraitOrDefault();
Tooltip = (tooltip == null ? " < " + Info.Name + " >" : tooltip.Name) + "\n" + owner.Name + " (" + owner.Faction + ")"
+ "\nID: " + ID + "\nType: " + Info.Name;

View File

@@ -67,7 +67,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (actor == lastActor && hotkey == lastHotkey && pm.PowerState == lastPowerState)
return;
var tooltip = actor.TraitInfos<TooltipInfo>().FirstOrDefault(Exts.IsTraitEnabled);
var tooltip = actor.TraitInfos<TooltipInfo>().FirstEnabledTraitOrDefault();
var name = tooltip != null ? tooltip.Name : actor.Name;
var buildable = actor.TraitInfo<BuildableInfo>();
var cost = actor.TraitInfo<ValuedInfo>().Cost;
@@ -135,7 +135,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
ActorInfo ai;
if (rules.Actors.TryGetValue(a.ToLowerInvariant(), out ai))
{
var actorTooltip = ai.TraitInfos<TooltipInfo>().FirstOrDefault(Exts.IsTraitEnabled);
var actorTooltip = ai.TraitInfos<TooltipInfo>().FirstEnabledTraitOrDefault();
if (actorTooltip != null)
return actorTooltip.Name;
}

View File

@@ -235,7 +235,7 @@ namespace OpenRA.Mods.Common.Widgets
if (underCursor != null)
{
ActorTooltip = underCursor.TraitsImplementing<ITooltip>().FirstOrDefault(Exts.IsTraitEnabled);
ActorTooltip = underCursor.TraitsImplementing<ITooltip>().FirstEnabledTraitOrDefault();
if (ActorTooltip != null)
{
ActorTooltipExtra = underCursor.TraitsImplementing<IProvideTooltipInfo>().ToArray();