From c1342bd4cd6b75b24d11275bdd73ebf893f916ea Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 4 May 2022 20:35:08 -0400 Subject: disable case-insensitive paths by default pending performance rework --- src/SMAPI/Framework/ContentCoordinator.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/SMAPI/Framework/ContentCoordinator.cs') diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs index 84fff250..1a82d194 100644 --- a/src/SMAPI/Framework/ContentCoordinator.cs +++ b/src/SMAPI/Framework/ContentCoordinator.cs @@ -16,6 +16,7 @@ using StardewModdingAPI.Internal; using StardewModdingAPI.Metadata; using StardewModdingAPI.Toolkit.Serialization; using StardewModdingAPI.Toolkit.Utilities; +using StardewModdingAPI.Toolkit.Utilities.PathLookups; using StardewValley; using StardewValley.GameData; using xTile; @@ -34,6 +35,9 @@ namespace StardewModdingAPI.Framework /// Whether to enable more aggressive memory optimizations. private readonly bool AggressiveMemoryOptimizations; + /// Get a file path lookup for the given directory. + private readonly Func GetFilePathLookup; + /// Encapsulates monitoring and logging. private readonly IMonitor Monitor; @@ -115,11 +119,13 @@ namespace StardewModdingAPI.Framework /// A callback to invoke the first time *any* game content manager loads an asset. /// A callback to invoke when an asset is fully loaded. /// Whether to enable more aggressive memory optimizations. + /// Get a file path lookup for the given directory. /// A callback to invoke when any asset names have been invalidated from the cache. /// Get the load/edit operations to apply to an asset by querying registered event handlers. - public ContentCoordinator(IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, IMonitor monitor, Reflector reflection, JsonHelper jsonHelper, Action onLoadingFirstAsset, Action onAssetLoaded, bool aggressiveMemoryOptimizations, Action> onAssetsInvalidated, Func> requestAssetOperations) + public ContentCoordinator(IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, IMonitor monitor, Reflector reflection, JsonHelper jsonHelper, Action onLoadingFirstAsset, Action onAssetLoaded, bool aggressiveMemoryOptimizations, Func getFilePathLookup, Action> onAssetsInvalidated, Func> requestAssetOperations) { this.AggressiveMemoryOptimizations = aggressiveMemoryOptimizations; + this.GetFilePathLookup = getFilePathLookup; this.Monitor = monitor ?? throw new ArgumentNullException(nameof(monitor)); this.Reflection = reflection; this.JsonHelper = jsonHelper; @@ -208,7 +214,7 @@ namespace StardewModdingAPI.Framework jsonHelper: this.JsonHelper, onDisposing: this.OnDisposing, aggressiveMemoryOptimizations: this.AggressiveMemoryOptimizations, - relativePathCache: CaseInsensitivePathLookup.GetCachedFor(rootDirectory) + relativePathLookup: this.GetFilePathLookup(rootDirectory) ); this.ContentManagers.Add(manager); return manager; -- cgit From 295ad29b8d60fdbae0c0030e8d887a2adab779a3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 4 May 2022 21:02:41 -0400 Subject: remove aggressive memory optimizations option --- src/SMAPI/Framework/ContentCoordinator.cs | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) (limited to 'src/SMAPI/Framework/ContentCoordinator.cs') diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs index 1a82d194..ef442fbe 100644 --- a/src/SMAPI/Framework/ContentCoordinator.cs +++ b/src/SMAPI/Framework/ContentCoordinator.cs @@ -32,9 +32,6 @@ namespace StardewModdingAPI.Framework /// An asset key prefix for assets from SMAPI mod folders. private readonly string ManagedPrefix = "SMAPI"; - /// Whether to enable more aggressive memory optimizations. - private readonly bool AggressiveMemoryOptimizations; - /// Get a file path lookup for the given directory. private readonly Func GetFilePathLookup; @@ -118,13 +115,11 @@ namespace StardewModdingAPI.Framework /// Encapsulates SMAPI's JSON file parsing. /// A callback to invoke the first time *any* game content manager loads an asset. /// A callback to invoke when an asset is fully loaded. - /// Whether to enable more aggressive memory optimizations. /// Get a file path lookup for the given directory. /// A callback to invoke when any asset names have been invalidated from the cache. /// Get the load/edit operations to apply to an asset by querying registered event handlers. - public ContentCoordinator(IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, IMonitor monitor, Reflector reflection, JsonHelper jsonHelper, Action onLoadingFirstAsset, Action onAssetLoaded, bool aggressiveMemoryOptimizations, Func getFilePathLookup, Action> onAssetsInvalidated, Func> requestAssetOperations) + public ContentCoordinator(IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, IMonitor monitor, Reflector reflection, JsonHelper jsonHelper, Action onLoadingFirstAsset, Action onAssetLoaded, Func getFilePathLookup, Action> onAssetsInvalidated, Func> requestAssetOperations) { - this.AggressiveMemoryOptimizations = aggressiveMemoryOptimizations; this.GetFilePathLookup = getFilePathLookup; this.Monitor = monitor ?? throw new ArgumentNullException(nameof(monitor)); this.Reflection = reflection; @@ -145,26 +140,11 @@ namespace StardewModdingAPI.Framework reflection: reflection, onDisposing: this.OnDisposing, onLoadingFirstAsset: onLoadingFirstAsset, - onAssetLoaded: onAssetLoaded, - aggressiveMemoryOptimizations: aggressiveMemoryOptimizations + onAssetLoaded: onAssetLoaded ) ); - var contentManagerForAssetPropagation = new GameContentManagerForAssetPropagation( - name: nameof(GameContentManagerForAssetPropagation), - serviceProvider: serviceProvider, - rootDirectory: rootDirectory, - currentCulture: currentCulture, - coordinator: this, - monitor: monitor, - reflection: reflection, - onDisposing: this.OnDisposing, - onLoadingFirstAsset: onLoadingFirstAsset, - onAssetLoaded: onAssetLoaded, - aggressiveMemoryOptimizations: aggressiveMemoryOptimizations - ); - this.ContentManagers.Add(contentManagerForAssetPropagation); this.VanillaContentManager = new LocalizedContentManager(serviceProvider, rootDirectory); - this.CoreAssets = new CoreAssetPropagator(this.MainContentManager, contentManagerForAssetPropagation, this.Monitor, reflection, aggressiveMemoryOptimizations, name => this.ParseAssetName(name, allowLocales: true)); + this.CoreAssets = new CoreAssetPropagator(this.MainContentManager, this.Monitor, reflection, name => this.ParseAssetName(name, allowLocales: true)); this.LocaleCodes = new Lazy>(() => this.GetLocaleCodes(customLanguages: Enumerable.Empty())); } @@ -184,8 +164,7 @@ namespace StardewModdingAPI.Framework reflection: this.Reflection, onDisposing: this.OnDisposing, onLoadingFirstAsset: this.OnLoadingFirstAsset, - onAssetLoaded: this.OnAssetLoaded, - aggressiveMemoryOptimizations: this.AggressiveMemoryOptimizations + onAssetLoaded: this.OnAssetLoaded ); this.ContentManagers.Add(manager); return manager; @@ -213,7 +192,6 @@ namespace StardewModdingAPI.Framework reflection: this.Reflection, jsonHelper: this.JsonHelper, onDisposing: this.OnDisposing, - aggressiveMemoryOptimizations: this.AggressiveMemoryOptimizations, relativePathLookup: this.GetFilePathLookup(rootDirectory) ); this.ContentManagers.Add(manager); -- cgit From a969828e9357306aaac5163c430e108ab57f578b Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 6 May 2022 18:26:35 -0400 Subject: cache asset operation instances created legacy interceptors --- src/SMAPI/Framework/ContentCoordinator.cs | 74 +++++++++++++++++++------------ 1 file changed, 46 insertions(+), 28 deletions(-) (limited to 'src/SMAPI/Framework/ContentCoordinator.cs') diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs index ef442fbe..8ce0dba1 100644 --- a/src/SMAPI/Framework/ContentCoordinator.cs +++ b/src/SMAPI/Framework/ContentCoordinator.cs @@ -81,6 +81,14 @@ namespace StardewModdingAPI.Framework /// The cached asset load/edit operations to apply, indexed by asset name. private readonly TickCacheDictionary AssetOperationsByKey = new(); + /// A cache of asset operation groups created for legacy implementations. + [Obsolete] + private readonly Dictionary LegacyLoaderCache = new(ReferenceEqualityComparer.Instance); + + /// A cache of asset operation groups created for legacy implementations. + [Obsolete] + private readonly Dictionary LegacyEditorCache = new(ReferenceEqualityComparer.Instance); + /********* ** Accessors @@ -598,21 +606,26 @@ namespace StardewModdingAPI.Framework } // add operation - yield return new AssetOperationGroup( - mod: loader.Mod, - loadOperations: new[] - { - new AssetLoadOperation( - mod: loader.Mod, - priority: AssetLoadPriority.Exclusive, - onBehalfOf: null, - getData: assetInfo => loader.Data.Load( - this.GetLegacyAssetInfo(assetInfo) + if (!this.LegacyLoaderCache.TryGetValue(loader.Data, out AssetOperationGroup? group)) + { + this.LegacyLoaderCache[loader.Data] = group = new AssetOperationGroup( + mod: loader.Mod, + loadOperations: new[] + { + new AssetLoadOperation( + mod: loader.Mod, + priority: AssetLoadPriority.Exclusive, + onBehalfOf: null, + getData: assetInfo => loader.Data.Load( + this.GetLegacyAssetInfo(assetInfo) + ) ) - ) - }, - editOperations: Array.Empty() - ); + }, + editOperations: Array.Empty() + ); + } + + yield return group; } // legacy edit operations @@ -652,21 +665,26 @@ namespace StardewModdingAPI.Framework }; // add operation - yield return new AssetOperationGroup( - mod: editor.Mod, - loadOperations: Array.Empty(), - editOperations: new[] - { - new AssetEditOperation( - mod: editor.Mod, - priority: priority, - onBehalfOf: null, - applyEdit: assetData => editor.Data.Edit( - this.GetLegacyAssetData(assetData) + if (!this.LegacyEditorCache.TryGetValue(editor.Data, out AssetOperationGroup? group)) + { + this.LegacyEditorCache[editor.Data] = group = new AssetOperationGroup( + mod: editor.Mod, + loadOperations: Array.Empty(), + editOperations: new[] + { + new AssetEditOperation( + mod: editor.Mod, + priority: priority, + onBehalfOf: null, + applyEdit: assetData => editor.Data.Edit( + this.GetLegacyAssetData(assetData) + ) ) - ) - } - ); + } + ); + } + + yield return group; } #pragma warning restore CS0612, CS0618 } -- cgit From 09c52fb3f530bb450de5a7b4ba2ca09c1035b3cd Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 6 May 2022 19:39:51 -0400 Subject: cache legacy asset operations by target type --- src/SMAPI/Framework/ContentCoordinator.cs | 50 +++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 16 deletions(-) (limited to 'src/SMAPI/Framework/ContentCoordinator.cs') diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs index 8ce0dba1..4f52d57e 100644 --- a/src/SMAPI/Framework/ContentCoordinator.cs +++ b/src/SMAPI/Framework/ContentCoordinator.cs @@ -83,11 +83,11 @@ namespace StardewModdingAPI.Framework /// A cache of asset operation groups created for legacy implementations. [Obsolete] - private readonly Dictionary LegacyLoaderCache = new(ReferenceEqualityComparer.Instance); + private readonly Dictionary> LegacyLoaderCache = new(ReferenceEqualityComparer.Instance); /// A cache of asset operation groups created for legacy implementations. [Obsolete] - private readonly Dictionary LegacyEditorCache = new(ReferenceEqualityComparer.Instance); + private readonly Dictionary> LegacyEditorCache = new(ReferenceEqualityComparer.Instance); /********* @@ -606,9 +606,11 @@ namespace StardewModdingAPI.Framework } // add operation - if (!this.LegacyLoaderCache.TryGetValue(loader.Data, out AssetOperationGroup? group)) - { - this.LegacyLoaderCache[loader.Data] = group = new AssetOperationGroup( + yield return this.GetOrCreateLegacyOperationGroup( + cache: this.LegacyLoaderCache, + editor: loader.Data, + dataType: info.DataType, + createGroup: () => new AssetOperationGroup( mod: loader.Mod, loadOperations: new[] { @@ -622,10 +624,8 @@ namespace StardewModdingAPI.Framework ) }, editOperations: Array.Empty() - ); - } - - yield return group; + ) + ); } // legacy edit operations @@ -665,9 +665,11 @@ namespace StardewModdingAPI.Framework }; // add operation - if (!this.LegacyEditorCache.TryGetValue(editor.Data, out AssetOperationGroup? group)) - { - this.LegacyEditorCache[editor.Data] = group = new AssetOperationGroup( + yield return this.GetOrCreateLegacyOperationGroup( + cache: this.LegacyEditorCache, + editor: editor.Data, + dataType: info.DataType, + createGroup: () => new AssetOperationGroup( mod: editor.Mod, loadOperations: Array.Empty(), editOperations: new[] @@ -681,14 +683,30 @@ namespace StardewModdingAPI.Framework ) ) } - ); - } - - yield return group; + ) + ); } #pragma warning restore CS0612, CS0618 } + /// Get a cached asset operation group for a legacy or instance, creating it if needed. + /// The editor type (one of or ). + /// The cached operation groups for the interceptor type. + /// The legacy asset interceptor. + /// The asset data type. + /// Create the asset operation group if it's not cached yet. + private AssetOperationGroup GetOrCreateLegacyOperationGroup(Dictionary> cache, TInterceptor editor, Type dataType, Func createGroup) + where TInterceptor : class + { + if (!cache.TryGetValue(editor, out Dictionary? cacheByType)) + cache[editor] = cacheByType = new Dictionary(); + + if (!cacheByType.TryGetValue(dataType, out AssetOperationGroup? group)) + cacheByType[dataType] = group = createGroup(); + + return group; + } + /// Get an asset info compatible with legacy and instances, which always expect the base name. /// The asset info. private IAssetInfo GetLegacyAssetInfo(IAssetInfo asset) -- cgit