Skip to content

Commit bf271b9

Browse files
committed
refactor Image Cache to single dictionary
1 parent d3d69be commit bf271b9

File tree

2 files changed

+37
-37
lines changed

2 files changed

+37
-37
lines changed

Flow.Launcher.Infrastructure/Image/ImageCache.cs

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,69 +11,73 @@ namespace Flow.Launcher.Infrastructure.Image
1111
public class ImageCache
1212
{
1313
private const int MaxCached = 50;
14-
public ConcurrentDictionary<string, int> Usage = new ConcurrentDictionary<string, int>();
15-
private readonly ConcurrentDictionary<string, ImageSource> _data = new ConcurrentDictionary<string, ImageSource>();
14+
public ConcurrentDictionary<string, (int usage, ImageSource imageSource)> Data { get; private set; } = new ConcurrentDictionary<string, (int, ImageSource)>();
1615
private const int permissibleFactor = 2;
1716

17+
public void Initialization(Dictionary<string, int> usage)
18+
{
19+
foreach (var key in usage.Keys)
20+
{
21+
Data[key] = (usage[key], null);
22+
}
23+
}
24+
1825
public ImageSource this[string path]
1926
{
2027
get
2128
{
22-
Usage.AddOrUpdate(path, 1, (k, v) => v + 1);
23-
var i = _data[path];
24-
return i;
29+
if (Data.TryGetValue(path, out var value))
30+
{
31+
value.usage++;
32+
return value.imageSource;
33+
}
34+
else return null;
2535
}
2636
set
2737
{
28-
_data[path] = value;
38+
Data.AddOrUpdate(path, (1, value), (k, v) =>
39+
{
40+
v.imageSource = value;
41+
v.usage++;
42+
return v;
43+
});
2944

3045
// 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
3146
// This is done so that we don't constantly perform this resizing operation and also maintain the image cache size at the same time
32-
if (_data.Count > permissibleFactor * MaxCached)
47+
if (Data.Count > permissibleFactor * MaxCached)
3348
{
34-
// This function resizes the Usage dictionary, taking the top 'maxCached' number of items and filtering the image icons that are not accessed frequently.
35-
Cleanup();
36-
3749
// To delete the images from the data dictionary based on the resizing of the Usage Dictionary.
38-
foreach (var key in _data.Keys)
50+
51+
52+
foreach (var key in Data.OrderBy(x => x.Value.usage).Take(Data.Count - MaxCached).Select(x => x.Key))
3953
{
40-
int dictValue;
41-
if (!Usage.TryGetValue(key, out dictValue) && !(key.Equals(Constant.ErrorIcon) || key.Equals(Constant.DefaultIcon)))
54+
if (!(key.Equals(Constant.ErrorIcon) || key.Equals(Constant.DefaultIcon)))
4255
{
43-
ImageSource imgSource;
44-
_data.TryRemove(key, out imgSource);
56+
Data.TryRemove(key, out _);
4557
}
4658
}
4759
}
4860
}
4961
}
5062

51-
public void Cleanup()
52-
{
53-
var images = Usage
54-
.OrderByDescending(o => o.Value)
55-
.Take(MaxCached)
56-
.ToDictionary(i => i.Key, i => i.Value);
57-
Usage = new ConcurrentDictionary<string, int>(images);
58-
}
5963

6064
public bool ContainsKey(string key)
6165
{
62-
var contains = _data.ContainsKey(key);
66+
var contains = Data.ContainsKey(key);
6367
return contains;
6468
}
6569

6670
public int CacheSize()
6771
{
68-
return _data.Count;
72+
return Data.Count;
6973
}
7074

7175
/// <summary>
7276
/// return the number of unique images in the cache (by reference not by checking images content)
7377
/// </summary>
7478
public int UniqueImagesInCache()
7579
{
76-
return _data.Values.Distinct().Count();
80+
return Data.Values.Select(x => x.imageSource).Distinct().Count();
7781
}
7882
}
7983

Flow.Launcher.Infrastructure/Image/ImageLoader.cs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static void Initialize()
3535
_storage = new BinaryStorage<Dictionary<string, int>>("Image");
3636
_hashGenerator = new ImageHashGenerator();
3737

38-
ImageCache.Usage = LoadStorageToConcurrentDictionary();
38+
var usage = LoadStorageToConcurrentDictionary();
3939

4040
foreach (var icon in new[] { Constant.DefaultIcon, Constant.MissingImgIcon })
4141
{
@@ -48,27 +48,26 @@ public static void Initialize()
4848
{
4949
Stopwatch.Normal("|ImageLoader.Initialize|Preload images cost", () =>
5050
{
51-
ImageCache.Usage.AsParallel().ForAll(x =>
51+
ImageCache.Data.AsParallel().ForAll(x =>
5252
{
5353
Load(x.Key);
5454
});
5555
});
56-
Log.Info($"|ImageLoader.Initialize|Number of preload images is <{ImageCache.Usage.Count}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}");
56+
Log.Info($"|ImageLoader.Initialize|Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}");
5757
});
5858
}
5959

6060
public static void Save()
6161
{
6262
lock (_storage)
6363
{
64-
ImageCache.Cleanup();
65-
_storage.Save(new Dictionary<string, int>(ImageCache.Usage));
64+
_storage.Save(ImageCache.Data.Select(x => (x.Key, x.Value.usage)).ToDictionary(x => x.Key, y => y.usage));
6665
}
6766
}
6867

6968
private static ConcurrentDictionary<string, int> LoadStorageToConcurrentDictionary()
7069
{
71-
lock(_storage)
70+
lock (_storage)
7271
{
7372
var loaded = _storage.TryLoad(new Dictionary<string, int>());
7473

@@ -222,13 +221,10 @@ public static ImageSource Load(string path, bool loadFullImage = false)
222221
string hash = EnableImageHash ? _hashGenerator.GetHashFromImage(img) : null;
223222
if (hash != null)
224223
{
225-
int ImageCacheValue;
224+
226225
if (GuidToKey.TryGetValue(hash, out string key))
227226
{ // image already exists
228-
if (ImageCache.Usage.TryGetValue(path, out ImageCacheValue))
229-
{
230-
img = ImageCache[key];
231-
}
227+
img = ImageCache[key] ?? img;
232228
}
233229
else
234230
{ // new guid

0 commit comments

Comments
 (0)