Skip to content

Commit 1fba38e

Browse files
authored
Merge pull request #3962 from riemannulus/imp/use-bitfaster-caching
🔴 refactor: use `Bitfaster.Caching` instead of `Libplanet.LruCahceNet`
2 parents bfd304b + 90c524a commit 1fba38e

File tree

4 files changed

+24
-64
lines changed

4 files changed

+24
-64
lines changed

CHANGES.md

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ To be released.
5151
- (Libplanet.Net) Changed to no longer report `BlockHashDownloadState`
5252
and `BlockDownloadState` during preloading. It is strongly advised
5353
not to rely on these to track the progress of preloading. [[#3943]]
54+
- (Libplanet.Store) Optimized LRU Cache for `HashNode` and `BlockSet`.
55+
[[#3962]]
5456

5557
### Bug fixes
5658

@@ -69,6 +71,7 @@ To be released.
6971
[#3949]: https://github.com/planetarium/libplanet/pull/3949
7072
[#3950]: https://github.com/planetarium/libplanet/pull/3950
7173
[#3960]: https://github.com/planetarium/libplanet/pull/3960
74+
[#3962]: https://github.com/planetarium/libplanet/pull/3962
7275

7376

7477
Version 5.2.2

src/Libplanet.Store/BlockSet.cs

+10-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Linq;
5+
using BitFaster.Caching;
6+
using BitFaster.Caching.Lru;
57
using Caching;
68
using Libplanet.Types.Blocks;
79

@@ -10,12 +12,14 @@ namespace Libplanet.Store
1012
public class BlockSet : IReadOnlyDictionary<BlockHash, Block>
1113
{
1214
private readonly IStore _store;
13-
private readonly LRUCache<BlockHash, Block> _cache;
15+
private readonly ICache<BlockHash, Block> _cache;
1416

1517
public BlockSet(IStore store, int cacheSize = 4096)
1618
{
1719
_store = store;
18-
_cache = new LRUCache<BlockHash, Block>(cacheSize, Math.Max(cacheSize / 64, 8));
20+
_cache = new ConcurrentLruBuilder<BlockHash, Block>()
21+
.WithCapacity(cacheSize)
22+
.Build();
1923
}
2024

2125
public IEnumerable<BlockHash> Keys =>
@@ -68,7 +72,7 @@ public Block this[BlockHash key]
6872

6973
value.ValidateTimestamp();
7074
_store.PutBlock(value);
71-
_cache.AddReplace(value.Hash, value);
75+
_cache.AddOrUpdate(value.Hash, value);
7276
}
7377
}
7478

@@ -82,7 +86,7 @@ public bool Remove(BlockHash key)
8286
{
8387
bool deleted = _store.DeleteBlock(key);
8488

85-
_cache.Remove(key);
89+
_cache.TryRemove(key);
8690

8791
return deleted;
8892
}
@@ -162,14 +166,14 @@ public IEnumerator<KeyValuePair<BlockHash, Block>> GetEnumerator()
162166
else
163167
{
164168
// The cached block had been deleted on _store...
165-
_cache.Remove(key);
169+
_cache.TryRemove(key);
166170
}
167171
}
168172

169173
Block? fetched = _store.GetBlock(key);
170174
if (fetched is { })
171175
{
172-
_cache.AddReplace(key, fetched);
176+
_cache.AddOrUpdate(key, fetched);
173177
}
174178

175179
return fetched;

src/Libplanet.Store/HashNodeCache.cs

+10-58
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
using System.Diagnostics;
1+
using System;
22
using System.Security.Cryptography;
3-
using System.Threading;
43
using Bencodex.Types;
4+
using BitFaster.Caching;
5+
using BitFaster.Caching.Lru;
56
using Libplanet.Common;
67
using Libplanet.Store.Trie;
7-
using LruCacheNet;
8-
using Serilog;
98

109
namespace Libplanet.Store
1110
{
@@ -16,73 +15,26 @@ public class HashNodeCache
1615
{
1716
// FIXME: Tuned to 9c mainnet. Should be refactored to accept cache size as an argument.
1817
private const int _cacheSize = 524_288;
19-
private const int _reportPeriod = 60_000;
2018

21-
private LruCache<HashDigest<SHA256>, IValue> _cache;
22-
private Stopwatch _stopwatch;
23-
private int _attempts;
24-
private int _hits;
25-
private object _reportLock;
19+
private ICache<HashDigest<SHA256>, IValue> _cache;
2620

2721
internal HashNodeCache()
2822
{
29-
_cache = new LruCache<HashDigest<SHA256>, IValue>(_cacheSize);
30-
_stopwatch = new Stopwatch();
31-
_attempts = 0;
32-
_hits = 0;
33-
_reportLock = new object();
34-
_stopwatch.Start();
23+
_cache = new ConcurrentLruBuilder<HashDigest<SHA256>, IValue>()
24+
.WithMetrics()
25+
.WithExpireAfterAccess(TimeSpan.FromMinutes(10))
26+
.WithCapacity(_cacheSize)
27+
.Build();
3528
}
3629

3730
public bool TryGetValue(HashDigest<SHA256> hash, out IValue? value)
3831
{
39-
lock (_reportLock)
40-
{
41-
Report();
42-
}
43-
44-
Interlocked.Increment(ref _attempts);
45-
if (_cache.TryGetValue(hash, out value))
46-
{
47-
Interlocked.Increment(ref _hits);
48-
return true;
49-
}
50-
else
51-
{
52-
value = null;
53-
return false;
54-
}
32+
return _cache.TryGet(hash, out value);
5533
}
5634

5735
public void AddOrUpdate(HashDigest<SHA256> hash, IValue value)
5836
{
5937
_cache.AddOrUpdate(hash, value);
6038
}
61-
62-
private void Report()
63-
{
64-
long period = _stopwatch.ElapsedMilliseconds;
65-
if (period > _reportPeriod)
66-
{
67-
Log
68-
.ForContext("Source", nameof(HashNodeCache))
69-
.ForContext("Tag", "Metric")
70-
.ForContext("Subtag", "HashNodeCacheReport")
71-
.Debug(
72-
"Successfully fetched {HitCount} cached values out of last " +
73-
"{AttemptCount} attempts with hitrate of {HitRate} and " +
74-
"{CacheUsed}/{CacheSize} cache in use during last {PeriodMs} ms",
75-
_hits,
76-
_attempts,
77-
(double)_hits / _attempts,
78-
_cache.Count,
79-
_cache.Capacity,
80-
period);
81-
82-
_stopwatch.Restart();
83-
Interlocked.Exchange(ref _attempts, 0);
84-
Interlocked.Exchange(ref _hits, 0);
85-
}
86-
}
8739
}
8840
}

src/Libplanet.Store/Libplanet.Store.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8+
<PackageReference Include="BitFaster.Caching" Version="2.5.2" />
89
<PackageReference Include="System.Collections.Immutable" Version="1.*" />
910
<PackageReference Include="Bencodex" Version="0.16.0" />
1011
<PackageReference Include="Caching.dll" Version="1.4.0.1" />

0 commit comments

Comments
 (0)