Skip to content

Commit

Permalink
Merge pull request #1013 from longfin/feature/cache-blockset
Browse files Browse the repository at this point in the history
Improve performance of `BlockSet<T>`
  • Loading branch information
longfin authored Sep 23, 2020
2 parents 072f481 + 7286351 commit 63048cc
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ To be released.
- `doesTransactionFollowPolicy` parameter became
`Func<Transaction<T>, BlockChain<T>, bool>` on `BlockPolicy<T>()`
constructor. [[#1012]]
- Added `cacheSize` optional parameter to `BlockSet<T>()` constructor.
[[#1013]]

### Backward-incompatible network protocol changes

Expand Down Expand Up @@ -257,6 +259,8 @@ To be released.
- `BlockChain<T>` instead of `BlockPolicy<T>` became to validate `Block<T>`s to append
so that even if an empty implementation of `IBlockPolicy<T>` is used `Block<T>`s are
unable to be appended to `BlockChain<T>`. [[#1010]]
- `BlockSet<T>[HashDigest<SHA256>]` and `BlockChain<T>.Genesis` became cached
so that they become faster to get. [[#1013]]

### Bug fixes

Expand Down Expand Up @@ -359,6 +363,7 @@ To be released.
[#1004]: https://github.com/planetarium/libplanet/pull/1004
[#1010]: https://github.com/planetarium/libplanet/pull/1010
[#1012]: https://github.com/planetarium/libplanet/pull/1012
[#1013]: https://github.com/planetarium/libplanet/pull/1013
[sleep mode]: https://en.wikipedia.org/wiki/Sleep_mode


Expand Down
7 changes: 6 additions & 1 deletion Libplanet/Blockchain/BlockChain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public class BlockChain<T>
/// </summary>
private IDictionary<TxId, Transaction<T>> _transactions;

/// <summary>
/// Cached genesis block.
/// </summary>
private Block<T> _genesis;

/// <summary>
/// Initializes a new instance of the <see cref="BlockChain{T}"/> class.
/// </summary>
Expand Down Expand Up @@ -235,7 +240,7 @@ public Block<T> Tip
/// <summary>
/// The first <see cref="Block{T}"/> in the <see cref="BlockChain{T}"/>.
/// </summary>
public Block<T> Genesis => this[0];
public Block<T> Genesis => _genesis ??= this[0];

public Guid Id { get; private set; }

Expand Down
41 changes: 37 additions & 4 deletions Libplanet/Store/BlockSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,27 @@
using System.Security.Cryptography;
using Libplanet.Action;
using Libplanet.Blocks;
using LruCacheNet;

namespace Libplanet.Store
{
public class BlockSet<T> : BaseIndex<HashDigest<SHA256>, Block<T>>
where T : IAction, new()
{
public BlockSet(IStore store)
private readonly LruCache<HashDigest<SHA256>, Block<T>> _cache;

public BlockSet(IStore store, int cacheSize = 4096)
: base(store)
{
_cache = new LruCache<HashDigest<SHA256>, Block<T>>(cacheSize);
}

public override ICollection<HashDigest<SHA256>> Keys =>
Store.IterateBlockHashes().ToList();

public override ICollection<Block<T>> Values =>
Store.IterateBlockHashes()
.Select(Store.GetBlock<T>)
.Select(GetBlock)
.ToList();

public override int Count => (int)Store.CountBlocks();
Expand All @@ -31,7 +35,7 @@ public override Block<T> this[HashDigest<SHA256> key]
{
get
{
Block<T> block = Store.GetBlock<T>(key);
Block<T> block = GetBlock(key);
if (block is null)
{
throw new KeyNotFoundException(
Expand All @@ -58,6 +62,7 @@ public override Block<T> this[HashDigest<SHA256> key]

value.Validate(DateTimeOffset.UtcNow);
Store.PutBlock(value);
_cache.Add(value.Hash, value);
}
}

Expand All @@ -74,7 +79,35 @@ public override bool ContainsKey(HashDigest<SHA256> key)

public override bool Remove(HashDigest<SHA256> key)
{
return Store.DeleteBlock(key);
bool deleted = Store.DeleteBlock(key);

_cache.Remove(key);

return deleted;
}

private Block<T> GetBlock(HashDigest<SHA256> key)
{
if (_cache.TryGetValue(key, out Block<T> cached))
{
if (Store.ContainsBlock(key))
{
return cached;
}
else
{
// The cached block had been deleted on Store...
_cache.Remove(key);
}
}

Block<T> fetched = Store.GetBlock<T>(key);
if (!(fetched is null))
{
_cache.Add(key, fetched);
}

return fetched;
}
}
}

0 comments on commit 63048cc

Please sign in to comment.