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

Use non-allocating Int64 key generation #7413

Merged
merged 3 commits into from
Sep 13, 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
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ public long MigratedBlockNumber
set
{
_migratedBlockNumber = value;
_defaultColumn.Set(MigrationBlockNumberKey, MigratedBlockNumber.ToBigEndianByteArrayWithoutLeadingZeros());
_defaultColumn.PutSpan(MigrationBlockNumberKey.Bytes, value.ToBigEndianSpanWithoutLeadingZeros(out _));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void SetValidators(long finalizingBlockNumber, Address[] validators)
var validatorInfo = new ValidatorInfo(finalizingBlockNumber, _latestFinalizedValidatorsBlockNumber, validators);
var rlp = Rlp.Encode(validatorInfo);
_db.Set(GetKey(finalizingBlockNumber), rlp.Bytes);
_db.Set(LatestFinalizedValidatorsBlockNumberKey, finalizingBlockNumber.ToBigEndianByteArrayWithoutLeadingZeros());
_db.PutSpan(LatestFinalizedValidatorsBlockNumberKey.Bytes, finalizingBlockNumber.ToBigEndianSpanWithoutLeadingZeros(out _));
_latestFinalizedValidatorsBlockNumber = finalizingBlockNumber;
_latestValidatorInfo = validatorInfo;
Metrics.ValidatorsCount = validators.Length;
Expand Down
115 changes: 12 additions & 103 deletions src/Nethermind/Nethermind.Core/Extensions/Int64Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,120 +3,29 @@

using System;
using System.Buffers.Binary;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using Nethermind.Int256;

namespace Nethermind.Core.Extensions;

public static class Int64Extensions
{
public static byte[] ToBigEndianByteArrayWithoutLeadingZeros(this long value)
public static ReadOnlySpan<byte> ToBigEndianSpanWithoutLeadingZeros(this long value, out long buffer)
{
byte byte6 = (byte)(value >> 8);
byte byte5 = (byte)(value >> 16);
byte byte4 = (byte)(value >> 24);
byte byte3 = (byte)(value >> 32);
byte byte2 = (byte)(value >> 40);
byte byte1 = (byte)(value >> 48);
byte byte0 = (byte)(value >> 56);

if (byte0 == 0)
{
if (byte1 == 0)
{
if (byte2 == 0)
{
if (byte3 == 0)
{
if (byte4 == 0)
{
if (byte5 == 0)
{
if (byte6 == 0)
{
byte[] bytes = new byte[1];
bytes[0] = (byte)value;
return bytes;
}
else
{
byte[] bytes = new byte[2];
bytes[1] = (byte)value;
bytes[0] = byte6;
return bytes;
}
}
else
{
byte[] bytes = new byte[3];
bytes[2] = (byte)value;
bytes[1] = byte6;
bytes[0] = byte5;
return bytes;
}
}
else
{
byte[] bytes = new byte[4];
bytes[3] = (byte)value;
bytes[2] = byte6;
bytes[1] = byte5;
bytes[0] = byte4;
return bytes;
}
}
else
{
byte[] bytes = new byte[5];
bytes[4] = (byte)value;
bytes[3] = byte6;
bytes[2] = byte5;
bytes[1] = byte4;
bytes[0] = byte3;
return bytes;
}
}
else
{
byte[] bytes = new byte[6];
bytes[5] = (byte)value;
bytes[4] = byte6;
bytes[3] = byte5;
bytes[2] = byte4;
bytes[1] = byte3;
bytes[0] = byte2;
return bytes;
}
}
else
{
byte[] bytes = new byte[7];
bytes[6] = (byte)value;
bytes[5] = byte6;
bytes[4] = byte5;
bytes[3] = byte4;
bytes[2] = byte3;
bytes[1] = byte2;
bytes[0] = byte1;
return bytes;
}
}
else
{
byte[] bytes = new byte[8];
bytes[7] = (byte)value;
bytes[6] = byte6;
bytes[5] = byte5;
bytes[4] = byte4;
bytes[3] = byte3;
bytes[2] = byte2;
bytes[1] = byte1;
bytes[0] = byte0;
return bytes;
}
// Min 7 bytes as we still want a byte if the value is 0.
var start = Math.Min(BitOperations.LeadingZeroCount((ulong)value) / sizeof(long), sizeof(long) - 1);
// We create the span over the out value to ensure the span stack space remains valid.
buffer = BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(value) : value;
ReadOnlySpan<byte> span = MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref buffer, 1));
return span[start..];
}

