Skip to content

Commit 850efcf

Browse files
authored
Improve LRU performance
1. ``` class Pair``` replaced with ```struct Pair``` 2. `ValueRef` used instead of `Value` in the `LinkedListNode`. The performance gain is up to 5% (on small numbers no gain or a minor loss), memory gain is up to 23%.
1 parent 5628a75 commit 850efcf

File tree

1 file changed

+50
-48
lines changed
  • bench/algorithm/lru

1 file changed

+50
-48
lines changed

bench/algorithm/lru/2.cs

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -32,65 +32,67 @@ public static void Main(string[] args)
3232
}
3333
}
3434

35-
public class Pair<TK, TV>
35+
public struct Pair<TK, TV>
3636
{
37-
public TK Key;
37+
public TK Key;
3838

39-
public TV Value;
39+
public TV Value;
4040
}
4141

4242
public class LRU<TK, TV>
43+
where TK : notnull
44+
where TV : notnull
4345
{
44-
public int Size { get; private set; }
46+
public int Size { get; private set; }
4547

46-
private readonly Dictionary<TK, LinkedListNode<Pair<TK, TV>>> _key_lookup;
48+
private readonly Dictionary<TK, LinkedListNode<Pair<TK, TV>>> _key_lookup;
4749

48-
private readonly LinkedList<Pair<TK, TV>> _entries;
50+
private readonly LinkedList<Pair<TK, TV>> _entries;
4951

50-
public LRU(int size)
51-
{
52-
Size = size;
53-
_key_lookup = new Dictionary<TK, LinkedListNode<Pair<TK, TV>>>(size);
54-
_entries = new LinkedList<Pair<TK, TV>>();
55-
}
52+
public LRU(int size)
53+
{
54+
Size = size;
55+
_key_lookup = new Dictionary<TK, LinkedListNode<Pair<TK, TV>>>(size);
56+
_entries = new LinkedList<Pair<TK, TV>>();
57+
}
5658

57-
public bool TryGet(TK key, out TV value)
58-
{
59-
if (_key_lookup.TryGetValue(key, out var node))
60-
{
61-
value = node.Value.Value;
62-
_entries.Remove(node);
63-
_entries.AddLast(node);
64-
return true;
65-
}
66-
value = default;
67-
return false;
68-
}
59+
public bool TryGet(TK key, out TV value)
60+
{
61+
if (_key_lookup.TryGetValue(key, out var node))
62+
{
63+
value = node.ValueRef.Value;
64+
_entries.Remove(node);
65+
_entries.AddLast(node);
66+
return true;
67+
}
68+
value = default;
69+
return false;
70+
}
6971

70-
public void Put(TK key, TV value)
71-
{
72-
if (_key_lookup.TryGetValue(key, out var node))
73-
{
74-
node.Value.Value = value;
75-
_entries.Remove(node);
76-
_entries.AddLast(node);
77-
}
78-
else if (_entries.Count == Size)
79-
{
80-
var first = _entries.First;
81-
_key_lookup.Remove(first.Value.Key);
82-
_entries.RemoveFirst();
83-
first.Value.Key = key;
84-
first.Value.Value = value;
85-
_entries.AddLast(first);
86-
_key_lookup[key] = first;
87-
}
88-
else
89-
{
90-
_entries.AddLast(new Pair<TK, TV> { Key = key, Value = value });
91-
_key_lookup[key] = _entries.Last;
92-
}
93-
}
72+
public void Put(TK key, TV value)
73+
{
74+
if (_key_lookup.TryGetValue(key, out var node))
75+
{
76+
node.ValueRef.Value = value;
77+
_entries.Remove(node);
78+
_entries.AddLast(node);
79+
}
80+
else if (_entries.Count == Size)
81+
{
82+
var first = _entries.First;
83+
_key_lookup.Remove(first!.Value.Key);
84+
_entries.RemoveFirst();
85+
first.ValueRef.Key = key;
86+
first.ValueRef.Value = value;
87+
_entries.AddLast(first);
88+
_key_lookup[key] = first;
89+
}
90+
else
91+
{
92+
_entries.AddLast(new Pair<TK, TV> { Key = key, Value = value });
93+
_key_lookup[key] = _entries.Last;
94+
}
95+
}
9496
}
9597

9698
public class LCG

0 commit comments

Comments
 (0)