Skip to content

Commit

Permalink
Merge branch 'master' into feature/gnosis-cancun
Browse files Browse the repository at this point in the history
  • Loading branch information
rubo authored Feb 12, 2024
2 parents c0185d1 + 2a4edee commit 306ecdd
Show file tree
Hide file tree
Showing 47 changed files with 297 additions and 193 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ protected TestContractBlockchain()
ChainSpecLoader loader = new(new EthereumJsonSerializer());
string name = string.IsNullOrEmpty(testSuffix) ? $"{typeof(TTestClass).FullName}.json" : $"{typeof(TTestClass).FullName}.{testSuffix}.json";
using Stream? stream = typeof(TTestClass).Assembly.GetManifestResourceStream(name);
using StreamReader reader = new(stream ?? new MemoryStream());
ChainSpec chainSpec = loader.Load(reader.ReadToEnd());
ChainSpec chainSpec = loader.Load(stream);
ChainSpecBasedSpecProvider chainSpecBasedSpecProvider = new(chainSpec);
return (chainSpec, chainSpecBasedSpecProvider);
}
Expand Down
108 changes: 104 additions & 4 deletions src/Nethermind/Nethermind.Benchmark/Store/PatriciaTreeBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
using Nethermind.Core.Test.Builders;
using Nethermind.Db;
using Nethermind.Int256;
using Nethermind.Logging;
using Nethermind.State;
using Nethermind.Trie.Pruning;

