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

Perf/valuekeccak snap code #5689

Merged
merged 4 commits into from
May 12, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public interface ISnapSyncPeer
{
Task<AccountsAndProofs> GetAccountRange(AccountRange range, CancellationToken token);
Task<SlotsAndProofs> GetStorageRange(StorageRange range, CancellationToken token);
Task<byte[][]> GetByteCodes(IReadOnlyList<Keccak> codeHashes, CancellationToken token);
Task<byte[][]> GetByteCodes(IReadOnlyList<ValueKeccak> codeHashes, CancellationToken token);
Task<byte[][]> GetTrieNodes(AccountsToRefreshRequest request, CancellationToken token);
Task<byte[][]> GetTrieNodes(GetTrieNodesRequest request, CancellationToken token);
}
Expand Down
3 changes: 3 additions & 0 deletions src/Nethermind/Nethermind.Core.Test/Builders/TestItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ static TestItem()
PublicKeys = new PublicKey[255];
Addresses = new Address[255];
Keccaks = new Keccak[255];
ValueKeccaks = new ValueKeccak[255];

for (byte i = 1; i > 0; i++) // this will wrap around
{
Expand All @@ -36,6 +37,7 @@ static TestItem()
PublicKeys[i - 1] = PrivateKeys[i - 1].PublicKey;
Addresses[i - 1] = PublicKeys[i - 1].Address;
Keccaks[i - 1] = Keccak.Compute(PublicKeys[i - 1].Bytes);
ValueKeccaks[i - 1] = Keccaks[i - 1];
}
}

Expand Down Expand Up @@ -82,6 +84,7 @@ public static Keccak KeccakFromNumber(int i)
public static PublicKey[] PublicKeys;
public static Address[] Addresses;
public static Keccak[] Keccaks;
public static ValueKeccak[] ValueKeccaks;

public static Address AddressA = PublicKeyA.Address;
public static Address AddressB = PublicKeyB.Address;
Expand Down
30 changes: 16 additions & 14 deletions src/Nethermind/Nethermind.Core/Crypto/Keccak.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ namespace Nethermind.Core.Crypto
[DebuggerDisplay("{ToString()}")]
public readonly struct ValueKeccak : IEquatable<ValueKeccak>, IComparable<ValueKeccak>, IEquatable<Keccak>
{
private readonly Vector256<byte> Bytes;
private readonly Vector256<byte> _bytes;

public const int MemorySize = 32;

public Span<byte> BytesAsSpan => MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref Unsafe.AsRef(in Bytes), 1));
public Span<byte> BytesAsSpan => MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref Unsafe.AsRef(in _bytes), 1));

public ReadOnlySpan<byte> Span => MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in Bytes), 1));
public ReadOnlySpan<byte> Bytes => Span; // To reduce changes when switching to ValueKeccak.

public ReadOnlySpan<byte> Span => MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in _bytes), 1));

/// <returns>
/// <string>0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470</string>
Expand Down Expand Up @@ -57,25 +59,25 @@ public ValueKeccak(byte[]? bytes)
{
if (bytes is null || bytes.Length == 0)
{
Bytes = OfAnEmptyString.Bytes;
_bytes = OfAnEmptyString._bytes;
return;
}

Debug.Assert(bytes.Length == ValueKeccak.MemorySize);
Bytes = Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetArrayDataReference(bytes));
_bytes = Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetArrayDataReference(bytes));
}

public ValueKeccak(string? hex)
{
if (hex is null || hex.Length == 0)
{
Bytes = OfAnEmptyString.Bytes;
_bytes = OfAnEmptyString._bytes;
return;
}

byte[] bytes = Extensions.Bytes.FromHexString(hex);
Debug.Assert(bytes.Length == ValueKeccak.MemorySize);
Bytes = Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetArrayDataReference(bytes));
_bytes = Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetArrayDataReference(bytes));
}

public ValueKeccak(Span<byte> bytes)
Expand All @@ -85,12 +87,12 @@ public ValueKeccak(ReadOnlySpan<byte> bytes)
{
if (bytes.Length == 0)
{
Bytes = OfAnEmptyString.Bytes;
_bytes = OfAnEmptyString._bytes;
return;
}

Debug.Assert(bytes.Length == ValueKeccak.MemorySize);
Bytes = Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetReference(bytes));
_bytes = Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetReference(bytes));
}

[DebuggerStepThrough]
Expand All @@ -115,16 +117,16 @@ private static ValueKeccak InternalCompute(byte[] input)

public override bool Equals(object? obj) => obj is ValueKeccak keccak && Equals(keccak);

