Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hunting allocations #6601

Merged
merged 5 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Nethermind/Nethermind.Analytics/SupplyVerifier.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using Nethermind.Core;
using Nethermind.Core.Crypto;
Expand Down Expand Up @@ -78,7 +79,7 @@ public void VisitExtension(TrieNode node, TrieVisitContext trieVisitContext)
}
}

public void VisitLeaf(TrieNode node, TrieVisitContext trieVisitContext, byte[] value = null)
public void VisitLeaf(TrieNode node, TrieVisitContext trieVisitContext, ReadOnlySpan<byte> value)
{
_nodesVisited++;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void VisitMissingNode(Hash256 nodeHash, TrieVisitContext trieVisitContext

public void VisitExtension(TrieNode node, TrieVisitContext trieVisitContext) => PersistNode(node);

public void VisitLeaf(TrieNode node, TrieVisitContext trieVisitContext, byte[]? value = null) => PersistNode(node);
public void VisitLeaf(TrieNode node, TrieVisitContext trieVisitContext, ReadOnlySpan<byte> value) => PersistNode(node);

public void VisitCode(Hash256 codeHash, TrieVisitContext trieVisitContext) { }

Expand All @@ -78,7 +78,7 @@ private void PersistNode(TrieNode node)
if (node.Keccak is not null)
{
// simple copy of nodes RLP
_pruningContext.Set(node.Keccak.Bytes, node.FullRlp.ToArray(), _writeFlags);
_pruningContext.PutSpan(node.Keccak.Bytes, node.FullRlp.AsSpan(), _writeFlags);
Interlocked.Increment(ref _persistedNodes);

// log message every 1 mln nodes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public ref struct KeccaksIterator
private readonly Span<byte> _buffer;
public long Index { get; private set; }

public KeccaksIterator(Span<byte> data, Span<byte> buffer)
public KeccaksIterator(ReadOnlySpan<byte> data, Span<byte> buffer)
{
if (buffer.Length != 32) throw new ArgumentException("Buffer must be 32 bytes long");
_decoderContext = new Rlp.ValueDecoderContext(data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public ref struct LogEntriesIterator
private readonly IReceiptRefDecoder _receiptRefDecoder;
public long Index { get; private set; }

public LogEntriesIterator(Span<byte> data, IReceiptRefDecoder receiptRefDecoder)
public LogEntriesIterator(ReadOnlySpan<byte> data, IReceiptRefDecoder receiptRefDecoder)
{
_decoderContext = new Rlp.ValueDecoderContext(data);
_length = _decoderContext.ReadSequenceLength();
Expand Down
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.Core/Address.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ public ref struct AddressStructRef
private const int HexCharsCount = 2 * ByteLength; // 5a4eab120fb44eb6684e5e32785702ff45ea344d
private const int PrefixedHexCharsCount = 2 + HexCharsCount; // 0x5a4eab120fb44eb6684e5e32785702ff45ea344d

public Span<byte> Bytes { get; }
public ReadOnlySpan<byte> Bytes { get; }

public AddressStructRef(Hash256StructRef keccak) : this(keccak.Bytes.Slice(12, ByteLength)) { }

Expand Down Expand Up @@ -274,7 +274,7 @@ public static bool IsValidAddress(string hexString, bool allowPrefix)

public AddressStructRef(string hexString) : this(Extensions.Bytes.FromHexString(hexString)) { }

public AddressStructRef(Span<byte> bytes)
public AddressStructRef(ReadOnlySpan<byte> bytes)
{
if (bytes.Length != ByteLength)
{
Expand Down
56 changes: 2 additions & 54 deletions src/Nethermind/Nethermind.Core/Bloom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,37 +229,12 @@ public ref struct BloomStructRef
public const int BitLength = 2048;
public const int ByteLength = BitLength / 8;

public BloomStructRef(LogEntry[] logEntries, Bloom? blockBloom = null)
{
Bytes = new byte[ByteLength];
Add(logEntries, blockBloom);
}

public BloomStructRef(Span<byte> bytes)
public BloomStructRef(ReadOnlySpan<byte> bytes)
LukaszRozmej marked this conversation as resolved.
Show resolved Hide resolved
{
Bytes = bytes;
}

public Span<byte> Bytes { get; }

public void Set(ReadOnlySpan<byte> sequence)
{
Set(sequence, null);
}

private readonly void Set(ReadOnlySpan<byte> sequence, Bloom? masterBloom = null)
{
Bloom.BloomExtract indexes = GetExtract(sequence);
Set(indexes.Index1);
Set(indexes.Index2);
Set(indexes.Index3);
if (masterBloom is not null)
{
masterBloom.Set(indexes.Index1);
masterBloom.Set(indexes.Index2);
masterBloom.Set(indexes.Index3);
}
}
public ReadOnlySpan<byte> Bytes { get; }

public bool Matches(ReadOnlySpan<byte> sequence)
{
Expand Down Expand Up @@ -306,26 +281,6 @@ public override readonly int GetHashCode()
return Core.Extensions.Bytes.GetSimplifiedHashCode(Bytes);
}

public void Add(LogEntry[] logEntries, Bloom? blockBloom)
{
for (int entryIndex = 0; entryIndex < logEntries.Length; entryIndex++)
{
LogEntry logEntry = logEntries[entryIndex];
byte[] addressBytes = logEntry.LoggersAddress.Bytes;
Set(addressBytes, blockBloom);
for (int topicIndex = 0; topicIndex < logEntry.Topics.Length; topicIndex++)
{
Hash256 topic = logEntry.Topics[topicIndex];
Set(topic.Bytes, blockBloom);
}
}
}

public readonly void Accumulate(BloomStructRef bloom)
{
Bytes.Or(bloom.Bytes);
}

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

private readonly void Set(int index)
{
int bytePosition = index / 8;
int shift = index % 8;
Bytes[bytePosition].SetBit(shift);
}

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

public bool Matches(Hash256 topic) => Matches(topic.Bytes);
Expand Down
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.Core/Crypto/Hash256.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,9 @@ public ref struct Hash256StructRef

public static int MemorySize => MemorySizes.ArrayOverhead + Size;

public Span<byte> Bytes { get; }
public ReadOnlySpan<byte> Bytes { get; }

public Hash256StructRef(Span<byte> bytes)
public Hash256StructRef(ReadOnlySpan<byte> bytes)
{
if (bytes.Length != Size)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Core/IKeyValueStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ bool KeyExists(ReadOnlySpan<byte> key)
return result;
}

void DangerousReleaseMemory(in Span<byte> span) { }
void DangerousReleaseMemory(in ReadOnlySpan<byte> span) { }
}

public interface IWriteOnlyKeyValueStore
Expand Down
6 changes: 3 additions & 3 deletions src/Nethermind/Nethermind.Core/LogEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public LogEntry(Address address, byte[] data, Hash256[] topics)

public ref struct LogEntryStructRef
{
public LogEntryStructRef(AddressStructRef address, Span<byte> data, Span<byte> topicsRlp)
public LogEntryStructRef(AddressStructRef address, ReadOnlySpan<byte> data, ReadOnlySpan<byte> topicsRlp)
{
LoggersAddress = address;
Data = data;
Expand All @@ -45,8 +45,8 @@ public LogEntryStructRef(LogEntry logEntry)
/// <summary>
/// Rlp encoded array of Keccak
/// </summary>
public Span<byte> TopicsRlp { get; }
public ReadOnlySpan<byte> TopicsRlp { get; }

public Span<byte> Data { get; }
public ReadOnlySpan<byte> Data { get; }
}
}
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Core/TransactionReceipt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public ref struct TxReceiptStructRef
/// <summary>
/// Rlp encoded logs
/// </summary>
public Span<byte> LogsRlp { get; set; }
public ReadOnlySpan<byte> LogsRlp { get; set; }

public LogEntry[]? Logs { get; set; }

Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public void Compact()
public long GetIndexSize() => _mainDb.GetIndexSize();
public long GetMemtableSize() => _mainDb.GetMemtableSize();

public void DangerousReleaseMemory(in Span<byte> span)
public void DangerousReleaseMemory(in ReadOnlySpan<byte> span)
{
_mainDb.DangerousReleaseMemory(span);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ public void PutSpan(ReadOnlySpan<byte> key, ReadOnlySpan<byte> value, WriteFlags
SetWithColumnFamily(key, null, value, writeFlags);
}

public void DangerousReleaseMemory(in Span<byte> span)
public void DangerousReleaseMemory(in ReadOnlySpan<byte> span)
{
if (!span.IsNullOrEmpty())
{
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Db.Rpc/RpcDb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public void PutSpan(ReadOnlySpan<byte> key, ReadOnlySpan<byte> value, WriteFlags
Set(key, value.ToArray(), writeFlags);
}

public void DangerousReleaseMemory(in Span<byte> span)
public void DangerousReleaseMemory(in ReadOnlySpan<byte> span)
{
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Db/MemDb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public virtual Span<byte> GetSpan(ReadOnlySpan<byte> key)
return Get(key).AsSpan();
}

public void DangerousReleaseMemory(in Span<byte> span)
public void DangerousReleaseMemory(in ReadOnlySpan<byte> span)
{
}

Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Db/ReadOnlyDb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public void PutSpan(ReadOnlySpan<byte> keyBytes, ReadOnlySpan<byte> value, Write
_memDb.Set(keyBytes, value.ToArray(), writeFlags);
}

public void DangerousReleaseMemory(in Span<byte> span) { }
public void DangerousReleaseMemory(in ReadOnlySpan<byte> span) { }

public bool PreferWriteByArray => true; // Because of memdb buffer
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
using NUnit.Framework;
using System.Threading.Tasks;
using Nethermind.Consensus.Processing;
using Nethermind.Core.Buffers;
using Nethermind.State.Tracing;
using NSubstitute;

Expand Down Expand Up @@ -850,8 +851,8 @@ private async Task TestCallWithStorageAndCode(byte[] code, UInt256 gasPrice, Add
// the exception will be thrown if the account did not exist before the call
try
{
byte[] verifyOneProof = ProofVerifier.VerifyOneProof(accountProof.Proof!, block.StateRoot!)!;
new AccountDecoder().Decode(new RlpStream(verifyOneProof));
CappedArray<byte> verifyOneProof = ProofVerifier.VerifyOneProof(accountProof.Proof!, block.StateRoot!);
new AccountDecoder().Decode(verifyOneProof.AsSpan());
}
catch (Exception)
{
Expand Down
54 changes: 53 additions & 1 deletion src/Nethermind/Nethermind.Serialization.Rlp/AccountDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Nethermind.Serialization.Rlp
{
public class AccountDecoder : IRlpObjectDecoder<Account?>, IRlpStreamDecoder<Account?>
public class AccountDecoder : IRlpObjectDecoder<Account?>, IRlpStreamDecoder<Account?>, IRlpValueDecoder<Account?>
{
private readonly bool _slimFormat;

Expand Down Expand Up @@ -201,5 +201,57 @@ private Hash256 DecodeCodeHash(RlpStream rlpStream)

return codeHash;
}

public Account? Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
{
int length = decoderContext.ReadSequenceLength();
if (length == 1)
{
return null;
}

UInt256 nonce = decoderContext.DecodeUInt256();
UInt256 balance = decoderContext.DecodeUInt256();
Hash256 storageRoot = DecodeStorageRoot(ref decoderContext);
Hash256 codeHash = DecodeCodeHash(ref decoderContext);
if (ReferenceEquals(storageRoot, Keccak.EmptyTreeHash) && ReferenceEquals(codeHash, Keccak.OfAnEmptyString))
{
return new(nonce, balance);
}

return new(nonce, balance, storageRoot, codeHash);
}

private Hash256 DecodeStorageRoot(ref Rlp.ValueDecoderContext rlpStream)
{
Hash256 storageRoot;
if (_slimFormat && rlpStream.IsNextItemEmptyArray())
{
rlpStream.ReadByte();
storageRoot = Keccak.EmptyTreeHash;
}
else
{
storageRoot = rlpStream.DecodeKeccak();
}

return storageRoot;
}

private Hash256 DecodeCodeHash(ref Rlp.ValueDecoderContext rlpStream)
{
Hash256 codeHash;
if (_slimFormat && rlpStream.IsNextItemEmptyArray())
{
rlpStream.ReadByte();
codeHash = Keccak.OfAnEmptyString;
}
else
{
codeHash = rlpStream.DecodeKeccak();
}

return codeHash;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public void DecodeStructRef(scoped ref Rlp.ValueDecoderContext decoderContext, R

decoderContext.SkipLength();

Span<byte> firstItem = decoderContext.DecodeByteArraySpan();
ReadOnlySpan<byte> firstItem = decoderContext.DecodeByteArraySpan();
if (firstItem.Length == 1)
{
item.StatusCode = firstItem[0];
Expand Down
11 changes: 11 additions & 0 deletions src/Nethermind/Nethermind.Serialization.Rlp/IRlpDecoder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;

namespace Nethermind.Serialization.Rlp
{
public interface IRlpDecoder
Expand All @@ -27,4 +29,13 @@ public interface IRlpValueDecoder<T> : IRlpDecoder<T>
{
T Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None);
}

public static class RlpValueDecoderExtensions
{
public static T Decode<T>(this IRlpValueDecoder<T> decoder, ReadOnlySpan<byte> bytes, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
{
Rlp.ValueDecoderContext context = new(bytes);
return decoder.Decode(ref context, rlpBehaviors);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ public void DecodeStructRef(scoped ref Rlp.ValueDecoderContext decoderContext, R
}

decoderContext.ReadSequenceLength();
Span<byte> firstItem = decoderContext.DecodeByteArraySpan();
ReadOnlySpan<byte> firstItem = decoderContext.DecodeByteArraySpan();
if (firstItem.Length == 1)
{
item.StatusCode = firstItem[0];
Expand Down
Loading