namespace Nethermind.Benchmarks.Store
{

[MemoryDiagnoser]
public class PatriciaTreeBenchmarks
{
private static readonly Account _empty = Build.An.Account.WithBalance(0).TestObject;
Expand All @@ -20,6 +28,21 @@ public class PatriciaTreeBenchmarks

private StateTree _tree;

private Hash256 _rootHash;

// Just the backing KV. Used for benchmarking that include deserialization overhead.
private MemDb _backingMemory;

// Full uncommitted tree with in memory node. Node should be fully deserialized.
private StateTree _uncommittedFullTree;

private StateTree _fullTree;

// All entries
private const int _entryCount = 1024 * 4;
private (Hash256, Account)[] _entries;
private (Hash256, Account)[] _entriesShuffled;

private (string Name, Action<StateTree> Action)[] _scenarios = new (string, Action<StateTree>)[]
{
("set_3_via_address", tree =>
Expand Down Expand Up @@ -198,10 +221,45 @@ public class PatriciaTreeBenchmarks
public void Setup()
{
_tree = new StateTree();

_entries = new (Hash256, Account)[_entryCount];
for (int i = 0; i < _entryCount; i++)
{
_entries[i] = (Keccak.Compute(i.ToBigEndianByteArray()), new Account((UInt256)i));
}

_entriesShuffled = new (Hash256, Account)[_entryCount];
for (int i = 0; i < _entryCount; i++)
{
_entriesShuffled[i] = _entries[i];
}
new Random(0).Shuffle(_entriesShuffled);

_backingMemory = new MemDb();
StateTree tempTree = new StateTree(new TrieStore(_backingMemory, NullLogManager.Instance), NullLogManager.Instance);
for (int i = 0; i < _entryCount; i++)
{
tempTree.Set(_entries[i].Item1, _entries[i].Item2);
}
tempTree.Commit(0);
_rootHash = tempTree.RootHash;

_fullTree = new StateTree();
for (int i = 0; i < _entryCount; i++)
{
_fullTree.Set(_entries[i].Item1, _entries[i].Item2);
}
_fullTree.Commit(0);

_uncommittedFullTree = new StateTree();
for (int i = 0; i < _entryCount; i++)
{
_uncommittedFullTree.Set(_entries[i].Item1, _entries[i].Item2);
}
}

[Benchmark]
public void Improved()
public void Scenarios()
{
for (int i = 0; i < 19; i++)
{
Expand All @@ -210,11 +268,53 @@ public void Improved()
}

[Benchmark]
public void Current()
public void InsertAndHash()
{
for (int i = 0; i < 19; i++)
StateTree tempTree = new StateTree();
for (int i = 0; i < _entryCount; i++)
{
_scenarios[i].Action(_tree);
tempTree.Set(_entries[i].Item1, _entries[i].Item2);
}
tempTree.UpdateRootHash();
}

[Benchmark]
public void InsertAndCommit()
{
StateTree tempTree = new StateTree(new TrieStore(new MemDb(), NullLogManager.Instance), NullLogManager.Instance);
for (int i = 0; i < _entryCount; i++)
{
tempTree.Set(_entries[i].Item1, _entries[i].Item2);
}
tempTree.Commit(0);
}

[Benchmark]
public void ReadWithFullTree()
{
for (int i = 0; i < _entryCount; i++)
{
_fullTree.Get(_entriesShuffled[i].Item1);
}
}

[Benchmark]
public void ReadWithUncommittedFullTree()
{
for (int i = 0; i < _entryCount; i++)
{
_uncommittedFullTree.Get(_entriesShuffled[i].Item1);
}
}

[Benchmark]
public void ReadAndDeserialize()
{
StateTree tempTree = new StateTree(new TrieStore(_backingMemory, NullLogManager.Instance), NullLogManager.Instance);
tempTree.RootHash = _rootHash;
for (int i = 0; i < _entryCount; i++)
{
tempTree.Get(_entriesShuffled[i].Item1);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System.IO;
Expand Down Expand Up @@ -71,9 +71,8 @@ private Block GetGenesisBlock(string chainspecPath)

private static ChainSpec LoadChainSpec(string path)
{
string data = File.ReadAllText(path);
ChainSpecLoader chainSpecLoader = new(new EthereumJsonSerializer());
ChainSpec chainSpec = chainSpecLoader.Load(data);
ChainSpec chainSpec = chainSpecLoader.LoadFromFile(path);
return chainSpec;
}
}
7 changes: 2 additions & 5 deletions src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class BlockStore : IBlockStore

private readonly LruCache<ValueHash256, Block>
_blockCache = new(CacheSize, CacheSize, "blocks");
private long? _maxSize;
private readonly long? _maxSize;

public BlockStore(IDb blockDb, long? maxSize = null)
{
Expand Down Expand Up @@ -97,10 +97,7 @@ public void Delete(long blockNumber, Hash256 blockHash)
GetBlockNumPrefixedKey(blockNumber, blockHash, keyWithBlockNumber);

MemoryManager<byte>? memoryOwner = _blockDb.GetOwnedMemory(keyWithBlockNumber);
if (memoryOwner is null)
{
memoryOwner = _blockDb.GetOwnedMemory(blockHash.Bytes);
}
memoryOwner ??= _blockDb.GetOwnedMemory(blockHash.Bytes);

return BlockDecoder.DecodeToReceiptRecoveryBlock(memoryOwner, memoryOwner?.Memory ?? Memory<byte>.Empty, RlpBehaviors.None);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class CopyTreeVisitor : ITreeVisitor, IDisposable
private readonly WriteFlags _writeFlags;
private readonly CancellationToken _cancellationToken;
private const int Million = 1_000_000;
private ConcurrentWriteBatcher _concurrentWriteBatcher;
private readonly ConcurrentWriteBatcher _concurrentWriteBatcher;

public CopyTreeVisitor(
IPruningContext pruningContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

namespace Nethermind.Consensus.Processing;

public class BlockchainProcessor : IBlockchainProcessor, IBlockProcessingQueue
public sealed class BlockchainProcessor : IBlockchainProcessor, IBlockProcessingQueue
{
public int SoftMaxRecoveryQueueSizeInTx = 10000; // adjust based on tx or gas
public const int MaxProcessingQueueSize = 2000; // adjust based on tx or gas
Expand Down Expand Up @@ -749,8 +749,6 @@ public void Dispose()
_recoveryQueue.Dispose();
_blockQueue.Dispose();
_loopCancellationSource?.Dispose();
_recoveryTask?.Dispose();
_processorTask?.Dispose();
_blockTree.NewBestSuggestedBlock -= OnNewBestBlock;
_blockTree.NewHeadBlock -= OnNewHeadBlock;
}
Expand Down
8 changes: 4 additions & 4 deletions src/Nethermind/Nethermind.Core/Bloom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public BloomStructRef(ReadOnlySpan<byte> bytes)

public ReadOnlySpan<byte> Bytes { get; }

public bool Matches(ReadOnlySpan<byte> sequence)
public readonly bool Matches(ReadOnlySpan<byte> sequence)
{
Bloom.BloomExtract indexes = GetExtract(sequence);
return Matches(in indexes);
Expand Down Expand Up @@ -281,7 +281,7 @@ public override readonly int GetHashCode()
return Core.Extensions.Bytes.GetSimplifiedHashCode(Bytes);
}

public bool Matches(LogEntry logEntry)
public readonly bool Matches(LogEntry logEntry)
{
if (Matches(logEntry.LoggersAddress))
{
Expand All @@ -306,9 +306,9 @@ private readonly bool Get(int index)
return Bytes[bytePosition].GetBit(shift);
}

public bool Matches(Address address) => Matches(address.Bytes);
public readonly bool Matches(Address address) => Matches(address.Bytes);

public bool Matches(Hash256 topic) => Matches(topic.Bytes);
public readonly bool Matches(Hash256 topic) => Matches(topic.Bytes);

public readonly bool Matches(in Bloom.BloomExtract extract) => Get(extract.Index1) && Get(extract.Index2) && Get(extract.Index3);

Expand Down
23 changes: 0 additions & 23 deletions src/Nethermind/Nethermind.Core/Collections/IListExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,29 +57,6 @@ public static int BinarySearch<TItem, TSearch>(this IList<TItem> list, TSearch v
return ~lower;
}

/// <summary>
/// Performs a binary search on the specified collection.
/// </summary>
/// <typeparam name="TItem">The type of the item.</typeparam>
/// <param name="list">The list to be searched.</param>
/// <param name="value">The value to search for.</param>
/// <returns></returns>
public static int BinarySearch<TItem>(this IList<TItem> list, TItem value) => BinarySearch(list, value, Comparer<TItem>.Default);

/// <summary>
/// Performs a binary search on the specified collection.
/// </summary>
/// <typeparam name="TItem">The type of the item.</typeparam>
/// <param name="list">The list to be searched.</param>
/// <param name="value">The value to search for.</param>
/// <param name="comparer">The comparer that is used to compare the value
/// with the list items.</param>
/// <returns></returns>
public static int BinarySearch<TItem>(this IList<TItem> list, TItem value, IComparer<TItem> comparer) => list.BinarySearch(value, comparer.Compare);

public static bool TryGetSearchedItem<TComparable>(this IList<TComparable> list, in TComparable activation, out TComparable? item) where TComparable : IComparable<TComparable> =>
list.TryGetSearchedItem(activation, (b, c) => b.CompareTo(c), out item);

public static bool TryGetForBlock(this IList<long> list, in long blockNumber, out long item) =>
list.TryGetSearchedItem(blockNumber, (b, c) => b.CompareTo(c), out item);

Expand Down
37 changes: 34 additions & 3 deletions src/Nethermind/Nethermind.Core/Collections/StackList.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Nethermind.Core.Collections
{
public class StackList<T> : List<T>
public sealed class StackList<T> : List<T>
where T : struct, IComparable<T>
{
public T Peek() => this[^1];

public bool TryPeek(out T? item)
public bool TryPeek(out T item)
{
if (Count > 0)
{
Expand All @@ -30,7 +33,7 @@ public T Pop()
return value;
}

public bool TryPop(out T? item)
public bool TryPop(out T item)
{
if (Count > 0)
{
Expand All @@ -48,5 +51,33 @@ public void Push(T item)
{
Add(item);
}

public bool TryGetSearchedItem(T activation, out T item)
{
Span<T> span = CollectionsMarshal.AsSpan(this);
int index = span.BinarySearch(activation);
bool result;
if ((uint)index < (uint)span.Length)
{
item = span[index];
result = true;
}
else
{
index = ~index - 1;
if ((uint)index < (uint)span.Length)
{
item = span[index];
result = true;
}
else
{
item = default;
result = false;
}
}

return result;
}
}
}
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.Crypto/Keccak512.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public Keccak512(byte[] bytes)

public byte[]? Bytes { get; }

public override string ToString()
public override readonly string ToString()
{
return ToString(true);
}
Expand Down Expand Up @@ -112,7 +112,7 @@ public readonly bool Equals(Keccak512 other)
return Core.Extensions.Bytes.AreEqual(other.Bytes, Bytes);
}

public override bool Equals(object obj)
public override readonly bool Equals(object obj)
{
return obj?.GetType() == typeof(Keccak512) && Equals((Keccak512)obj);
}
Expand Down
4 changes: 1 addition & 3 deletions src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -985,9 +985,7 @@ protected internal bool KeyExistsWithColumn(ReadOnlySpan<byte> key, ColumnFamily

try
{
// seems it has no performance impact
return _db.Get(key, cf, _defaultReadOptions) is not null;
// return _db.Get(key, 32, _keyExistsBuffer, 0, 0, null, null) != -1;
return _db.HasKey(key, cf, _defaultReadOptions);
}
catch (RocksDbSharpException e)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Db/IDb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void Flush() { }
void Clear() { }
void Compact() { }

struct DbMetric
readonly struct DbMetric
{
public long Size { get; init; }
public long CacheSize { get; init; }
Expand Down
Loading

0 comments on commit 306ecdd

Please sign in to comment.