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
This commit is contained in:
Alekhya 2020-06-26 10:20:35 -07:00 committed by GitHub
parent d2f1f67a22
commit 5745a984aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 4 deletions

View File

@ -2,6 +2,7 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using System.Windows.Media; using System.Windows.Media;
namespace Wox.Infrastructure.Image namespace Wox.Infrastructure.Image
@ -9,10 +10,10 @@ namespace Wox.Infrastructure.Image
[Serializable] [Serializable]
public class ImageCache public class ImageCache
{ {
private const int MaxCached = 5000; private const int MaxCached = 50;
public ConcurrentDictionary<string, int> Usage = new ConcurrentDictionary<string, int>(); public ConcurrentDictionary<string, int> Usage = new ConcurrentDictionary<string, int>();
private readonly ConcurrentDictionary<string, ImageSource> _data = new ConcurrentDictionary<string, ImageSource>(); private readonly ConcurrentDictionary<string, ImageSource> _data = new ConcurrentDictionary<string, ImageSource>();
private const int permissibleFactor = 2;
public ImageSource this[string path] public ImageSource this[string path]
{ {
@ -22,7 +23,29 @@ namespace Wox.Infrastructure.Image
var i = _data[path]; var i = _data[path];
return i; 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() public void Cleanup()

View File

@ -185,9 +185,13 @@ namespace Wox.Infrastructure.Image
string hash = EnableImageHash ? _hashGenerator.GetHashFromImage(img) : null; string hash = EnableImageHash ? _hashGenerator.GetHashFromImage(img) : null;
if (hash != null) if (hash != null)
{ {
int ImageCacheValue;
if (GuidToKey.TryGetValue(hash, out string key)) if (GuidToKey.TryGetValue(hash, out string key))
{ // image already exists { // image already exists
img = ImageCache[key]; if(ImageCache.Usage.TryGetValue(path, out ImageCacheValue))
{
img = ImageCache[key];
}
} }
else else
{ // new guid { // new guid