public static byte[] ToBigEndianByteArrayWithoutLeadingZeros(this long value)
=> value.ToBigEndianSpanWithoutLeadingZeros(out _).ToArray();

public static byte[] ToBigEndianByteArray(this long value)
{
byte[] bytes = BitConverter.GetBytes(value);
Expand Down
2 changes: 0 additions & 2 deletions src/Nethermind/Nethermind.Core/IKeyValueStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Buffers;
using Nethermind.Core.Buffers;
using Nethermind.Core.Extensions;

namespace Nethermind.Core
Expand Down
10 changes: 5 additions & 5 deletions src/Nethermind/Nethermind.Core/KeyValueStoreExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,18 @@ public static bool KeyExists(this IReadOnlyKeyValueStore db, Hash256 key)

public static bool KeyExists(this IReadOnlyKeyValueStore db, long key)
{
return db.KeyExists(key.ToBigEndianByteArrayWithoutLeadingZeros());
return db.KeyExists(key.ToBigEndianSpanWithoutLeadingZeros(out _));
}

public static byte[]? Get(this IReadOnlyKeyValueStore db, long key) => db[key.ToBigEndianByteArrayWithoutLeadingZeros()];
public static byte[]? Get(this IReadOnlyKeyValueStore db, long key) => db[key.ToBigEndianSpanWithoutLeadingZeros(out _)];

/// <summary>
///
/// </summary>
/// <param name="db"></param>
/// <param name="key"></param>
/// <returns>Can return null or empty Span on missing key</returns>
public static Span<byte> GetSpan(this IReadOnlyKeyValueStore db, long key) => db.GetSpan(key.ToBigEndianByteArrayWithoutLeadingZeros());
public static Span<byte> GetSpan(this IReadOnlyKeyValueStore db, long key) => db.GetSpan(key.ToBigEndianSpanWithoutLeadingZeros(out _));

public static MemoryManager<byte>? GetOwnedMemory(this IReadOnlyKeyValueStore db, ReadOnlySpan<byte> key)
{
Expand Down Expand Up @@ -140,7 +140,7 @@ public static void Delete(this IWriteOnlyKeyValueStore db, Hash256 key)

public static void Delete(this IWriteOnlyKeyValueStore db, long key)
{
db.Remove(key.ToBigEndianByteArrayWithoutLeadingZeros());
db.Remove(key.ToBigEndianSpanWithoutLeadingZeros(out _));
}

[SkipLocalsInit]
Expand All @@ -153,7 +153,7 @@ public static void Delete(this IWriteOnlyKeyValueStore db, long blockNumber, Has

public static void Set(this IWriteOnlyKeyValueStore db, long key, byte[] value)
{
db[key.ToBigEndianByteArrayWithoutLeadingZeros()] = value;
db[key.ToBigEndianSpanWithoutLeadingZeros(out _)] = value;
}

#endregion
Expand Down
1 change: 0 additions & 1 deletion src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using ConcurrentCollections;
using Nethermind.Config;
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Db/Blooms/BloomStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ public void Migrate(IEnumerable<BlockHeader> headers)

private void Set(Hash256 key, long value)
{
_bloomInfoDb.Set(key, value.ToBigEndianByteArrayWithoutLeadingZeros());
_bloomInfoDb.PutSpan(key.Bytes, value.ToBigEndianSpanWithoutLeadingZeros(out _));
}

public void Dispose()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static class KeyValueStoreRlpExtensions

public static TItem? Get<TItem>(this IReadOnlyKeyValueStore db, long key, IRlpStreamDecoder<TItem>? decoder, LruCache<long, TItem>? cache = null, RlpBehaviors rlpBehaviors = RlpBehaviors.None, bool shouldCache = true) where TItem : class
{
byte[] keyDb = key.ToBigEndianByteArrayWithoutLeadingZeros();
ReadOnlySpan<byte> keyDb = key.ToBigEndianSpanWithoutLeadingZeros(out _);
return Get(db, key, keyDb, decoder, cache, rlpBehaviors, shouldCache);
}

Expand Down