From c547f3f26d1127893b067a3b901944795cac083a Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Mon, 1 Apr 2024 14:37:43 +0100 Subject: [PATCH] Trim memory usage of SpriteCache. As the SpriteCache is used as a one-shot operation in practise, holding on to the capacity of backing collections is not required. Memory usage can be reduced by allowing the capacity to be reset after the SpriteCache has resolved items. - Once LoadReservations is called, reset the reservation dictionaries so their backing collections can be reclaimed. - When ResolveSprites is called, shrink the resolved dictionary as resolutions take place. --- OpenRA.Game/Graphics/SpriteCache.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/OpenRA.Game/Graphics/SpriteCache.cs b/OpenRA.Game/Graphics/SpriteCache.cs index 97ed93b66f..24e5f8cf77 100644 --- a/OpenRA.Game/Graphics/SpriteCache.cs +++ b/OpenRA.Game/Graphics/SpriteCache.cs @@ -112,6 +112,11 @@ namespace OpenRA.Graphics } } + spriteReservations.Clear(); + spriteReservations.TrimExcess(); + reservationsByFilename.Clear(); + reservationsByFilename.TrimExcess(); + // When the sheet builder is adding sprites, it reserves height for the tallest sprite seen along the row. // We can achieve better sheet packing by keeping sprites with similar heights together. var orderedPendingResolve = pendingResolve.OrderBy(x => x.Frame.Size.Height); @@ -137,17 +142,17 @@ namespace OpenRA.Graphics modData.LoadScreen?.Display(); } - spriteReservations.Clear(); - reservationsByFilename.Clear(); - foreach (var sb in SheetBuilders.Values) sb.Current.ReleaseBuffer(); } public Sprite[] ResolveSprites(int token) { - var resolved = resolvedSprites[token]; - resolvedSprites.Remove(token); + if (!resolvedSprites.Remove(token, out var resolved)) + throw new InvalidOperationException($"{nameof(token)} {token} has either already been resolved, or was never reserved via {nameof(ReserveSprites)}"); + + resolvedSprites.TrimExcess(); + if (missingFiles.TryGetValue(token, out var r)) throw new FileNotFoundException($"{r.Location}: {r.Filename} not found", r.Filename);