Skip to content

Commit 7384cc1

Browse files
committed
enhance: only cache recently used 256 avatars
Signed-off-by: leo <longshuang@msn.cn>
1 parent 6fa5332 commit 7384cc1

1 file changed

Lines changed: 78 additions & 7 deletions

File tree

src/Models/AvatarManager.cs

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static AvatarManager Instance
3838
private readonly Lock _synclock = new();
3939
private string _storePath;
4040
private List<IAvatarHost> _avatars = new List<IAvatarHost>();
41-
private Dictionary<string, Bitmap> _resources = new Dictionary<string, Bitmap>();
41+
private Cache _cache = new Cache(256);
4242
private HashSet<string> _requesting = new HashSet<string>();
4343
private HashSet<string> _defaultAvatars = new HashSet<string>();
4444

@@ -120,7 +120,7 @@ public void Start()
120120

121121
Dispatcher.UIThread.Post(() =>
122122
{
123-
_resources[email] = img;
123+
_cache.AddOrUpdate(email, img);
124124
NotifyResourceChanged(email, img);
125125
});
126126
}
@@ -146,7 +146,7 @@ public Bitmap Request(string email, bool forceRefetch)
146146
if (_defaultAvatars.Contains(email))
147147
return null;
148148

149-
_resources.Remove(email);
149+
_cache.Remove(email);
150150

151151
var localFile = Path.Combine(_storePath, GetEmailHash(email));
152152
if (File.Exists(localFile))
@@ -156,7 +156,7 @@ public Bitmap Request(string email, bool forceRefetch)
156156
}
157157
else
158158
{
159-
if (_resources.TryGetValue(email, out var value))
159+
if (_cache.TryGet(email, out var value))
160160
return value;
161161

162162
var localFile = Path.Combine(_storePath, GetEmailHash(email));
@@ -167,7 +167,7 @@ public Bitmap Request(string email, bool forceRefetch)
167167
using (var stream = File.OpenRead(localFile))
168168
{
169169
var img = Bitmap.DecodeToWidth(stream, 128);
170-
_resources.Add(email, img);
170+
_cache.AddOrUpdate(email, img);
171171
return img;
172172
}
173173
}
@@ -197,7 +197,7 @@ public void SetFromLocal(string email, string file)
197197
image = Bitmap.DecodeToWidth(stream, 128);
198198
}
199199

200-
_resources[email] = image;
200+
_cache.AddOrUpdate(email, image);
201201

202202
lock (_synclock)
203203
{
@@ -217,7 +217,7 @@ public void SetFromLocal(string email, string file)
217217
private void LoadDefaultAvatar(string key, string img)
218218
{
219219
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/{img}", UriKind.RelativeOrAbsolute));
220-
_resources.Add(key, new Bitmap(icon));
220+
_cache.AddOrUpdate(key, new Bitmap(icon));
221221
_defaultAvatars.Add(key);
222222
}
223223

@@ -233,5 +233,76 @@ private void NotifyResourceChanged(string email, Bitmap image)
233233
foreach (var avatar in _avatars)
234234
avatar.OnAvatarResourceChanged(email, image);
235235
}
236+
237+
private class Cache
238+
{
239+
private readonly int _capacity;
240+
private readonly LinkedList<Item> _imgList;
241+
private readonly Dictionary<string, LinkedListNode<Item>> _key2img;
242+
243+
private class Item
244+
{
245+
public string Key { get; }
246+
public Bitmap Image { get; set; }
247+
248+
public Item(string key, Bitmap image)
249+
{
250+
Key = key;
251+
Image = image;
252+
}
253+
}
254+
255+
public Cache(int capacity)
256+
{
257+
_capacity = capacity;
258+
_key2img = new Dictionary<string, LinkedListNode<Item>>();
259+
_imgList = new LinkedList<Item>();
260+
}
261+
262+
public bool TryGet(string key, out Bitmap bitmap)
263+
{
264+
if (_key2img.TryGetValue(key, out var node))
265+
{
266+
_imgList.Remove(node);
267+
_imgList.AddFirst(node);
268+
bitmap = node.Value.Image;
269+
return true;
270+
}
271+
272+
bitmap = null;
273+
return false;
274+
}
275+
276+
public void AddOrUpdate(string key, Bitmap bitmap)
277+
{
278+
if (_key2img.TryGetValue(key, out var node))
279+
{
280+
_imgList.Remove(node);
281+
_imgList.AddFirst(node);
282+
node.Value.Image = bitmap;
283+
return;
284+
}
285+
286+
if (_key2img.Count >= _capacity)
287+
{
288+
var lastNode = _imgList.Last;
289+
_imgList.RemoveLast();
290+
_key2img.Remove(lastNode.Value.Key);
291+
}
292+
293+
var newNode = new LinkedListNode<Item>(new Item(key, bitmap));
294+
_imgList.AddFirst(newNode);
295+
_key2img[key] = newNode;
296+
}
297+
298+
public void Remove(string key)
299+
{
300+
if (_key2img.TryGetValue(key, out var node))
301+
{
302+
_imgList.Remove(node);
303+
_key2img.Remove(key);
304+
}
305+
}
306+
}
236307
}
237308
}

0 commit comments

Comments
 (0)