public bool Equals(ValueKeccak other) => Bytes.Equals(other.Bytes);
public bool Equals(ValueKeccak other) => _bytes.Equals(other._bytes);

public bool Equals(Keccak? other) => BytesAsSpan.SequenceEqual(other?.Bytes);

public override int GetHashCode()
{
long v0 = Unsafe.As<Vector256<byte>, long>(ref Unsafe.AsRef(in Bytes));
long v1 = Unsafe.Add(ref Unsafe.As<Vector256<byte>, long>(ref Unsafe.AsRef(in Bytes)), 1);
long v2 = Unsafe.Add(ref Unsafe.As<Vector256<byte>, long>(ref Unsafe.AsRef(in Bytes)), 2);
long v3 = Unsafe.Add(ref Unsafe.As<Vector256<byte>, long>(ref Unsafe.AsRef(in Bytes)), 3);
long v0 = Unsafe.As<Vector256<byte>, long>(ref Unsafe.AsRef(in _bytes));
long v1 = Unsafe.Add(ref Unsafe.As<Vector256<byte>, long>(ref Unsafe.AsRef(in _bytes)), 1);
long v2 = Unsafe.Add(ref Unsafe.As<Vector256<byte>, long>(ref Unsafe.AsRef(in _bytes)), 2);
long v3 = Unsafe.Add(ref Unsafe.As<Vector256<byte>, long>(ref Unsafe.AsRef(in _bytes)), 3);
v0 ^= v1;
v2 ^= v3;
v0 ^= v2;
Expand Down
6 changes: 3 additions & 3 deletions src/Nethermind/Nethermind.Core/Crypto/KeccakHash.cs
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ public static void ComputeHash(ReadOnlySpan<byte> input, Span<byte> output)
MemoryMarshal.AsBytes(state[..(size / sizeof(ulong))]).CopyTo(output);
}

