From 7e8f4518764a86e7d3589ae75235b1d3d4462f8b Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 31 Jan 2021 15:37:00 -0500 Subject: add experimental 'aggressive memory optimization' flag (#757) --- .../ContentManagers/BaseContentManager.cs | 26 +++++++++++++++++----- .../ContentManagers/GameContentManager.cs | 5 +++-- .../Framework/ContentManagers/ModContentManager.cs | 5 +++-- 3 files changed, 26 insertions(+), 10 deletions(-) (limited to 'src/SMAPI/Framework/ContentManagers') diff --git a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs index 92264f8c..709c624e 100644 --- a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs @@ -11,6 +11,7 @@ using StardewModdingAPI.Framework.Content; using StardewModdingAPI.Framework.Exceptions; using StardewModdingAPI.Framework.Reflection; using StardewValley; +using xTile; namespace StardewModdingAPI.Framework.ContentManagers { @@ -29,6 +30,9 @@ namespace StardewModdingAPI.Framework.ContentManagers /// Encapsulates monitoring and logging. protected readonly IMonitor Monitor; + /// Whether to enable more aggressive memory optimizations. + protected readonly bool AggressiveMemoryOptimizations; + /// Whether the content coordinator has been disposed. private bool IsDisposed; @@ -75,7 +79,8 @@ namespace StardewModdingAPI.Framework.ContentManagers /// Simplifies access to private code. /// A callback to invoke when the content manager is being disposed. /// Whether this content manager handles managed asset keys (e.g. to load assets from a mod folder). - protected BaseContentManager(string name, IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, ContentCoordinator coordinator, IMonitor monitor, Reflector reflection, Action onDisposing, bool isNamespaced) + /// Whether to enable more aggressive memory optimizations. + protected BaseContentManager(string name, IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, ContentCoordinator coordinator, IMonitor monitor, Reflector reflection, Action onDisposing, bool isNamespaced, bool aggressiveMemoryOptimizations) : base(serviceProvider, rootDirectory, currentCulture) { // init @@ -85,6 +90,7 @@ namespace StardewModdingAPI.Framework.ContentManagers this.Monitor = monitor ?? throw new ArgumentNullException(nameof(monitor)); this.OnDisposing = onDisposing; this.IsNamespaced = isNamespaced; + this.AggressiveMemoryOptimizations = aggressiveMemoryOptimizations; // get asset data this.LanguageCodes = this.GetKeyLocales().ToDictionary(p => p.Value, p => p.Key, StringComparer.OrdinalIgnoreCase); @@ -198,14 +204,22 @@ namespace StardewModdingAPI.Framework.ContentManagers { this.ParseCacheKey(key, out string assetName, out _); - if (removeAssets.ContainsKey(assetName)) - return true; - if (predicate(assetName, asset.GetType())) + // check if asset should be removed + bool remove = removeAssets.ContainsKey(assetName); + if (!remove && predicate(assetName, asset.GetType())) { removeAssets[assetName] = asset; - return true; + remove = true; } - return false; + + // dispose if safe + if (remove && this.AggressiveMemoryOptimizations) + { + if (asset is Map map) + map.DisposeTileSheets(Game1.mapDisplayDevice); + } + + return remove; }, dispose); return removeAssets; diff --git a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs index 665c019b..f8ee575f 100644 --- a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs @@ -52,8 +52,9 @@ namespace StardewModdingAPI.Framework.ContentManagers /// Simplifies access to private code. /// A callback to invoke when the content manager is being disposed. /// A callback to invoke the first time *any* game content manager loads an asset. - public GameContentManager(string name, IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, ContentCoordinator coordinator, IMonitor monitor, Reflector reflection, Action onDisposing, Action onLoadingFirstAsset) - : base(name, serviceProvider, rootDirectory, currentCulture, coordinator, monitor, reflection, onDisposing, isNamespaced: false) + /// Whether to enable more aggressive memory optimizations. + public GameContentManager(string name, IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, ContentCoordinator coordinator, IMonitor monitor, Reflector reflection, Action onDisposing, Action onLoadingFirstAsset, bool aggressiveMemoryOptimizations) + : base(name, serviceProvider, rootDirectory, currentCulture, coordinator, monitor, reflection, onDisposing, isNamespaced: false, aggressiveMemoryOptimizations: aggressiveMemoryOptimizations) { this.OnLoadingFirstAsset = onLoadingFirstAsset; } diff --git a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs index 1456d3c1..284c1f37 100644 --- a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs @@ -50,8 +50,9 @@ namespace StardewModdingAPI.Framework.ContentManagers /// Simplifies access to private code. /// Encapsulates SMAPI's JSON file parsing. /// A callback to invoke when the content manager is being disposed. - public ModContentManager(string name, IContentManager gameContentManager, IServiceProvider serviceProvider, string modName, string rootDirectory, CultureInfo currentCulture, ContentCoordinator coordinator, IMonitor monitor, Reflector reflection, JsonHelper jsonHelper, Action onDisposing) - : base(name, serviceProvider, rootDirectory, currentCulture, coordinator, monitor, reflection, onDisposing, isNamespaced: true) + /// Whether to enable more aggressive memory optimizations. + public ModContentManager(string name, IContentManager gameContentManager, IServiceProvider serviceProvider, string modName, string rootDirectory, CultureInfo currentCulture, ContentCoordinator coordinator, IMonitor monitor, Reflector reflection, JsonHelper jsonHelper, Action onDisposing, bool aggressiveMemoryOptimizations) + : base(name, serviceProvider, rootDirectory, currentCulture, coordinator, monitor, reflection, onDisposing, isNamespaced: true, aggressiveMemoryOptimizations: aggressiveMemoryOptimizations) { this.GameContentManager = gameContentManager; this.JsonHelper = jsonHelper; -- cgit