From 18a4da6bc04bb1d4e66abf8eda30ef0d66305bc8 Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 22 Jan 2010 16:26:56 +1300 Subject: [PATCH] perf fix wrt calling OpenRead way too often. --- OpenRa.FileFormats/FileSystem.cs | 46 +++++++++++++++++++++++++++++++- OpenRa.FileFormats/Folder.cs | 10 ++++++- OpenRa.FileFormats/Package.cs | 6 +++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/OpenRa.FileFormats/FileSystem.cs b/OpenRa.FileFormats/FileSystem.cs index 673c3326fe..a4112d3979 100644 --- a/OpenRa.FileFormats/FileSystem.cs +++ b/OpenRa.FileFormats/FileSystem.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using IjwFramework.Collections; namespace OpenRa.FileFormats { @@ -9,10 +10,13 @@ namespace OpenRa.FileFormats static List mountedFolders = new List(); static List temporaryMounts = new List(); + static Cache> allFiles = new Cache>( _ => new List() ); + static Cache> allTemporaryFiles = new Cache>( _ => new List() ); + public static void MountDefaultPackages() { FileSystem.Mount(new Folder("./")); - if( File.Exists( "main.mix" ) ) + if( FileSystem.Exists( "main.mix" ) ) FileSystem.Mount( new Package( "main.mix" ) ); FileSystem.Mount( new Package( "redalert.mix" ) ); FileSystem.Mount( new Package( "conquer.mix" ) ); @@ -34,22 +38,54 @@ namespace OpenRa.FileFormats public static void Mount(IFolder folder) { mountedFolders.Add(folder); + + foreach( var hash in folder.AllFileHashes() ) + { + var l = allFiles[hash]; + if( !l.Contains( folder ) ) + l.Add( folder ); + } } public static void MountTemporary(IFolder folder) { mountedFolders.Add(folder); temporaryMounts.Add(folder); + + foreach( var hash in folder.AllFileHashes() ) + { + var l = allFiles[hash]; + if( !l.Contains( folder ) ) + l.Add( folder ); + } } public static void UnmountTemporaryPackages() { mountedFolders.RemoveAll(f => temporaryMounts.Contains(f)); temporaryMounts.Clear(); + + allTemporaryFiles = new Cache>( _ => new List() ); + } + + static Stream GetFromCache( Cache> index, string filename ) + { + foreach( var folder in index[ PackageEntry.HashFilename( filename ) ] ) + { + Stream s = folder.GetContent(filename); + if( s != null ) + return s; + } + return null; } public static Stream Open(string filename) { + var ret = GetFromCache( allFiles, filename ) + ?? GetFromCache( allTemporaryFiles, filename ); + if( ret != null ) + return ret; + foreach( IFolder folder in mountedFolders ) { Stream s = folder.GetContent(filename); @@ -62,6 +98,14 @@ namespace OpenRa.FileFormats public static Stream OpenWithExts( string filename, params string[] exts ) { + foreach( var ext in exts ) + { + var s = GetFromCache( allFiles, filename + ext ) + ?? GetFromCache( allTemporaryFiles, filename + ext ); + if( s != null ) + return s; + } + foreach( var ext in exts ) { foreach( IFolder folder in mountedFolders ) diff --git a/OpenRa.FileFormats/Folder.cs b/OpenRa.FileFormats/Folder.cs index 04cb36fd3d..dda5719305 100644 --- a/OpenRa.FileFormats/Folder.cs +++ b/OpenRa.FileFormats/Folder.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Collections.Generic; namespace OpenRa.FileFormats { @@ -10,8 +11,15 @@ namespace OpenRa.FileFormats public Stream GetContent(string filename) { - try { return File.OpenRead(path + filename); } + Log.Write( "GetContent from folder: {0}", filename ); + try { return File.OpenRead( Path.Combine( path, filename ) ); } catch { return null; } } + + public IEnumerable AllFileHashes() + { + foreach( var filename in Directory.GetFiles( path, "*", SearchOption.TopDirectoryOnly ) ) + yield return PackageEntry.HashFilename( filename ); + } } } diff --git a/OpenRa.FileFormats/Package.cs b/OpenRa.FileFormats/Package.cs index 8bb504d5fc..92b916e16e 100644 --- a/OpenRa.FileFormats/Package.cs +++ b/OpenRa.FileFormats/Package.cs @@ -8,6 +8,7 @@ namespace OpenRa.FileFormats public interface IFolder { Stream GetContent(string filename); + IEnumerable AllFileHashes(); } public class Package : IFolder @@ -131,6 +132,11 @@ namespace OpenRa.FileFormats { return GetContent(PackageEntry.HashFilename(filename)); } + + public IEnumerable AllFileHashes() + { + return index.Keys; + } } [Flags]