public void Update(Span<byte> input)
public void Update(ReadOnlySpan<byte> input)
{
if (_hash is not null)
{
Expand All @@ -465,7 +465,7 @@ public void Update(Span<byte> input)
if (_remainderLength != 0)
{
// Copy data to our remainder
Span<byte> remainderAdditive = input[..Math.Min(input.Length, _roundSize - _remainderLength)];
ReadOnlySpan<byte> remainderAdditive = input[..Math.Min(input.Length, _roundSize - _remainderLength)];
remainderAdditive.CopyTo(_remainderBuffer.AsSpan(_remainderLength));

// Increment the length
Expand Down Expand Up @@ -501,7 +501,7 @@ public void Update(Span<byte> input)
while (input.Length >= _roundSize)
{
// Cast our input to ulongs.
Span<ulong> input64 = MemoryMarshal.Cast<byte, ulong>(input[.._roundSize]);
ReadOnlySpan<ulong> input64 = MemoryMarshal.Cast<byte, ulong>(input[.._roundSize]);

// Eliminate bounds check for state for the loop
_ = state[input64.Length];
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Crypto/KeccakRlpStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public KeccakRlpStream()
_keccakHash = keccakHash;
}

public override void Write(Span<byte> bytesToWrite)
public override void Write(ReadOnlySpan<byte> bytesToWrite)
{
_keccakHash.Update(bytesToWrite);
}
Expand Down
12 changes: 12 additions & 0 deletions src/Nethermind/Nethermind.Db/DbExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ public static void Set(this IDb db, Keccak key, Span<byte> value)
}
}

public static void Set(this IDb db, in ValueKeccak key, Span<byte> value)
{
if (db is IDbWithSpan dbWithSpan)
{
dbWithSpan.PutSpan(key.Bytes, value);
}
else
{
db[key.Bytes] = value.ToArray();
}
}

public static void Set(this IDb db, ReadOnlySpan<byte> key, ReadOnlySpan<byte> value)
{
if (db is IDbWithSpan dbWithSpan)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void Roundtrip_Many()
GetByteCodesMessage msg = new()
{
RequestId = MessageConstants.Random.NextLong(),
Hashes = TestItem.Keccaks,
Hashes = TestItem.ValueKeccaks,
Bytes = 10
};

Expand All @@ -34,7 +34,7 @@ public void Roundtrip_Empty()
GetByteCodesMessage msg = new()
{
RequestId = MessageConstants.Random.NextLong(),
Hashes = Array.Empty<Keccak>(),
Hashes = Array.Empty<ValueKeccak>(),
Bytes = 10
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class GetByteCodesMessage : SnapMessageBase
/// <summary>
/// Code hashes to retrieve the code for
/// </summary>
public IReadOnlyList<Keccak> Hashes { get; set; }
public IReadOnlyList<ValueKeccak> Hashes { get; set; }

/// <summary>
/// Soft limit at which to stop returning data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ protected override GetByteCodesMessage Deserialize(RlpStream rlpStream)
rlpStream.ReadSequenceLength();

message.RequestId = rlpStream.DecodeLong();
message.Hashes = rlpStream.DecodeArray(_ => rlpStream.DecodeKeccak());
message.Hashes = rlpStream.DecodeArray(_ => rlpStream.DecodeValueKeccak().Value);
message.Bytes = rlpStream.DecodeLong();

return message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class GetTrieNodesMessage : SnapMessageBase
/// <summary>
/// Root hash of the account trie to serve
/// </summary>
public Keccak RootHash { get; set; }
public ValueKeccak RootHash { get; set; }

/// <summary>
/// Trie paths to retrieve the nodes for, grouped by account
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ public async Task<SlotsAndProofs> GetStorageRange(StorageRange range, Cancellati
return new SlotsAndProofs() { PathsAndSlots = response.Slots, Proofs = response.Proofs };
}

public async Task<byte[][]> GetByteCodes(IReadOnlyList<Keccak> codeHashes, CancellationToken token)
public async Task<byte[][]> GetByteCodes(IReadOnlyList<ValueKeccak> codeHashes, CancellationToken token)
{
var request = new GetByteCodesMessage()
{
Expand Down Expand Up @@ -239,7 +239,7 @@ public async Task<byte[][]> GetTrieNodes(GetTrieNodesRequest request, Cancellati
return await GetTrieNodes(request.RootHash, request.AccountAndStoragePaths, token);
}

private async Task<byte[][]> GetTrieNodes(Keccak rootHash, PathGroup[] groups, CancellationToken token)
private async Task<byte[][]> GetTrieNodes(ValueKeccak rootHash, PathGroup[] groups, CancellationToken token)
{
GetTrieNodesMessage reqMsg = new()
{
Expand All @@ -263,7 +263,7 @@ private PathGroup[] GetPathGroups(AccountsToRefreshRequest request)
for (int i = 0; i < request.Paths.Length; i++)
{
AccountWithStorageStartingHash path = request.Paths[i];
groups[i] = new PathGroup() { Group = new[] { path.PathAndAccount.Path.Bytes, _emptyBytes } };
groups[i] = new PathGroup() { Group = new[] { path.PathAndAccount.Path.Bytes.ToArray(), _emptyBytes } };
}

return groups;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public NettyRlpStream(IByteBuffer buffer)
_initialPosition = buffer.ReaderIndex;
}

public override void Write(Span<byte> bytesToWrite)
public override void Write(ReadOnlySpan<byte> bytesToWrite)
{
_buffer.EnsureWritable(bytesToWrite.Length, true);

Expand Down
29 changes: 29 additions & 0 deletions src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,11 @@ public static int LengthOf(Keccak? item)
return item is null ? 1 : 33;
}

public static int LengthOf(in ValueKeccak? item)
{
return item is null ? 1 : 33;
}

public static int LengthOf(Keccak[] keccaks, bool includeLengthOfSequenceStart = false)
{
int value = keccaks?.Length * LengthOfKeccakRlp ?? 0;
Expand All @@ -1370,6 +1375,18 @@ public static int LengthOf(Keccak[] keccaks, bool includeLengthOfSequenceStart =
return value;
}

public static int LengthOf(ValueKeccak[] keccaks, bool includeLengthOfSequenceStart = false)
{
int value = keccaks?.Length * LengthOfKeccakRlp ?? 0;

if (includeLengthOfSequenceStart)
{
value = LengthOfSequence(value);
}

return value;
}

public static int LengthOf(IReadOnlyList<Keccak> keccaks, bool includeLengthOfSequenceStart = false)
{
int value = keccaks?.Count * LengthOfKeccakRlp ?? 0;
Expand All @@ -1382,6 +1399,18 @@ public static int LengthOf(IReadOnlyList<Keccak> keccaks, bool includeLengthOfSe
return value;
}

public static int LengthOf(IReadOnlyList<ValueKeccak> keccaks, bool includeLengthOfSequenceStart = false)
{
int value = keccaks?.Count * LengthOfKeccakRlp ?? 0;

if (includeLengthOfSequenceStart)
{
value = LengthOfSequence(value);
}

return value;
}

public static int LengthOf(Address? item)
{
return item is null ? 1 : 21;
Expand Down
Loading