From 5745a984aaba249baa15a8fa7f257e7c6858fd0e Mon Sep 17 00:00:00 2001 From: Alekhya Date: Fri, 26 Jun 2020 10:20:35 -0700 Subject: [PATCH] Partial Fix for Memory issue - Limiting the number of ImageSources cached (#4433) * reducing storage of images * Added task.run * cleaned up code and added comments * Renamed variable * refactored code * Removed task.run because it was leading to race conditions in the concurrent dictionary and it was taking only upto 10 ms for reordering the dictionary * Added comments and fixed variable name --- .../Wox.Infrastructure/Image/ImageCache.cs | 29 +++++++++++++++++-- .../Wox.Infrastructure/Image/ImageLoader.cs | 6 +++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/modules/launcher/Wox.Infrastructure/Image/ImageCache.cs b/src/modules/launcher/Wox.Infrastructure/Image/ImageCache.cs index 85e477add9..835ccdcea1 100644 --- a/src/modules/launcher/Wox.Infrastructure/Image/ImageCache.cs +++ b/src/modules/launcher/Wox.Infrastructure/Image/ImageCache.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using System.Windows.Media; namespace Wox.Infrastructure.Image @@ -9,10 +10,10 @@ namespace Wox.Infrastructure.Image [Serializable] public class ImageCache { - private const int MaxCached = 5000; + private const int MaxCached = 50; public ConcurrentDictionary Usage = new ConcurrentDictionary(); private readonly ConcurrentDictionary _data = new ConcurrentDictionary(); - + private const int permissibleFactor = 2; public ImageSource this[string path] { @@ -22,7 +23,29 @@ namespace Wox.Infrastructure.Image var i = _data[path]; return i; } - set { _data[path] = value; } + set + { + _data[path] = value; + + // To prevent the dictionary from drastically increasing in size by caching images, the dictionary size is not allowed to grow more than the permissibleFactor * maxCached size + // This is done so that we don't constantly perform this resizing operation and also maintain the image cache size at the same time + if (_data.Count > permissibleFactor * MaxCached) + { + // This function resizes the Usage dictionary, taking the top 'maxCached' number of items and filtering the image icons that are not accessed frequently. + Cleanup(); + + // To delete the images from the data dictionary based on the resizing of the Usage Dictionary. + foreach (var key in _data.Keys) + { + int dictValue; + if (!Usage.TryGetValue(key, out dictValue)) + { + ImageSource imgSource; + _data.TryRemove(key, out imgSource); + } + } + } + } } public void Cleanup() diff --git a/src/modules/launcher/Wox.Infrastructure/Image/ImageLoader.cs b/src/modules/launcher/Wox.Infrastructure/Image/ImageLoader.cs index 6fa9a004a5..997cc14ca8 100644 --- a/src/modules/launcher/Wox.Infrastructure/Image/ImageLoader.cs +++ b/src/modules/launcher/Wox.Infrastructure/Image/ImageLoader.cs @@ -185,9 +185,13 @@ namespace Wox.Infrastructure.Image string hash = EnableImageHash ? _hashGenerator.GetHashFromImage(img) : null; if (hash != null) { + int ImageCacheValue; if (GuidToKey.TryGetValue(hash, out string key)) { // image already exists - img = ImageCache[key]; + if(ImageCache.Usage.TryGetValue(path, out ImageCacheValue)) + { + img = ImageCache[key]; + } } else { // new guid