From 7deefc5246f46aa10e88d7b778f2a8366023a146 Mon Sep 17 00:00:00 2001 From: Bob Date: Sun, 16 May 2010 17:27:19 +1200 Subject: [PATCH] debug (timing) spam, and perf fixed on SupportPower Build timing (un)hacked by chrisf --- OpenRA.FileFormats/Support/Timer.cs | 4 +- OpenRA.Game/Exts.cs | 15 +++++ OpenRA.Game/GameRules/ActorInfo.cs | 2 +- OpenRA.Game/OpenRA.Game.csproj | 3 +- OpenRA.Game/Traits/Player/TechTreeCache.cs | 69 ++++++++++++++++++++++ OpenRA.Game/Traits/SupportPower.cs | 29 +++++---- OpenRA.Game/World.cs | 36 ++++++++--- mods/ra/system.yaml | 1 + 8 files changed, 136 insertions(+), 23 deletions(-) create mode 100755 OpenRA.Game/Traits/Player/TechTreeCache.cs diff --git a/OpenRA.FileFormats/Support/Timer.cs b/OpenRA.FileFormats/Support/Timer.cs index b76d46d69d..d9b3e4d17d 100755 --- a/OpenRA.FileFormats/Support/Timer.cs +++ b/OpenRA.FileFormats/Support/Timer.cs @@ -28,7 +28,9 @@ namespace OpenRA.Support public static void Time( string message ) { var time = sw.ElapsedTime(); - Log.Write( message, time - lastTime ); + var dt = time - lastTime; + if( dt > 0.0001 ) + Log.Write( message, dt ); lastTime = time; } } diff --git a/OpenRA.Game/Exts.cs b/OpenRA.Game/Exts.cs index 4283f9b481..4326f05f2b 100644 --- a/OpenRA.Game/Exts.cs +++ b/OpenRA.Game/Exts.cs @@ -23,6 +23,7 @@ using System.Collections.Generic; using System.Linq; using OpenRA.GameRules; using OpenRA.Traits; +using OpenRA.Support; namespace OpenRA { @@ -92,5 +93,19 @@ namespace OpenRA var xs = ts.ToArray(); return xs[r.Next(xs.Length)]; } + + public static void DoTimed( this IEnumerable e, Action a, string text, double time ) + { + var sw = new Stopwatch(); + + e.Do( x => + { + var t = sw.ElapsedTime(); + a( x ); + var dt = sw.ElapsedTime() - t; + if( dt > time ) + Log.Write( text, x, dt*1000 ); + } ); + } } } diff --git a/OpenRA.Game/GameRules/ActorInfo.cs b/OpenRA.Game/GameRules/ActorInfo.cs index 6adc0db176..43ab71c937 100644 --- a/OpenRA.Game/GameRules/ActorInfo.cs +++ b/OpenRA.Game/GameRules/ActorInfo.cs @@ -87,7 +87,7 @@ namespace OpenRA.GameRules throw new InvalidOperationException( "Trait prerequisites not satisfied (or prerequisite loop)" ); var prereqs = PrerequisitesOf( t[ index ] ); - if( prereqs.Count == 0 || prereqs.All( n => ret.Any( x => x.GetType().IsSubclassOf( n ) ) ) ) + if( prereqs.Count == 0 || prereqs.All( n => ret.Any( x => x.GetType() == n || x.GetType().IsSubclassOf( n ) ) ) ) { ret.Add( t[ index ] ); t.RemoveAt( index ); diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 7a716137b1..6a5bb88a9b 100755 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -36,7 +36,7 @@ true bin\Debug\ - TRACE;DEBUG;SANITY_CHECKS + TRACE;DEBUG true full x86 @@ -87,6 +87,7 @@ + diff --git a/OpenRA.Game/Traits/Player/TechTreeCache.cs b/OpenRA.Game/Traits/Player/TechTreeCache.cs new file mode 100755 index 0000000000..3b476e856a --- /dev/null +++ b/OpenRA.Game/Traits/Player/TechTreeCache.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRA.GameRules; +using OpenRA.FileFormats; + +namespace OpenRA.Traits +{ + class TechTreeCacheInfo : TraitInfo { } + + class TechTreeCache : ITick + { + class Watcher + { + public readonly List prerequisites; + public readonly ITechTreeElement watcher; + bool hasPrerequisites; + + public Watcher(List prerequisites, ITechTreeElement watcher) + { + this.prerequisites = prerequisites; + this.watcher = watcher; + this.hasPrerequisites = false; + } + + public void Tick( Player owner, Cache> buildings ) + { + var effectivePrereq = prerequisites.Where( a => a.Traits.Get().Owner.Contains( owner.Country.Race ) ); + var nowHasPrerequisites = effectivePrereq.Any() && + effectivePrereq.All( a => buildings[ a.Name ].Any( b => !b.traits.Get().Disabled ) ); + + if( nowHasPrerequisites && !hasPrerequisites ) + watcher.Available(); + + if( !nowHasPrerequisites && hasPrerequisites ) + watcher.Unavailable(); + + hasPrerequisites = nowHasPrerequisites; + } + } + + readonly List watchers = new List(); + + public void Tick( Actor self ) + { + var buildings = Rules.TechTree.GatherBuildings( self.Owner ); + + foreach( var w in watchers ) + w.Tick( self.Owner, buildings ); + } + + public void Add( List prerequisites, ITechTreeElement tte ) + { + watchers.Add( new Watcher( prerequisites, tte ) ); + } + + public void Remove( ITechTreeElement tte ) + { + watchers.RemoveAll( x => x.watcher == tte ); + } + } + + interface ITechTreeElement + { + void Available(); + void Unavailable(); + } +} diff --git a/OpenRA.Game/Traits/SupportPower.cs b/OpenRA.Game/Traits/SupportPower.cs index e0f6b781dd..4eae60b823 100644 --- a/OpenRA.Game/Traits/SupportPower.cs +++ b/OpenRA.Game/Traits/SupportPower.cs @@ -22,7 +22,7 @@ using System.Linq; namespace OpenRA.Traits { - public abstract class SupportPowerInfo : ITraitInfo + public abstract class SupportPowerInfo : ITraitInfo, ITraitPrerequisite { public readonly bool RequiresPower = true; public readonly bool OneShot = false; @@ -46,7 +46,7 @@ namespace OpenRA.Traits public SupportPowerInfo() { OrderName = GetType().Name + "Order"; } } - public class SupportPower : ITick + public class SupportPower : ITick, ITechTreeElement { public readonly SupportPowerInfo Info; public int RemainingTime { get; private set; } @@ -64,6 +64,8 @@ namespace OpenRA.Traits Info = info; RemainingTime = TotalTime; Owner = self.Owner; + + self.traits.Get().Add( Info.Prerequisites.Select( a => Rules.Info[ a.ToLowerInvariant() ] ).ToList(), this ); } public void Tick(Actor self) @@ -71,17 +73,8 @@ namespace OpenRA.Traits if (Info.OneShot && IsUsed) return; - var buildings = Rules.TechTree.GatherBuildings(self.Owner); - var effectivePrereq = Info.Prerequisites - .Select(a => a.ToLowerInvariant()) - .Where(a => Rules.Info[a].Traits.Get().Owner.Contains(self.Owner.Country.Race)); - if (Info.GivenAuto) - { - IsAvailable = Info.TechLevel > -1 - && effectivePrereq.Any() - && effectivePrereq.All(a => buildings[a].Count > 0); - } + IsAvailable = Info.TechLevel > -1 && hasPrerequisites; if (IsAvailable && (!Info.RequiresPower || IsPowered())) { @@ -157,5 +150,17 @@ namespace OpenRA.Traits Sound.PlayToPlayer(Owner, Info.SelectTargetSound); OnActivate(); } + + bool hasPrerequisites; + + public void Available() + { + hasPrerequisites = true; + } + + public void Unavailable() + { + hasPrerequisites = false; + } } } diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index a16f3577a0..6b298f1065 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -135,22 +135,34 @@ namespace OpenRA public event Action ActorAdded = _ => { }; public event Action ActorRemoved = _ => { }; - + public void Tick() { - foreach (var a in actors) a.Tick(); + Timer.Time("----World Tick"); - Queries.WithTraitMultiple().Do(x => x.Trait.Tick(x.Actor)); + actors.DoTimed( x => x.Tick(), "expensive actor tick: {0} ({1:0.000})", 0.001 ); + Timer.Time(" actors: {0:0.000}"); - foreach (var e in effects) e.Tick( this ); + Queries.WithTraitMultiple().DoTimed( x => + { + x.Trait.Tick( x.Actor ); + Timer.Time( "trait tick \"{0}\": {{0}}".F( x.Trait.GetType().Name ) ); + }, "expensive trait tick: {0} ({1:0.000})", 0.001 ); + Timer.Time(" traits: {0:0.000}"); + + effects.DoTimed( e => e.Tick( this ), "expensive effect tick: {0} ({1:0.000})", 0.001 ); + Timer.Time(" effects: {0:0.000}"); Game.viewport.Tick(); + Timer.Time(" viewport: {0:0.000}"); var acts = frameEndActions; frameEndActions = new List>(); foreach (var a in acts) a(this); + Timer.Time(" frameEndActions: {0:0.000}"); WorldRenderer.Tick(); + Timer.Time(" worldrenderer: {0:0.000}"); } public IEnumerable Actors { get { return actors; } } @@ -164,11 +176,14 @@ namespace OpenRA public int SyncHash() { - int ret = 0; - foreach (var a in Actors) - ret += (int)a.ActorID * Sync.CalculateSyncHash(a); + //using (new PerfSample("synchash")) + { + int ret = 0; + foreach (var a in Actors) + ret += (int)a.ActorID * Sync.CalculateSyncHash(a); - return ret; + return ret; + } } public class AllQueries @@ -219,6 +234,11 @@ namespace OpenRA { public Actor Actor; public T Trait; + + public override string ToString() + { + return "{0}->{1}".F( Actor.Info.Name, Trait.GetType().Name ); + } } public class OwnedByCachedView : CachedView diff --git a/mods/ra/system.yaml b/mods/ra/system.yaml index d5962afd07..8f01ef46c5 100644 --- a/mods/ra/system.yaml +++ b/mods/ra/system.yaml @@ -3,6 +3,7 @@ Player: BuildSpeed: .04 LowPowerSlowdown: 3 PlaceBuilding: + TechTreeCache: GpsPower: Image: gpssicon OneShot: yes