From 035834978d1ca9fada1bd478aadefa38cdb2f998 Mon Sep 17 00:00:00 2001 From: Pavlos Touboulidis Date: Wed, 23 Apr 2014 00:56:07 +0300 Subject: [PATCH 1/9] Make Stopwatch.ElapsedTime() a property and TimeSpan --- OpenRA.Game/Game.cs | 2 +- OpenRA.Game/Settings.cs | 4 ++-- OpenRA.Game/Support/PerfHistory.cs | 4 ++-- OpenRA.Game/Support/Stopwatch.cs | 9 +++++---- OpenRA.Game/Support/Timer.cs | 10 +++++----- OpenRA.Game/Traits/Util.cs | 6 +++--- OpenRA.Game/WorldUtils.cs | 10 +++++----- OpenRA.Mods.Cnc/CncLoadScreen.cs | 4 ++-- OpenRA.Mods.RA/DefaultLoadScreen.cs | 4 ++-- OpenRA.Mods.RA/World/DomainIndex.cs | 4 ++-- 10 files changed, 29 insertions(+), 28 deletions(-) diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index bcf50f1fd1..e7b89e8261 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -478,7 +478,7 @@ namespace OpenRA Tick(orderManager); - var waitTime = Math.Min(idealFrameTime - sw.ElapsedTime(), 1); + var waitTime = Math.Min(idealFrameTime - sw.Elapsed.TotalSeconds, 1); if (waitTime > 0) System.Threading.Thread.Sleep(TimeSpan.FromSeconds(waitTime)); } diff --git a/OpenRA.Game/Settings.cs b/OpenRA.Game/Settings.cs index ae463b48f4..813325a9bb 100644 --- a/OpenRA.Game/Settings.cs +++ b/OpenRA.Game/Settings.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -71,7 +71,7 @@ namespace OpenRA public bool BotDebug = false; public bool PerfText = false; public bool PerfGraph = false; - public float LongTickThreshold = 0.001f; + public TimeSpan LongTickThreshold = TimeSpan.FromMilliseconds(1d); public bool SanityCheckUnsyncedCode = false; public int Samples = 25; public bool IgnoreVersionMismatch = false; diff --git a/OpenRA.Game/Support/PerfHistory.cs b/OpenRA.Game/Support/PerfHistory.cs index 51d54dbfcc..a226904483 100644 --- a/OpenRA.Game/Support/PerfHistory.cs +++ b/OpenRA.Game/Support/PerfHistory.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -116,7 +116,7 @@ namespace OpenRA.Support public void Dispose() { - PerfHistory.Increment(Item, sw.ElapsedTime() * 1000); + PerfHistory.Increment(Item, sw.Elapsed.TotalMilliseconds); } } } diff --git a/OpenRA.Game/Support/Stopwatch.cs b/OpenRA.Game/Support/Stopwatch.cs index 22790e830f..76d2e5b3ae 100755 --- a/OpenRA.Game/Support/Stopwatch.cs +++ b/OpenRA.Game/Support/Stopwatch.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -13,14 +13,15 @@ namespace OpenRA.Support public class Stopwatch { System.Diagnostics.Stopwatch sw; - public Stopwatch () + + public Stopwatch() { Reset(); } - public double ElapsedTime() + public System.TimeSpan Elapsed { - return sw.Elapsed.TotalMilliseconds / 1000.0; + get { return this.sw.Elapsed; } } public void Reset() diff --git a/OpenRA.Game/Support/Timer.cs b/OpenRA.Game/Support/Timer.cs index 6463f7a1fe..9b3b42ee93 100755 --- a/OpenRA.Game/Support/Timer.cs +++ b/OpenRA.Game/Support/Timer.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -13,14 +13,14 @@ namespace OpenRA.Support public static class Timer { static Stopwatch sw = new Stopwatch(); - static double lastTime = 0; + static System.TimeSpan lastTime; public static void Time( string message ) { - var time = sw.ElapsedTime(); + var time = sw.Elapsed; var dt = time - lastTime; - if( dt > 0.0001 ) - Log.Write("perf", message, dt ); + if( dt.TotalSeconds > 0.0001 ) + Log.Write("perf", message, dt.TotalSeconds ); lastTime = time; } } diff --git a/OpenRA.Game/Traits/Util.cs b/OpenRA.Game/Traits/Util.cs index 6573964eca..0b347d4e67 100755 --- a/OpenRA.Game/Traits/Util.cs +++ b/OpenRA.Game/Traits/Util.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -83,9 +83,9 @@ namespace OpenRA.Traits var sw = new Stopwatch(); act = act.Tick(self); - var dt = sw.ElapsedTime(); + var dt = sw.Elapsed; if (dt > Game.Settings.Debug.LongTickThreshold) - Log.Write("perf", "[{2}] Activity: {0} ({1:0.000} ms)", prev, dt * 1000, Game.LocalTick); + Log.Write("perf", "[{2}] Activity: {0} ({1:0.000} ms)", prev, dt.TotalMilliseconds, Game.LocalTick); if (prev == act) break; diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index 7949f2f64f..23141fef10 100755 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -171,17 +171,17 @@ namespace OpenRA } } - public static void DoTimed(this IEnumerable e, Action a, string text, double time) + public static void DoTimed(this IEnumerable e, Action a, string text, TimeSpan time) { var sw = new Stopwatch(); e.Do(x => { - var t = sw.ElapsedTime(); + var t = sw.Elapsed; a(x); - var dt = sw.ElapsedTime() - t; + var dt = sw.Elapsed - t; if (dt > time) - Log.Write("perf", text, x, dt * 1000, Game.LocalTick); + Log.Write("perf", text, x, dt.TotalMilliseconds, Game.LocalTick); }); } diff --git a/OpenRA.Mods.Cnc/CncLoadScreen.cs b/OpenRA.Mods.Cnc/CncLoadScreen.cs index 06685d47dc..069768d494 100644 --- a/OpenRA.Mods.Cnc/CncLoadScreen.cs +++ b/OpenRA.Mods.Cnc/CncLoadScreen.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -76,7 +76,7 @@ namespace OpenRA.Mods.Cnc public void Display() { - if (r == null || loadTimer.ElapsedTime() < 0.25) + if (r == null || loadTimer.Elapsed.TotalSeconds < 0.25) return; loadTimer.Reset(); diff --git a/OpenRA.Mods.RA/DefaultLoadScreen.cs b/OpenRA.Mods.RA/DefaultLoadScreen.cs index 5d664e2988..ef9427ff1a 100644 --- a/OpenRA.Mods.RA/DefaultLoadScreen.cs +++ b/OpenRA.Mods.RA/DefaultLoadScreen.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -55,7 +55,7 @@ namespace OpenRA.Mods.RA return; // Update text at most every 0.5 seconds - if (lastUpdate.ElapsedTime() < 0.5) + if (lastUpdate.Elapsed.TotalSeconds < 0.5) return; if (r.Fonts == null) diff --git a/OpenRA.Mods.RA/World/DomainIndex.cs b/OpenRA.Mods.RA/World/DomainIndex.cs index dae2a6ca05..1b9dfec858 100644 --- a/OpenRA.Mods.RA/World/DomainIndex.cs +++ b/OpenRA.Mods.RA/World/DomainIndex.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -241,7 +241,7 @@ namespace OpenRA.Mods.RA domain += 1; } - Log.Write("debug", "{0}: Found {1} domains. Took {2} s", map.Title, domain-1, timer.ElapsedTime()); + Log.Write("debug", "{0}: Found {1} domains. Took {2} s", map.Title, domain-1, timer.Elapsed.TotalSeconds); } } } From 60732bd9bdb12fb46ae4d9c42a67378a954030ca Mon Sep 17 00:00:00 2001 From: Pavlos Touboulidis Date: Wed, 23 Apr 2014 01:58:30 +0300 Subject: [PATCH 2/9] Repurpose unused Timer.cs and add some loading perf metrics --- OpenRA.Game/Game.cs | 23 ++++++++++++++--- OpenRA.Game/ModData.cs | 12 ++++++--- OpenRA.Game/OpenRA.Game.csproj | 2 +- OpenRA.Game/Support/PerfTimer.cs | 42 ++++++++++++++++++++++++++++++++ OpenRA.Game/Support/Timer.cs | 27 -------------------- 5 files changed, 71 insertions(+), 35 deletions(-) create mode 100755 OpenRA.Game/Support/PerfTimer.cs delete mode 100755 OpenRA.Game/Support/Timer.cs diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index e7b89e8261..9c949622c7 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -246,11 +246,18 @@ namespace OpenRA { BeforeGameStart(); - var map = modData.PrepareMap(mapUID); + Map map; + using (new PerfTimer("PrepareMap")) + { + map = modData.PrepareMap(mapUID); + } orderManager.world = new World(modData.Manifest, map, orderManager, isShellmap); orderManager.world.Timestep = Timestep; worldRenderer = new WorldRenderer(orderManager.world); - orderManager.world.LoadComplete(worldRenderer); + using (new PerfTimer("LoadComplete")) + { + orderManager.world.LoadComplete(worldRenderer); + } if (orderManager.GameStarted) return; @@ -385,7 +392,10 @@ namespace OpenRA modData = new ModData(mod); Renderer.InitializeFonts(modData.Manifest); modData.InitializeLoaders(); - modData.MapCache.LoadMaps(); + using (new PerfTimer("LoadMaps")) + { + modData.MapCache.LoadMaps(); + } PerfHistory.items["render"].hasNormalTick = false; PerfHistory.items["batches"].hasNormalTick = false; @@ -436,7 +446,12 @@ namespace OpenRA public static void LoadShellMap() { - StartGame(ChooseShellmap(), true); + string shellMap = ChooseShellmap(); + + using (new PerfTimer("StartGame")) + { + StartGame(shellMap, true); + } } static string ChooseShellmap() diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index b65d8ed0d3..0ca48529f3 100755 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -118,11 +118,17 @@ namespace OpenRA // Mount map package so custom assets can be used. TODO: check priority. GlobalFileSystem.Mount(GlobalFileSystem.OpenPackage(map.Path, null, int.MaxValue)); - Rules.LoadRules(Manifest, map); + using (new Support.PerfTimer("LoadRules")) + { + Rules.LoadRules(Manifest, map); + } SpriteLoader = new SpriteLoader(Rules.TileSets[map.Tileset].Extensions, SheetBuilder); - // TODO: Don't load the sequences for assets that are not used in this tileset. Maybe use the existing EditorTilesetFilters. - SequenceProvider.Initialize(Manifest.Sequences, map.Sequences); + using (new Support.PerfTimer("SequenceProvider.Initialize")) + { + // TODO: Don't load the sequences for assets that are not used in this tileset. Maybe use the existing EditorTilesetFilters. + SequenceProvider.Initialize(Manifest.Sequences, map.Sequences); + } VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequences); return map; } diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 4d5b9a6e57..3447fecd9c 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -293,7 +293,7 @@ - + diff --git a/OpenRA.Game/Support/PerfTimer.cs b/OpenRA.Game/Support/PerfTimer.cs new file mode 100755 index 0000000000..c674d55fe5 --- /dev/null +++ b/OpenRA.Game/Support/PerfTimer.cs @@ -0,0 +1,42 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; + +namespace OpenRA.Support +{ + public class PerfTimer : IDisposable + { + readonly Stopwatch sw = new Stopwatch(); + readonly string Name; + static System.Threading.ThreadLocal depth = new System.Threading.ThreadLocal(); + + public PerfTimer(string name) + { + this.Name = name; + depth.Value++; + } + + public void Dispose() + { + string indentation; + + if (--depth.Value >= 0) + indentation = new string('\t', depth.Value); + else + { + depth.Value = 0; + indentation = string.Empty; + } + + Log.Write("perf", "{0}{1}: {2} ms", indentation, this.Name, Math.Round(this.sw.Elapsed.TotalMilliseconds)); + } + } +} diff --git a/OpenRA.Game/Support/Timer.cs b/OpenRA.Game/Support/Timer.cs deleted file mode 100755 index 9b3b42ee93..0000000000 --- a/OpenRA.Game/Support/Timer.cs +++ /dev/null @@ -1,27 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -namespace OpenRA.Support -{ - public static class Timer - { - static Stopwatch sw = new Stopwatch(); - static System.TimeSpan lastTime; - - public static void Time( string message ) - { - var time = sw.Elapsed; - var dt = time - lastTime; - if( dt.TotalSeconds > 0.0001 ) - Log.Write("perf", message, dt.TotalSeconds ); - lastTime = time; - } - } -} From c44d73d5816bd79b5953bc58fda7246a7e7ddfe8 Mon Sep 17 00:00:00 2001 From: Pavlos Touboulidis Date: Wed, 23 Apr 2014 03:42:27 +0300 Subject: [PATCH 3/9] Improve PerfTimer output --- OpenRA.Game/Support/PerfTimer.cs | 43 ++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/OpenRA.Game/Support/PerfTimer.cs b/OpenRA.Game/Support/PerfTimer.cs index c674d55fe5..b574e8243b 100755 --- a/OpenRA.Game/Support/PerfTimer.cs +++ b/OpenRA.Game/Support/PerfTimer.cs @@ -9,6 +9,7 @@ #endregion using System; +using System.Linq; namespace OpenRA.Support { @@ -16,27 +17,53 @@ namespace OpenRA.Support { readonly Stopwatch sw = new Stopwatch(); readonly string Name; + + // Hacks to give the output a tree-like structure static System.Threading.ThreadLocal depth = new System.Threading.ThreadLocal(); + static System.Threading.ThreadLocal prevHeader = new System.Threading.ThreadLocal(); public PerfTimer(string name) { + if (prevHeader.Value != null) + { + Log.Write("perf", prevHeader.Value); + prevHeader.Value = null; + } + this.Name = name; + + prevHeader.Value = string.Format("{0}{1}", Indentation, this.Name); depth.Value++; } + private static string Indentation + { + get + { + var d = depth.Value; + if (d == 1) + return "| "; + else if (d <= 0) + return string.Empty; + else + return string.Concat(Enumerable.Repeat("| ", depth.Value)); + } + } + public void Dispose() { - string indentation; - - if (--depth.Value >= 0) - indentation = new string('\t', depth.Value); + string format; + if (prevHeader.Value == null) + { + format = "{0}: {2} ms"; + } else { - depth.Value = 0; - indentation = string.Empty; + format = "{0}{1}: {2} ms"; + prevHeader.Value = null; } - - Log.Write("perf", "{0}{1}: {2} ms", indentation, this.Name, Math.Round(this.sw.Elapsed.TotalMilliseconds)); + depth.Value--; + Log.Write("perf", format, Indentation, this.Name, Math.Round(this.sw.Elapsed.TotalMilliseconds)); } } } From 2d8cd8299f8aa18108558bb89d9fc851b3fcbfc6 Mon Sep 17 00:00:00 2001 From: Pavlos Touboulidis Date: Wed, 23 Apr 2014 03:43:46 +0300 Subject: [PATCH 4/9] Add more perf measurements --- OpenRA.Game/Game.cs | 7 +++++-- OpenRA.Game/Map/MapCache.cs | 9 ++++++--- OpenRA.Game/World.cs | 5 ++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 9c949622c7..9eb2cccc13 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -251,8 +251,11 @@ namespace OpenRA { map = modData.PrepareMap(mapUID); } - orderManager.world = new World(modData.Manifest, map, orderManager, isShellmap); - orderManager.world.Timestep = Timestep; + using (new PerfTimer("NewWorld")) + { + orderManager.world = new World(modData.Manifest, map, orderManager, isShellmap); + orderManager.world.Timestep = Timestep; + } worldRenderer = new WorldRenderer(orderManager.world); using (new PerfTimer("LoadComplete")) { diff --git a/OpenRA.Game/Map/MapCache.cs b/OpenRA.Game/Map/MapCache.cs index d745bf39e3..135ab6ce10 100755 --- a/OpenRA.Game/Map/MapCache.cs +++ b/OpenRA.Game/Map/MapCache.cs @@ -47,9 +47,12 @@ namespace OpenRA { try { - var map = new Map(path, manifest.Mod.Id); - if (manifest.MapCompatibility.Contains(map.RequiresMod)) - previews[map.Uid].UpdateFromMap(map); + using (new Support.PerfTimer(path)) + { + var map = new Map(path, manifest.Mod.Id); + if (manifest.MapCompatibility.Contains(map.RequiresMod)) + previews[map.Uid].UpdateFromMap(map); + } } catch (Exception e) { diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 30e9ae7de2..1d1d12213a 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -148,7 +148,10 @@ namespace OpenRA public void LoadComplete(WorldRenderer wr) { foreach (var wlh in WorldActor.TraitsImplementing()) - wlh.WorldLoaded(this, wr); + { + using (new Support.PerfTimer(wlh.GetType().Name + ".WorldLoaded")) + wlh.WorldLoaded(this, wr); + } } public Actor CreateActor(string name, TypeDictionary initDict) From 9dc2b3cd7625dec59d8b6a531aee8e170df22532 Mon Sep 17 00:00:00 2001 From: Pavlos Touboulidis Date: Wed, 23 Apr 2014 03:48:49 +0300 Subject: [PATCH 5/9] Optimize ComputeHash by removing Concat() and ToArray() calls --- OpenRA.Game/Map/Map.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 2c878bbeca..8e8bf27b4b 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -431,13 +431,20 @@ namespace OpenRA string ComputeHash() { // UID is calculated by taking an SHA1 of the yaml and binary data - // Read the relevant data into a buffer - var data = Container.GetContent("map.yaml").ReadAllBytes() - .Concat(Container.GetContent("map.bin").ReadAllBytes()).ToArray(); - // Take the SHA1 - using (var csp = SHA1.Create()) - return new string(csp.ComputeHash(data).SelectMany(a => a.ToString("x2")).ToArray()); + using (var ms = new MemoryStream()) + { + // Read the relevant data into the buffer + using (var s = Container.GetContent("map.yaml")) + s.CopyTo(ms); + using (var s = Container.GetContent("map.bin")) + s.CopyTo(ms); + + // Take the SHA1 + ms.Seek(0, SeekOrigin.Begin); + using (var csp = SHA1.Create()) + return new string(csp.ComputeHash(ms).SelectMany(a => a.ToString("x2")).ToArray()); + } } public void MakeDefaultPlayers() From 36a660385c060e02a0f973056a3f25d6054c50a8 Mon Sep 17 00:00:00 2001 From: Pavlos Touboulidis Date: Wed, 23 Apr 2014 13:22:14 +0300 Subject: [PATCH 6/9] Fix OpenRA.Lint throwing because "perf" log channel does not exist Slightly modified the Log class to allow dummy channels that don't write anywhere, then use it on Lint because map loading writes to the "perf" channel. --- OpenRA.Game/Support/Log.cs | 9 +++++++++ OpenRA.Lint/YamlChecker.cs | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/OpenRA.Game/Support/Log.cs b/OpenRA.Game/Support/Log.cs index 19c62e07eb..b837815a96 100755 --- a/OpenRA.Game/Support/Log.cs +++ b/OpenRA.Game/Support/Log.cs @@ -46,6 +46,12 @@ namespace OpenRA { if (Channels.ContainsKey(channelName)) return; + if (string.IsNullOrEmpty(baseFilename)) + { + Channels.Add(channelName, new ChannelInfo()); + return; + } + foreach (var filename in FilenamesForChannel(channelName, baseFilename)) try { @@ -70,6 +76,9 @@ namespace OpenRA if (!Channels.TryGetValue(channel, out info)) throw new Exception("Tried logging to non-existant channel " + channel); + if (info.Writer == null) + return; + info.Writer.WriteLine(format, args); } } diff --git a/OpenRA.Lint/YamlChecker.cs b/OpenRA.Lint/YamlChecker.cs index 61ded227c4..979c09176e 100644 --- a/OpenRA.Lint/YamlChecker.cs +++ b/OpenRA.Lint/YamlChecker.cs @@ -6,6 +6,9 @@ * as published by the Free Software Foundation. For more information, * see COPYING. */ +using System.IO; + + #endregion using System; @@ -41,6 +44,8 @@ namespace OpenRA.Lint try { + Log.AddChannel("perf", null); + var options = args.Where(a => a.StartsWith("-")); var mod = args.Where(a => !options.Contains(a)).First(); var map = args.Where(a => !options.Contains(a)).Skip(1).FirstOrDefault(); From c17f70677271280d5a0a52e017b07bde908f5032 Mon Sep 17 00:00:00 2001 From: Pavlos Touboulidis Date: Wed, 23 Apr 2014 16:52:52 +0300 Subject: [PATCH 7/9] Prettier PerfTimer output --- OpenRA.Game/Support/PerfTimer.cs | 85 +++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 19 deletions(-) diff --git a/OpenRA.Game/Support/PerfTimer.cs b/OpenRA.Game/Support/PerfTimer.cs index b574e8243b..9dc461cd5a 100755 --- a/OpenRA.Game/Support/PerfTimer.cs +++ b/OpenRA.Game/Support/PerfTimer.cs @@ -18,9 +18,15 @@ namespace OpenRA.Support readonly Stopwatch sw = new Stopwatch(); readonly string Name; + // // Hacks to give the output a tree-like structure + // static System.Threading.ThreadLocal depth = new System.Threading.ThreadLocal(); static System.Threading.ThreadLocal prevHeader = new System.Threading.ThreadLocal(); + const int MaxWidth = 60, Digits = 6; + const int MaxIndentedLabel = MaxWidth - Digits; + const string IndentationString = "| "; + readonly string FormatString = "{0," + MaxIndentedLabel + "} {1," + Digits + "} ms"; public PerfTimer(string name) { @@ -32,38 +38,79 @@ namespace OpenRA.Support this.Name = name; - prevHeader.Value = string.Format("{0}{1}", Indentation, this.Name); + prevHeader.Value = GetHeader(Indentation, this.Name); depth.Value++; } + public void Dispose() + { + depth.Value--; + + string s; + + if (prevHeader.Value == null) + { + s = GetFooter(Indentation); + } + else + { + s = GetOneLiner(Indentation, this.Name); + prevHeader.Value = null; + } + + Log.Write("perf", FormatString, s, Math.Round(this.sw.Elapsed.TotalMilliseconds)); + } + + private static string GetHeader(string indentation, string label) + { + return string.Concat(indentation, LimitLength(label, MaxIndentedLabel - indentation.Length)); + } + + private static string GetOneLiner(string indentation, string label) + { + return string.Concat(indentation, SetLength(label, MaxIndentedLabel - indentation.Length)); + } + + private static string GetFooter(string indentation) + { + return string.Concat(indentation, new string('-', MaxIndentedLabel - indentation.Length)); + } + + private static string LimitLength(string s, int length, int minLength = 8) + { + length = Math.Max(length, minLength); + + if (s == null || s.Length <= length) + return s; + + return s.Substring(0, length); + } + + private static string SetLength(string s, int length, int minLength = 8) + { + length = Math.Max(length, minLength); + + if (s == null || s.Length == length) + return s; + + if (s.Length < length) + return s.PadRight(length); + + return s.Substring(0, length); + } + private static string Indentation { get { var d = depth.Value; if (d == 1) - return "| "; + return IndentationString; else if (d <= 0) return string.Empty; else - return string.Concat(Enumerable.Repeat("| ", depth.Value)); + return string.Concat(Enumerable.Repeat(IndentationString, depth.Value)); } } - - public void Dispose() - { - string format; - if (prevHeader.Value == null) - { - format = "{0}: {2} ms"; - } - else - { - format = "{0}{1}: {2} ms"; - prevHeader.Value = null; - } - depth.Value--; - Log.Write("perf", format, Indentation, this.Name, Math.Round(this.sw.Elapsed.TotalMilliseconds)); - } } } From 603dd1d8663814500f4828bc87a76573d18bee77 Mon Sep 17 00:00:00 2001 From: Pavlos Touboulidis Date: Thu, 24 Apr 2014 18:14:03 +0300 Subject: [PATCH 8/9] Style fixes --- OpenRA.Game/Game.cs | 12 ++---------- OpenRA.Game/ModData.cs | 2 -- OpenRA.Game/Support/PerfTimer.cs | 12 ++++++------ OpenRA.Lint/YamlChecker.cs | 4 +--- 4 files changed, 9 insertions(+), 21 deletions(-) diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 9eb2cccc13..b01405c989 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -248,9 +248,7 @@ namespace OpenRA Map map; using (new PerfTimer("PrepareMap")) - { map = modData.PrepareMap(mapUID); - } using (new PerfTimer("NewWorld")) { orderManager.world = new World(modData.Manifest, map, orderManager, isShellmap); @@ -258,9 +256,7 @@ namespace OpenRA } worldRenderer = new WorldRenderer(orderManager.world); using (new PerfTimer("LoadComplete")) - { orderManager.world.LoadComplete(worldRenderer); - } if (orderManager.GameStarted) return; @@ -396,9 +392,7 @@ namespace OpenRA Renderer.InitializeFonts(modData.Manifest); modData.InitializeLoaders(); using (new PerfTimer("LoadMaps")) - { modData.MapCache.LoadMaps(); - } PerfHistory.items["render"].hasNormalTick = false; PerfHistory.items["batches"].hasNormalTick = false; @@ -449,12 +443,10 @@ namespace OpenRA public static void LoadShellMap() { - string shellMap = ChooseShellmap(); + var shellmap = ChooseShellmap(); using (new PerfTimer("StartGame")) - { - StartGame(shellMap, true); - } + StartGame(shellmap, true); } static string ChooseShellmap() diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index 0ca48529f3..6bc9db8e54 100755 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -119,9 +119,7 @@ namespace OpenRA GlobalFileSystem.Mount(GlobalFileSystem.OpenPackage(map.Path, null, int.MaxValue)); using (new Support.PerfTimer("LoadRules")) - { Rules.LoadRules(Manifest, map); - } SpriteLoader = new SpriteLoader(Rules.TileSets[map.Tileset].Extensions, SheetBuilder); using (new Support.PerfTimer("SequenceProvider.Initialize")) diff --git a/OpenRA.Game/Support/PerfTimer.cs b/OpenRA.Game/Support/PerfTimer.cs index 9dc461cd5a..43ed9ba8e6 100755 --- a/OpenRA.Game/Support/PerfTimer.cs +++ b/OpenRA.Game/Support/PerfTimer.cs @@ -61,22 +61,22 @@ namespace OpenRA.Support Log.Write("perf", FormatString, s, Math.Round(this.sw.Elapsed.TotalMilliseconds)); } - private static string GetHeader(string indentation, string label) + static string GetHeader(string indentation, string label) { return string.Concat(indentation, LimitLength(label, MaxIndentedLabel - indentation.Length)); } - private static string GetOneLiner(string indentation, string label) + static string GetOneLiner(string indentation, string label) { return string.Concat(indentation, SetLength(label, MaxIndentedLabel - indentation.Length)); } - private static string GetFooter(string indentation) + static string GetFooter(string indentation) { return string.Concat(indentation, new string('-', MaxIndentedLabel - indentation.Length)); } - private static string LimitLength(string s, int length, int minLength = 8) + static string LimitLength(string s, int length, int minLength = 8) { length = Math.Max(length, minLength); @@ -86,7 +86,7 @@ namespace OpenRA.Support return s.Substring(0, length); } - private static string SetLength(string s, int length, int minLength = 8) + static string SetLength(string s, int length, int minLength = 8) { length = Math.Max(length, minLength); @@ -99,7 +99,7 @@ namespace OpenRA.Support return s.Substring(0, length); } - private static string Indentation + static string Indentation { get { diff --git a/OpenRA.Lint/YamlChecker.cs b/OpenRA.Lint/YamlChecker.cs index 979c09176e..2dfa8d1c1d 100644 --- a/OpenRA.Lint/YamlChecker.cs +++ b/OpenRA.Lint/YamlChecker.cs @@ -6,14 +6,12 @@ * as published by the Free Software Foundation. For more information, * see COPYING. */ -using System.IO; - - #endregion using System; using System.Collections.Generic; using System.Linq; +using System.IO; using OpenRA.FileSystem; using OpenRA.Traits; From e6dddf37041e1916b4a97c2ea03559cd3a97919c Mon Sep 17 00:00:00 2001 From: Pavlos Touboulidis Date: Sat, 26 Apr 2014 02:05:06 +0300 Subject: [PATCH 9/9] Style fixes --- OpenRA.Game/Support/PerfTimer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenRA.Game/Support/PerfTimer.cs b/OpenRA.Game/Support/PerfTimer.cs index 43ed9ba8e6..8fdb4ea5a7 100755 --- a/OpenRA.Game/Support/PerfTimer.cs +++ b/OpenRA.Game/Support/PerfTimer.cs @@ -10,6 +10,7 @@ using System; using System.Linq; +using System.Threading; namespace OpenRA.Support { @@ -21,8 +22,8 @@ namespace OpenRA.Support // // Hacks to give the output a tree-like structure // - static System.Threading.ThreadLocal depth = new System.Threading.ThreadLocal(); - static System.Threading.ThreadLocal prevHeader = new System.Threading.ThreadLocal(); + static ThreadLocal depth = new ThreadLocal(); + static ThreadLocal prevHeader = new ThreadLocal(); const int MaxWidth = 60, Digits = 6; const int MaxIndentedLabel = MaxWidth - Digits; const string IndentationString = "| ";