From 6b9bd1cbbc573604ba970ea28260ddd2098eb123 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Wed, 9 Sep 2015 22:56:53 +0100 Subject: [PATCH] Eagerly cache traits in Actor. In this case, removing the lazy generation buys us more performance in removing the overhead of accessing these values than we lose from avoided computation when these values are never accessed. --- OpenRA.Game/Actor.cs | 105 ++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index c7605549bc..48833218f2 100644 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -40,34 +40,38 @@ namespace OpenRA public Group Group; public int Generation; - Lazy bounds; - Lazy visualBounds; - Lazy facing; - Lazy health; - Lazy occupySpace; - Lazy effectiveOwner; - - public Rectangle Bounds { get { return bounds.Value; } } - public Rectangle VisualBounds { get { return visualBounds.Value; } } - public IOccupySpace OccupiesSpace { get { return occupySpace.Value; } } - public IEffectiveOwner EffectiveOwner { get { return effectiveOwner.Value; } } + public Rectangle Bounds { get; private set; } + public Rectangle VisualBounds { get; private set; } + public IEffectiveOwner EffectiveOwner { get; private set; } + public IOccupySpace OccupiesSpace + { + get + { + if (occupySpace == null) + occupySpace = Trait(); + return occupySpace; + } + } public bool IsIdle { get { return currentActivity == null; } } - public bool IsDead { get { return Disposed || (health.Value == null ? false : health.Value.IsDead); } } + public bool IsDead { get { return Disposed || (health != null && health.IsDead); } } - public CPos Location { get { return occupySpace.Value.TopLeft; } } - public WPos CenterPosition { get { return occupySpace.Value.CenterPosition; } } + public CPos Location { get { return OccupiesSpace.TopLeft; } } + public WPos CenterPosition { get { return OccupiesSpace.CenterPosition; } } public WRot Orientation { get { // TODO: Support non-zero pitch/roll in IFacing (IOrientation?) - var facingValue = facing.Value != null ? facing.Value.Facing : 0; + var facingValue = facing != null ? facing.Facing : 0; return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facingValue)); } } + IOccupySpace occupySpace; + readonly IFacing facing; + readonly Health health; readonly IRenderModifier[] renderModifiers; readonly IRender[] renders; readonly IDisable[] disables; @@ -83,8 +87,6 @@ namespace OpenRA if (initDict.Contains()) Owner = init.Get(); - occupySpace = Exts.Lazy(() => TraitOrDefault()); - if (name != null) { name = name.ToLowerInvariant(); @@ -97,38 +99,11 @@ namespace OpenRA AddTrait(trait.Create(init)); } - facing = Exts.Lazy(() => TraitOrDefault()); - health = Exts.Lazy(() => TraitOrDefault()); - effectiveOwner = Exts.Lazy(() => TraitOrDefault()); - - bounds = Exts.Lazy(() => - { - var si = Info.TraitInfoOrDefault(); - var size = (si != null && si.Bounds != null) ? new int2(si.Bounds[0], si.Bounds[1]) : - TraitsImplementing().Select(x => x.SelectionSize(this)).FirstOrDefault(); - - var offset = -size / 2; - if (si != null && si.Bounds != null && si.Bounds.Length > 2) - offset += new int2(si.Bounds[2], si.Bounds[3]); - - return new Rectangle(offset.X, offset.Y, size.X, size.Y); - }); - - visualBounds = Exts.Lazy(() => - { - var sd = Info.TraitInfoOrDefault(); - if (sd == null || sd.SelectionBoxBounds == null) - return bounds.Value; - - var size = new int2(sd.SelectionBoxBounds[0], sd.SelectionBoxBounds[1]); - - var offset = -size / 2; - if (sd.SelectionBoxBounds.Length > 2) - offset += new int2(sd.SelectionBoxBounds[2], sd.SelectionBoxBounds[3]); - - return new Rectangle(offset.X, offset.Y, size.X, size.Y); - }); - + Bounds = DetermineBounds(); + VisualBounds = DetermineVisualBounds(); + EffectiveOwner = TraitOrDefault(); + facing = TraitOrDefault(); + health = TraitOrDefault(); renderModifiers = TraitsImplementing().ToArray(); renders = TraitsImplementing().ToArray(); disables = TraitsImplementing().ToArray(); @@ -136,6 +111,34 @@ namespace OpenRA defaultVisibility = Trait(); } + Rectangle DetermineBounds() + { + var si = Info.TraitInfoOrDefault(); + var size = (si != null && si.Bounds != null) ? new int2(si.Bounds[0], si.Bounds[1]) : + TraitsImplementing().Select(x => x.SelectionSize(this)).FirstOrDefault(); + + var offset = -size / 2; + if (si != null && si.Bounds != null && si.Bounds.Length > 2) + offset += new int2(si.Bounds[2], si.Bounds[3]); + + return new Rectangle(offset.X, offset.Y, size.X, size.Y); + } + + Rectangle DetermineVisualBounds() + { + var sd = Info.TraitInfoOrDefault(); + if (sd == null || sd.SelectionBoxBounds == null) + return Bounds; + + var size = new int2(sd.SelectionBoxBounds[0], sd.SelectionBoxBounds[1]); + + var offset = -size / 2; + if (sd.SelectionBoxBounds.Length > 2) + offset += new int2(sd.SelectionBoxBounds[2], sd.SelectionBoxBounds[3]); + + return new Rectangle(offset.X, offset.Y, size.X, size.Y); + } + public void Tick() { var wasIdle = IsIdle; @@ -280,10 +283,10 @@ namespace OpenRA public void Kill(Actor attacker) { - if (health.Value == null) + if (health == null) return; - health.Value.InflictDamage(this, attacker, health.Value.MaxHP, null, true); + health.InflictDamage(this, attacker, health.MaxHP, null, true); } public bool IsDisabled()