diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs index 5d7224c5b..67f008972 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageCache.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageCache.cs @@ -2,17 +2,18 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using System.Windows.Media; -namespace Flow.Launcher.Infrastructure.Image +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,14 +23,39 @@ namespace Flow.Launcher.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 Dictionary CleanupAndToDictionary() - => Usage + public void Cleanup() + { + var images = Usage .OrderByDescending(o => o.Value) .Take(MaxCached) .ToDictionary(i => i.Key, i => i.Value); + Usage = new ConcurrentDictionary(images); + } public bool ContainsKey(string key) { @@ -51,4 +77,4 @@ namespace Flow.Launcher.Infrastructure.Image } } -} +} \ No newline at end of file diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 0bf575337..e03ee709a 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -9,7 +9,7 @@ using System.Windows.Media.Imaging; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; -namespace Flow.Launcher.Infrastructure.Image +namespace Wox.Infrastructure.Image { public static class ImageLoader { @@ -218,27 +218,29 @@ namespace Flow.Launcher.Infrastructure.Image var img = imageResult.ImageSource; if (imageResult.ImageType != ImageType.Error && imageResult.ImageType != ImageType.Cache) - { - // we need to get image hash - string hash = _enableHashImage ? _hashGenerator.GetHashFromImage(img) : null; + { // we need to get image hash + string hash = EnableImageHash ? _hashGenerator.GetHashFromImage(img) : null; if (hash != null) { - if (_guidToKey.TryGetValue(hash, out string key)) - { - // image already exists - img = _imageCache[key]; + int ImageCacheValue; + if (GuidToKey.TryGetValue(hash, out string key)) + { // image already exists + if (ImageCache.Usage.TryGetValue(path, out ImageCacheValue)) + { + img = ImageCache[key]; + } } else - { - // new guid - _guidToKey[hash] = path; + { // new guid + GuidToKey[hash] = path; } } // update cache - _imageCache[path] = img; + ImageCache[path] = img; } + return img; }