From 7e15f4461a1a1c0eeaf3debecb020d91ce8b7eca Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Mon, 23 Dec 2024 12:18:46 +0000 Subject: [PATCH] Reduce guard checks and interface calls when using ArrayPoolList (#7960) --- .../Nethermind.Crypto/KeccakRlpStream.cs | 5 -- .../Eth/FeeHistory/FeeHistoryOracle.cs | 3 +- .../P2P/SerializerTester.cs | 1 + .../Eth/V65/Eth65ProtocolHandlerTests.cs | 3 +- .../Eth/V65/PooledTxsRequestorTests.cs | 60 +++++++++++-------- .../Eth/V68/Eth68ProtocolHandlerTests.cs | 4 +- .../NodeData/GetNodeDataMessageTests.cs | 6 +- .../GetStorageRangesMessageSerializerTests.cs | 4 +- .../GetTrieNodesMessageSerializerTests.cs | 2 +- .../TrieNodesMessageSerializerTests.cs | 4 +- .../Eth/HashesMessageSerializer.cs | 4 +- .../Subprotocols/Eth/IPooledTxsRequestor.cs | 8 +-- .../Subprotocols/Eth/PooledTxsRequestor.cs | 51 +++++++--------- .../Eth/V62/Eth62ProtocolHandler.cs | 6 +- .../Messages/TransactionsMessageSerializer.cs | 4 +- .../Eth/V65/Eth65ProtocolHandler.cs | 4 +- ...ledTransactionHashesMessageSerializer68.cs | 18 +++--- .../Snap/Messages/GetStorageRangeMessage.cs | 2 +- .../GetStorageRangesMessageSerializer.cs | 26 ++++---- .../Subprotocols/Snap/SnapProtocolHandler.cs | 4 +- .../NettyRlpStream.cs | 15 +---- .../Nethermind.Serialization.Rlp/RlpStream.cs | 35 ----------- 22 files changed, 111 insertions(+), 158 deletions(-) diff --git a/src/Nethermind/Nethermind.Crypto/KeccakRlpStream.cs b/src/Nethermind/Nethermind.Crypto/KeccakRlpStream.cs index 3a943a97bed..0d049e54e8b 100644 --- a/src/Nethermind/Nethermind.Crypto/KeccakRlpStream.cs +++ b/src/Nethermind/Nethermind.Crypto/KeccakRlpStream.cs @@ -30,11 +30,6 @@ public override void Write(ReadOnlySpan bytesToWrite) _keccakHash.Update(bytesToWrite); } - public override void Write(IReadOnlyList bytesToWrite) - { - _keccakHash.Update(bytesToWrite.ToArray()); - } - public override void WriteByte(byte byteToWrite) { _keccakHash.Update(MemoryMarshal.CreateSpan(ref byteToWrite, 1)); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/FeeHistory/FeeHistoryOracle.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/FeeHistory/FeeHistoryOracle.cs index cd6a76ceda2..bccfd97e433 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/FeeHistory/FeeHistoryOracle.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/FeeHistory/FeeHistoryOracle.cs @@ -254,10 +254,11 @@ static IEnumerable CalculateGasUsed(TxReceipt[] txReceipts) : txs.Select(static tx => tx.GasLimit)); List rewardInfos = new(txs.Length); + Span gasUsedSpan = gasUsed.AsSpan(); for (int i = 0; i < txs.Length; i++) { txs[i].TryCalculatePremiumPerGas(block.BaseFeePerGas, out UInt256 premiumPerGas); - rewardInfos.Add(new RewardInfo(gasUsed[i], premiumPerGas)); + rewardInfos.Add(new RewardInfo(gasUsedSpan[i], premiumPerGas)); } rewardInfos.Sort(static (i1, i2) => i1.PremiumPerGas.CompareTo(i2.PremiumPerGas)); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/SerializerTester.cs b/src/Nethermind/Nethermind.Network.Test/P2P/SerializerTester.cs index ecb452577cc..49af7bc0457 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/SerializerTester.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/SerializerTester.cs @@ -50,6 +50,7 @@ public static void TestZero(IZeroMessageSerializer serializer, T message, { buffer.Release(); buffer2.Release(); + message.TryDispose(); } } } diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandlerTests.cs index 2101315e42a..0da9a95c1b9 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandlerTests.cs @@ -10,6 +10,7 @@ using FluentAssertions; using Nethermind.Consensus; using Nethermind.Core; +using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Specs; @@ -196,7 +197,7 @@ public void should_handle_NewPooledTransactionHashesMessage([Values(true, false) HandleIncomingStatusMessage(); HandleZeroMessage(msg, Eth65MessageCode.NewPooledTransactionHashes); - _pooledTxsRequestor.Received(canGossipTransactions ? 1 : 0).RequestTransactions(Arg.Any>(), Arg.Any>()); + _pooledTxsRequestor.Received(canGossipTransactions ? 1 : 0).RequestTransactions(Arg.Any>(), Arg.Any>()); } private void HandleZeroMessage(T msg, int messageCode) where T : MessageBase diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTxsRequestorTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTxsRequestorTests.cs index 6dab74e1b83..bf4b2a8fd4e 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTxsRequestorTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V65/PooledTxsRequestorTests.cs @@ -12,6 +12,9 @@ using Nethermind.TxPool; using NSubstitute; using NUnit.Framework; +using System.Runtime.InteropServices; +using Nethermind.Core.Collections; +using Nethermind.Core.Extensions; namespace Nethermind.Network.Test.P2P.Subprotocols.Eth.V65 { @@ -20,74 +23,79 @@ public class PooledTxsRequestorTests private readonly ITxPool _txPool = Substitute.For(); private readonly Action _doNothing = static msg => msg.Dispose(); private IPooledTxsRequestor _requestor; - private IReadOnlyList _request; - private IList _expected; - private IReadOnlyList _response; + private ArrayPoolList _response; + [TearDown] + public void TearDown() + { + _response?.Dispose(); + } [Test] public void filter_properly_newPooledTxHashes() { - _response = new List(); _requestor = new PooledTxsRequestor(_txPool, new TxPoolConfig()); - _requestor.RequestTransactions(_doNothing, new List { TestItem.KeccakA, TestItem.KeccakD }); + using var skipped = new ArrayPoolList(2) { TestItem.KeccakA, TestItem.KeccakD }; + _requestor.RequestTransactions(_doNothing, skipped); - _request = new List { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }; - _expected = new List { TestItem.KeccakB, TestItem.KeccakC }; - _requestor.RequestTransactions(Send, _request); - _response.Should().BeEquivalentTo(_expected); + using var request = new ArrayPoolList(3) { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }; + using var expected = new ArrayPoolList(3) { TestItem.KeccakB, TestItem.KeccakC }; + _requestor.RequestTransactions(Send, request); + _response.Should().BeEquivalentTo(expected); } [Test] public void filter_properly_already_pending_hashes() { - _response = new List(); _requestor = new PooledTxsRequestor(_txPool, new TxPoolConfig()); - _requestor.RequestTransactions(_doNothing, new List { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }); + using var skipped = new ArrayPoolList(3) { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }; + _requestor.RequestTransactions(_doNothing, skipped); - _request = new List { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }; - _requestor.RequestTransactions(Send, _request); + using var request = new ArrayPoolList(3) { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }; + _requestor.RequestTransactions(Send, request); _response.Should().BeEmpty(); } [Test] public void filter_properly_discovered_hashes() { - _response = new List(); _requestor = new PooledTxsRequestor(_txPool, new TxPoolConfig()); - _request = new List { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }; - _expected = new List { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }; - _requestor.RequestTransactions(Send, _request); - _response.Should().BeEquivalentTo(_expected); + using var request = new ArrayPoolList(3) { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }; + using var expected = new ArrayPoolList(3) { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }; + _requestor.RequestTransactions(Send, request); + _response.Should().BeEquivalentTo(expected); } [Test] public void can_handle_empty_argument() { - _response = new List(); _requestor = new PooledTxsRequestor(_txPool, new TxPoolConfig()); - _requestor.RequestTransactions(Send, new List()); + using var skipped = new ArrayPoolList(0); + _requestor.RequestTransactions(Send, skipped); _response.Should().BeEmpty(); } [Test] public void filter_properly_hashes_present_in_hashCache() { - _response = new List(); ITxPool txPool = Substitute.For(); txPool.IsKnown(Arg.Any()).Returns(true); _requestor = new PooledTxsRequestor(txPool, new TxPoolConfig()); - _request = new List { TestItem.KeccakA, TestItem.KeccakB }; - _expected = new List { }; - _requestor.RequestTransactions(Send, _request); - _response.Should().BeEquivalentTo(_expected); + using var request = new ArrayPoolList(2) { TestItem.KeccakA, TestItem.KeccakB }; + using var expected = new ArrayPoolList(0) { }; + _requestor.RequestTransactions(Send, request); + _response.Should().BeEquivalentTo(expected); } private void Send(GetPooledTransactionsMessage msg) { - using (msg) _response = msg.Hashes.ToList(); + _response?.Dispose(); + using (msg) + { + _response = msg.Hashes.ToPooledList(); + } } } } diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs index d628e6f2fb8..1e6ff9b22b9 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V68/Eth68ProtocolHandlerTests.cs @@ -125,7 +125,7 @@ public void Can_handle_NewPooledTransactions_message([Values(0, 1, 2, 100)] int HandleZeroMessage(msg, Eth68MessageCode.NewPooledTransactionHashes); _pooledTxsRequestor.Received(canGossipTransactions ? 1 : 0).RequestTransactionsEth68(Arg.Any>(), - Arg.Any>(), Arg.Any>(), Arg.Any>()); + Arg.Any>(), Arg.Any>(), Arg.Any>()); } [TestCase(true)] @@ -163,7 +163,7 @@ public void Should_process_huge_transaction() HandleZeroMessage(msg, Eth68MessageCode.NewPooledTransactionHashes); _pooledTxsRequestor.Received(1).RequestTransactionsEth68(Arg.Any>(), - Arg.Any>(), Arg.Any>(), Arg.Any>()); + Arg.Any>(), Arg.Any>(), Arg.Any>()); } [TestCase(1)] diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/NodeData/GetNodeDataMessageTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/NodeData/GetNodeDataMessageTests.cs index 3338e376b64..a0d1d6b6680 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/NodeData/GetNodeDataMessageTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/NodeData/GetNodeDataMessageTests.cs @@ -21,7 +21,7 @@ public class GetNodeDataMessageTests public void Sets_values_from_constructor_argument() { Hash256[] keys = { TestItem.KeccakA, TestItem.KeccakB }; - GetNodeDataMessage message = new(keys.ToPooledList()); + using GetNodeDataMessage message = new(keys.ToPooledList()); keys.Should().BeEquivalentTo(message.Hashes); } @@ -34,7 +34,7 @@ public void Throws_on_null_argument() [Test] public void To_string() { - GetNodeDataMessage message = new(ArrayPoolList.Empty()); + using GetNodeDataMessage message = new(ArrayPoolList.Empty()); _ = message.ToString(); } @@ -42,7 +42,7 @@ public void To_string() public void Packet_type_and_protocol_are_correct() { Hash256[] keys = { TestItem.KeccakA, TestItem.KeccakB }; - GetNodeDataMessage message = new(keys.ToPooledList()); + using GetNodeDataMessage message = new(keys.ToPooledList()); message.PacketType.Should().Be(NodeDataMessageCode.GetNodeData); message.Protocol.Should().Be(Protocol.NodeData); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializerTests.cs index 2ff36f94ab6..dc18743e1e7 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializerTests.cs @@ -22,7 +22,7 @@ public void Roundtrip_Many() GetStorageRangeMessage msg = new() { RequestId = MessageConstants.Random.NextLong(), - StoragetRange = new() + StorageRange = new() { RootHash = TestItem.KeccakA, Accounts = TestItem.Keccaks.Select(static k => new PathWithAccount(k, null)).ToPooledList(TestItem.Keccaks.Length), @@ -43,7 +43,7 @@ public void Roundtrip_Empty() GetStorageRangeMessage msg = new() { RequestId = MessageConstants.Random.NextLong(), - StoragetRange = new() + StorageRange = new() { RootHash = Keccak.OfAnEmptyString, Accounts = ArrayPoolList.Empty(), diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetTrieNodesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetTrieNodesMessageSerializerTests.cs index 246ec02169f..dfaa9be7109 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetTrieNodesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/GetTrieNodesMessageSerializerTests.cs @@ -98,7 +98,7 @@ public void NullPathGroup() GetTrieNodesMessageSerializer serializer = new(); - GetTrieNodesMessage? msg = serializer.Deserialize(data); + using GetTrieNodesMessage? msg = serializer.Deserialize(data); byte[] recode = serializer.Serialize(msg); recode.Should().BeEquivalentTo(data); diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/TrieNodesMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/TrieNodesMessageSerializerTests.cs index 8f39b2a721b..7f16e8267e3 100644 --- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/TrieNodesMessageSerializerTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Snap/Messages/TrieNodesMessageSerializerTests.cs @@ -15,7 +15,7 @@ public class TrieNodesMessageSerializerTests [Test] public void Roundtrip() { - ArrayPoolList data = new(2) { new byte[] { 0xde, 0xad, 0xc0, 0xde }, new byte[] { 0xfe, 0xed } }; + using ArrayPoolList data = new(2) { new byte[] { 0xde, 0xad, 0xc0, 0xde }, new byte[] { 0xfe, 0xed } }; TrieNodesMessage message = new(data); @@ -27,7 +27,7 @@ public void Roundtrip() [Test] public void RoundtripWithCorrectLength() { - ArrayPoolList data = new(2) { new byte[] { 0xde, 0xad, 0xc0, 0xde }, new byte[] { 0xfe, 0xed } }; + using ArrayPoolList data = new(2) { new byte[] { 0xde, 0xad, 0xc0, 0xde }, new byte[] { 0xfe, 0xed } }; TrieNodesMessage message = new(data); message.RequestId = 1; diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/HashesMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/HashesMessageSerializer.cs index b5b34e51ee0..3e19519d884 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/HashesMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/HashesMessageSerializer.cs @@ -40,9 +40,9 @@ public void Serialize(IByteBuffer byteBuffer, T message) RlpStream rlpStream = new NettyRlpStream(byteBuffer); rlpStream.StartSequence(contentLength); - for (int i = 0; i < message.Hashes.Count; i++) + foreach (Hash256 hash in message.Hashes.AsSpan()) { - rlpStream.Encode(message.Hashes[i]); + rlpStream.Encode(hash); } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/IPooledTxsRequestor.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/IPooledTxsRequestor.cs index b3018e51e55..26f443961a5 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/IPooledTxsRequestor.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/IPooledTxsRequestor.cs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Collections.Generic; +using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Network.P2P.Subprotocols.Eth.V65.Messages; @@ -10,8 +10,8 @@ namespace Nethermind.Network.P2P.Subprotocols.Eth { public interface IPooledTxsRequestor { - void RequestTransactions(Action send, IReadOnlyList hashes); - void RequestTransactionsEth66(Action send, IReadOnlyList hashes); - void RequestTransactionsEth68(Action send, IReadOnlyList hashes, IReadOnlyList sizes, IReadOnlyList types); + void RequestTransactions(Action send, IOwnedReadOnlyList hashes); + void RequestTransactionsEth66(Action send, IOwnedReadOnlyList hashes); + void RequestTransactionsEth68(Action send, IOwnedReadOnlyList hashes, IOwnedReadOnlyList sizes, IOwnedReadOnlyList types); } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/PooledTxsRequestor.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/PooledTxsRequestor.cs index 796b5c89d79..f0d77bf2694 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/PooledTxsRequestor.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/PooledTxsRequestor.cs @@ -27,15 +27,15 @@ public PooledTxsRequestor(ITxPool txPool, ITxPoolConfig txPoolConfig) _blobSupportEnabled = txPoolConfig.BlobsSupport.IsEnabled(); } - public void RequestTransactions(Action send, IReadOnlyList hashes) + public void RequestTransactions(Action send, IOwnedReadOnlyList hashes) { - ArrayPoolList discoveredTxHashes = AddMarkUnknownHashes(hashes); + ArrayPoolList discoveredTxHashes = AddMarkUnknownHashes(hashes.AsSpan()); RequestPooledTransactions(send, discoveredTxHashes); } - public void RequestTransactionsEth66(Action send, IReadOnlyList hashes) + public void RequestTransactionsEth66(Action send, IOwnedReadOnlyList hashes) { - ArrayPoolList discoveredTxHashes = AddMarkUnknownHashes(hashes); + ArrayPoolList discoveredTxHashes = AddMarkUnknownHashes(hashes.AsSpan()); if (discoveredTxHashes.Count <= MaxNumberOfTxsInOneMsg) { @@ -56,41 +56,44 @@ public void RequestTransactionsEth66(Action send, IReadOnlyList hashes, IReadOnlyList sizes, IReadOnlyList types) + public void RequestTransactionsEth68(Action send, IOwnedReadOnlyList hashes, IOwnedReadOnlyList sizes, IOwnedReadOnlyList types) { - using ArrayPoolList<(Hash256 Hash, byte Type, int Size)> discoveredTxHashesAndSizes = AddMarkUnknownHashesEth68(hashes, sizes, types); + using ArrayPoolList<(Hash256 Hash, byte Type, int Size)> discoveredTxHashesAndSizes = AddMarkUnknownHashesEth68(hashes.AsSpan(), sizes.AsSpan(), types.AsSpan()); if (discoveredTxHashesAndSizes.Count == 0) return; int packetSizeLeft = TransactionsMessage.MaxPacketSize; ArrayPoolList hashesToRequest = new(discoveredTxHashesAndSizes.Count); - for (int i = 0; i < discoveredTxHashesAndSizes.Count; i++) + var discoveredCount = discoveredTxHashesAndSizes.Count; + var toRequestCount = 0; + foreach ((Hash256 hash, byte type, int size) in discoveredTxHashesAndSizes.AsSpan()) { - int txSize = discoveredTxHashesAndSizes[i].Size; - TxType txType = (TxType)discoveredTxHashesAndSizes[i].Type; + int txSize = size; + TxType txType = (TxType)type; - if (txSize > packetSizeLeft && hashesToRequest.Count > 0) + if (txSize > packetSizeLeft && toRequestCount > 0) { RequestPooledTransactionsEth66(send, hashesToRequest); - hashesToRequest = new ArrayPoolList(discoveredTxHashesAndSizes.Count); + hashesToRequest = new ArrayPoolList(discoveredCount); packetSizeLeft = TransactionsMessage.MaxPacketSize; + toRequestCount = 0; } if (_blobSupportEnabled || txType != TxType.Blob) { - hashesToRequest.Add(discoveredTxHashesAndSizes[i].Hash); + hashesToRequest.Add(hash); packetSizeLeft -= txSize; + toRequestCount++; } } RequestPooledTransactionsEth66(send, hashesToRequest); } - private ArrayPoolList AddMarkUnknownHashes(IReadOnlyList hashes) + private ArrayPoolList AddMarkUnknownHashes(ReadOnlySpan hashes) { - int count = hashes.Count; - ArrayPoolList discoveredTxHashes = new ArrayPoolList(count); - for (int i = 0; i < count; i++) + ArrayPoolList discoveredTxHashes = new ArrayPoolList(hashes.Length); + for (int i = 0; i < hashes.Length; i++) { Hash256 hash = hashes[i]; if (!_txPool.IsKnown(hash) && _pendingHashes.Set(hash)) @@ -102,11 +105,10 @@ private ArrayPoolList AddMarkUnknownHashes(IReadOnlyList hashe return discoveredTxHashes; } - private ArrayPoolList<(Hash256, byte, int)> AddMarkUnknownHashesEth68(IReadOnlyList hashes, IReadOnlyList sizes, IReadOnlyList types) + private ArrayPoolList<(Hash256, byte, int)> AddMarkUnknownHashesEth68(ReadOnlySpan hashes, ReadOnlySpan sizes, ReadOnlySpan types) { - int count = hashes.Count; - ArrayPoolList<(Hash256, byte, int)> discoveredTxHashesAndSizes = new(count); - for (int i = 0; i < count; i++) + ArrayPoolList<(Hash256, byte, int)> discoveredTxHashesAndSizes = new(hashes.Length); + for (int i = 0; i < hashes.Length; i++) { Hash256 hash = hashes[i]; if (!_txPool.IsKnown(hash) && !_txPool.ContainsTx(hash, (TxType)types[i]) && _pendingHashes.Set(hash)) @@ -120,14 +122,7 @@ private ArrayPoolList AddMarkUnknownHashes(IReadOnlyList hashe private static void RequestPooledTransactions(Action send, IOwnedReadOnlyList hashesToRequest) { - if (hashesToRequest.Count > 0) - { - send(new(hashesToRequest)); - } - else - { - hashesToRequest.Dispose(); - } + send(new(hashesToRequest)); } private static void RequestPooledTransactionsEth66(Action send, IOwnedReadOnlyList hashesToRequest) diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs index db427262f5f..d14cc6ba3fc 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandler.cs @@ -261,12 +261,12 @@ protected void Handle(TransactionsMessage msg) private ValueTask HandleSlow((IOwnedReadOnlyList txs, int startIndex) request, CancellationToken cancellationToken) { IOwnedReadOnlyList transactions = request.txs; + ReadOnlySpan transactionsSpan = transactions.AsSpan(); try { int startIdx = request.startIndex; bool isTrace = Logger.IsTrace; - int count = transactions.Count; - for (int i = startIdx; i < count; i++) + for (int i = startIdx; i < transactionsSpan.Length; i++) { if (cancellationToken.IsCancellationRequested) { @@ -275,7 +275,7 @@ private ValueTask HandleSlow((IOwnedReadOnlyList txs, int startInde return ValueTask.CompletedTask; } - PrepareAndSubmitTransaction(transactions[i], isTrace); + PrepareAndSubmitTransaction(transactionsSpan[i], isTrace); } transactions.Dispose(); diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/TransactionsMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/TransactionsMessageSerializer.cs index 94366d508f7..33c633924d8 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/TransactionsMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/TransactionsMessageSerializer.cs @@ -19,9 +19,9 @@ public void Serialize(IByteBuffer byteBuffer, TransactionsMessage message) NettyRlpStream nettyRlpStream = new(byteBuffer); nettyRlpStream.StartSequence(contentLength); - for (int i = 0; i < message.Transactions.Count; i++) + foreach (Transaction tx in message.Transactions.AsSpan()) { - nettyRlpStream.Encode(message.Transactions[i], RlpBehaviors.InMempoolForm); + nettyRlpStream.Encode(tx, RlpBehaviors.InMempoolForm); } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs index 919b817e5c2..64bba16adee 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V65/Eth65ProtocolHandler.cs @@ -130,11 +130,11 @@ internal Task FulfillPooledTransactionsRequest(GetPoo ArrayPoolList txsToSend = new(msg.Hashes.Count); int packetSizeLeft = TransactionsMessage.MaxPacketSize; - for (int i = 0; i < msg.Hashes.Count; i++) + foreach (Hash256 hash in msg.Hashes.AsSpan()) { if (cancellationToken.IsCancellationRequested) break; - if (_txPool.TryGetPendingTransaction(msg.Hashes[i], out Transaction tx)) + if (_txPool.TryGetPendingTransaction(hash, out Transaction tx)) { int txSize = tx.GetLength(); diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Messages/NewPooledTransactionHashesMessageSerializer68.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Messages/NewPooledTransactionHashesMessageSerializer68.cs index e74239a702f..64e80a7bd69 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Messages/NewPooledTransactionHashesMessageSerializer68.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V68/Messages/NewPooledTransactionHashesMessageSerializer68.cs @@ -24,15 +24,15 @@ public NewPooledTransactionHashesMessage68 Deserialize(IByteBuffer byteBuffer) public void Serialize(IByteBuffer byteBuffer, NewPooledTransactionHashesMessage68 message) { int sizesLength = 0; - for (int i = 0; i < message.Sizes.Count; i++) + foreach (int size in message.Sizes.AsSpan()) { - sizesLength += Rlp.LengthOf(message.Sizes[i]); + sizesLength += Rlp.LengthOf(size); } int hashesLength = 0; - for (int i = 0; i < message.Hashes.Count; i++) + foreach (Hash256 hash in message.Hashes.AsSpan()) { - hashesLength += Rlp.LengthOf(message.Hashes[i]); + hashesLength += Rlp.LengthOf(hash); } int totalSize = Rlp.LengthOf(message.Types) + Rlp.LengthOfSequence(sizesLength) + Rlp.LengthOfSequence(hashesLength); @@ -42,18 +42,18 @@ public void Serialize(IByteBuffer byteBuffer, NewPooledTransactionHashesMessage6 RlpStream rlpStream = new NettyRlpStream(byteBuffer); rlpStream.StartSequence(totalSize); - rlpStream.Encode(message.Types); + rlpStream.Encode(message.Types.AsSpan()); rlpStream.StartSequence(sizesLength); - for (int i = 0; i < message.Sizes.Count; ++i) + foreach (int size in message.Sizes.AsSpan()) { - rlpStream.Encode(message.Sizes[i]); + rlpStream.Encode(size); } rlpStream.StartSequence(hashesLength); - for (int i = 0; i < message.Hashes.Count; ++i) + foreach (Hash256 hash in message.Hashes.AsSpan()) { - rlpStream.Encode(message.Hashes[i]); + rlpStream.Encode(hash); } } } diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangeMessage.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangeMessage.cs index a03b4f4015e..093f18cae0a 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangeMessage.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangeMessage.cs @@ -9,7 +9,7 @@ public class GetStorageRangeMessage : SnapMessageBase { public override int PacketType => SnapMessageCode.GetStorageRanges; - public StorageRange StoragetRange { get; set; } + public StorageRange StorageRange { get; set; } /// /// Soft limit at which to stop returning data diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs index 85742375261..238adab58c3 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/GetStorageRangesMessageSerializer.cs @@ -16,10 +16,10 @@ public override void Serialize(IByteBuffer byteBuffer, GetStorageRangeMessage me NettyRlpStream rlpStream = GetRlpStreamAndStartSequence(byteBuffer, message); rlpStream.Encode(message.RequestId); - rlpStream.Encode(message.StoragetRange.RootHash); - rlpStream.Encode(message.StoragetRange.Accounts.Select(static a => a.Path).ToArray()); // TODO: optimize this - rlpStream.Encode(message.StoragetRange.StartingHash); - rlpStream.Encode(message.StoragetRange.LimitHash); + rlpStream.Encode(message.StorageRange.RootHash); + rlpStream.Encode(message.StorageRange.Accounts.Select(static a => a.Path).ToArray()); // TODO: optimize this + rlpStream.Encode(message.StorageRange.StartingHash); + rlpStream.Encode(message.StorageRange.LimitHash); rlpStream.Encode(message.ResponseBytes); } @@ -30,11 +30,11 @@ protected override GetStorageRangeMessage Deserialize(RlpStream rlpStream) message.RequestId = rlpStream.DecodeLong(); - message.StoragetRange = new(); - message.StoragetRange.RootHash = rlpStream.DecodeKeccak(); - message.StoragetRange.Accounts = rlpStream.DecodeArrayPoolList(DecodePathWithRlpData); - message.StoragetRange.StartingHash = rlpStream.DecodeKeccak(); - message.StoragetRange.LimitHash = rlpStream.DecodeKeccak(); + message.StorageRange = new(); + message.StorageRange.RootHash = rlpStream.DecodeKeccak(); + message.StorageRange.Accounts = rlpStream.DecodeArrayPoolList(DecodePathWithRlpData); + message.StorageRange.StartingHash = rlpStream.DecodeKeccak(); + message.StorageRange.LimitHash = rlpStream.DecodeKeccak(); message.ResponseBytes = rlpStream.DecodeLong(); return message; @@ -48,10 +48,10 @@ private PathWithAccount DecodePathWithRlpData(RlpStream stream) public override int GetLength(GetStorageRangeMessage message, out int contentLength) { contentLength = Rlp.LengthOf(message.RequestId); - contentLength += Rlp.LengthOf(message.StoragetRange.RootHash); - contentLength += Rlp.LengthOf(message.StoragetRange.Accounts.Select(static a => a.Path).ToArray(), true); // TODO: optimize this - contentLength += Rlp.LengthOf(message.StoragetRange.StartingHash); - contentLength += Rlp.LengthOf(message.StoragetRange.LimitHash); + contentLength += Rlp.LengthOf(message.StorageRange.RootHash); + contentLength += Rlp.LengthOf(message.StorageRange.Accounts.Select(static a => a.Path).ToArray(), true); // TODO: optimize this + contentLength += Rlp.LengthOf(message.StorageRange.StartingHash); + contentLength += Rlp.LengthOf(message.StorageRange.LimitHash); contentLength += Rlp.LengthOf(message.ResponseBytes); return Rlp.LengthOfSequence(contentLength); diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs index 112bcd1ab82..bf5c53388a7 100644 --- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs +++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/SnapProtocolHandler.cs @@ -255,7 +255,7 @@ private StorageRangeMessage FulfillStorageRangeMessage(GetStorageRangeMessage ge Proofs = ArrayPoolList.Empty(), Slots = ArrayPoolList>.Empty(), }; - StorageRange? storageRange = getStorageRangeMessage.StoragetRange; + StorageRange? storageRange = getStorageRangeMessage.StorageRange; (IOwnedReadOnlyList>? ranges, IOwnedReadOnlyList proofs) = SyncServer.GetStorageRanges(storageRange.RootHash, storageRange.Accounts, storageRange.StartingHash, storageRange.LimitHash, getStorageRangeMessage.ResponseBytes, cancellationToken); StorageRangeMessage? response = new() { Proofs = proofs, Slots = ranges }; @@ -286,7 +286,7 @@ public async Task GetStorageRange(StorageRange range, Cancellati StorageRangeMessage response = await _requestSizer.MeasureLatency(bytesLimit => SendRequest(new GetStorageRangeMessage() { - StoragetRange = range, + StorageRange = range, ResponseBytes = bytesLimit }, _getStorageRangeRequests, token)); diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/NettyRlpStream.cs b/src/Nethermind/Nethermind.Serialization.Rlp/NettyRlpStream.cs index 652a3dded3b..e7aed1c2846 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/NettyRlpStream.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/NettyRlpStream.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using DotNetty.Buffers; using DotNetty.Common.Utilities; +using Nethermind.Core.Collections; namespace Nethermind.Serialization.Rlp { @@ -32,20 +33,6 @@ public override void Write(ReadOnlySpan bytesToWrite) _buffer.SetWriterIndex(newWriterIndex); } - public override void Write(IReadOnlyList bytesToWrite) - { - _buffer.EnsureWritable(bytesToWrite.Count); - Span target = - _buffer.Array.AsSpan(_buffer.ArrayOffset + _buffer.WriterIndex, bytesToWrite.Count); - for (int i = 0; i < bytesToWrite.Count; ++i) - { - target[i] = bytesToWrite[i]; - } - - int newWriterIndex = _buffer.WriterIndex + bytesToWrite.Count; - _buffer.SetWriterIndex(newWriterIndex); - } - public override void WriteByte(byte byteToWrite) { _buffer.EnsureWritable(1); diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs b/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs index c7300497dac..052abf998d2 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs @@ -183,15 +183,6 @@ public virtual void Write(ReadOnlySpan bytesToWrite) _position += bytesToWrite.Length; } - public virtual void Write(IReadOnlyList bytesToWrite) - { - for (int i = 0; i < bytesToWrite.Count; ++i) - { - Data[_position + i] = bytesToWrite[i]; - } - Position += bytesToWrite.Count; - } - protected virtual string Description => Data.AsSpan(0, Math.Min(Rlp.DebugMessageContentLength, Length)).ToHexString() ?? "0x"; @@ -594,32 +585,6 @@ public void Encode(ReadOnlySpan input) } } - public void Encode(IReadOnlyList input) - { - if (input.Count == 0) - { - WriteByte(EmptyArrayByte); - } - else if (input.Count == 1 && input[0] < 128) - { - WriteByte(input[0]); - } - else if (input.Count < 56) - { - byte smallPrefix = (byte)(input.Count + 128); - WriteByte(smallPrefix); - Write(input); - } - else - { - int lengthOfLength = Rlp.LengthOfLength(input.Count); - byte prefix = (byte)(183 + lengthOfLength); - WriteByte(prefix); - WriteEncodedLength(input.Count); - Write(input); - } - } - public void Encode(byte[][] arrays) { int itemsLength = 0;