From 2ec6df9680f390263897b179510c011997c963c1 Mon Sep 17 00:00:00 2001 From: Pavlos Touboulidis Date: Sun, 11 May 2014 05:55:38 +0300 Subject: [PATCH] Fix strange d2k loading slowness There is a strange issue that appears* when Theater calls ISpriteFrame.Frames on the R8Reader. The R8Reader uses IEnumerable.Cast<> which behaves slower and slower, which makes map loading become 10+ times slower. The changes here simply avoid the casting. [*] This happens at least on Linux x86_64 with Mono 3.2.8. See https://bugzilla.xamarin.com/show_bug.cgi?id=19668 --- OpenRA.Game/FileFormats/R8Reader.cs | 4 ++-- OpenRA.Game/FileFormats/ShpD2Reader.cs | 6 +++--- OpenRA.Game/FileFormats/ShpReader.cs | 6 +++++- OpenRA.Game/FileFormats/ShpTSReader.cs | 6 +++++- OpenRA.Game/FileFormats/TmpRAReader.cs | 4 ++-- OpenRA.Game/FileFormats/TmpTDReader.cs | 4 ++-- OpenRA.Game/FileFormats/TmpTSReader.cs | 4 ++-- OpenRA.Game/Graphics/SpriteSource.cs | 1 + 8 files changed, 22 insertions(+), 13 deletions(-) diff --git a/OpenRA.Game/FileFormats/R8Reader.cs b/OpenRA.Game/FileFormats/R8Reader.cs index bb1da936e9..ee5bb0a85d 100644 --- a/OpenRA.Game/FileFormats/R8Reader.cs +++ b/OpenRA.Game/FileFormats/R8Reader.cs @@ -62,8 +62,8 @@ namespace OpenRA.FileFormats public class R8Reader : ISpriteSource { - readonly List frames = new List(); - public IEnumerable Frames { get { return frames.Cast(); } } + readonly List frames = new List(); + public IEnumerable Frames { get { return frames; } } public bool CacheWhenLoadingTileset { get { return true; } } public readonly int ImageCount; diff --git a/OpenRA.Game/FileFormats/ShpD2Reader.cs b/OpenRA.Game/FileFormats/ShpD2Reader.cs index 095fb90f12..3a675f7132 100644 --- a/OpenRA.Game/FileFormats/ShpD2Reader.cs +++ b/OpenRA.Game/FileFormats/ShpD2Reader.cs @@ -86,8 +86,8 @@ namespace OpenRA.FileFormats public class ShpD2Reader : ISpriteSource { - List headers = new List(); - public IEnumerable Frames { get { return headers.Cast(); } } + readonly List frames = new List(); + public IEnumerable Frames { get { return frames; } } public bool CacheWhenLoadingTileset { get { return false; } } public ShpD2Reader(Stream s) @@ -108,7 +108,7 @@ namespace OpenRA.FileFormats for (var i = 0; i < imageCount; i++) { s.Position = offsets[i]; - headers.Add(new Frame(s)); + frames.Add(new Frame(s)); } } } diff --git a/OpenRA.Game/FileFormats/ShpReader.cs b/OpenRA.Game/FileFormats/ShpReader.cs index e239c5616a..22e2443d18 100644 --- a/OpenRA.Game/FileFormats/ShpReader.cs +++ b/OpenRA.Game/FileFormats/ShpReader.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -58,7 +59,8 @@ namespace OpenRA.FileFormats public class ShpReader : ISpriteSource { readonly List headers = new List(); - public IEnumerable Frames { get { return headers.Cast(); } } + Lazy> spriteFrames; + public IEnumerable Frames { get { return spriteFrames.Value; } } public bool CacheWhenLoadingTileset { get { return false; } } public readonly Size Size; @@ -93,6 +95,8 @@ namespace OpenRA.FileFormats foreach (var h in headers) Decompress(stream, h); + + spriteFrames = Exts.Lazy(() => headers.Cast()); } static byte[] ReadCompressedData(Stream stream, ImageHeader h) diff --git a/OpenRA.Game/FileFormats/ShpTSReader.cs b/OpenRA.Game/FileFormats/ShpTSReader.cs index 8fdaf78348..ea10a4e209 100644 --- a/OpenRA.Game/FileFormats/ShpTSReader.cs +++ b/OpenRA.Game/FileFormats/ShpTSReader.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -46,7 +47,8 @@ namespace OpenRA.FileFormats public class ShpTSReader : ISpriteSource { readonly List frames = new List(); - public IEnumerable Frames { get { return frames.Cast(); } } + Lazy> spriteFrames; + public IEnumerable Frames { get { return spriteFrames.Value; } } public bool CacheWhenLoadingTileset { get { return false; } } public ShpTSReader(Stream stream) @@ -95,6 +97,8 @@ namespace OpenRA.FileFormats } } } + + spriteFrames = Exts.Lazy(() => frames.Cast()); } } } \ No newline at end of file diff --git a/OpenRA.Game/FileFormats/TmpRAReader.cs b/OpenRA.Game/FileFormats/TmpRAReader.cs index f9ab49628b..e83b9b80d7 100644 --- a/OpenRA.Game/FileFormats/TmpRAReader.cs +++ b/OpenRA.Game/FileFormats/TmpRAReader.cs @@ -18,8 +18,8 @@ namespace OpenRA.FileFormats { public class TmpRAReader : ISpriteSource { - readonly List tiles = new List(); - public IEnumerable Frames { get { return tiles.Cast(); } } + readonly List tiles = new List(); + public IEnumerable Frames { get { return tiles; } } public bool CacheWhenLoadingTileset { get { return false; } } public TmpRAReader(Stream s) diff --git a/OpenRA.Game/FileFormats/TmpTDReader.cs b/OpenRA.Game/FileFormats/TmpTDReader.cs index 7a6002a92e..14f79ea2b8 100644 --- a/OpenRA.Game/FileFormats/TmpTDReader.cs +++ b/OpenRA.Game/FileFormats/TmpTDReader.cs @@ -37,8 +37,8 @@ namespace OpenRA.FileFormats public class TmpTDReader : ISpriteSource { - readonly List tiles = new List(); - public IEnumerable Frames { get { return tiles.Cast(); } } + readonly List tiles = new List(); + public IEnumerable Frames { get { return tiles; } } public bool CacheWhenLoadingTileset { get { return false; } } public TmpTDReader(Stream s) diff --git a/OpenRA.Game/FileFormats/TmpTSReader.cs b/OpenRA.Game/FileFormats/TmpTSReader.cs index 402d38500b..4c902874d9 100644 --- a/OpenRA.Game/FileFormats/TmpTSReader.cs +++ b/OpenRA.Game/FileFormats/TmpTSReader.cs @@ -51,8 +51,8 @@ namespace OpenRA.FileFormats public class TmpTSReader : ISpriteSource { - readonly List tiles = new List(); - public IEnumerable Frames { get { return tiles.Cast(); } } + readonly List tiles = new List(); + public IEnumerable Frames { get { return tiles; } } public bool CacheWhenLoadingTileset { get { return false; } } public TmpTSReader(Stream s) diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index 2418da2423..d5476302ef 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -26,6 +26,7 @@ namespace OpenRA.Graphics public interface ISpriteSource { + // TODO: Change this to IReadOnlyList so users don't need to call .ToArray() IEnumerable Frames { get; } bool CacheWhenLoadingTileset { get; } }