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

Less aggressive peer discovery #5747

Merged
merged 1 commit into from
Jun 1, 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
13 changes: 12 additions & 1 deletion src/Nethermind/Nethermind.Core/Crypto/PublicKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using Nethermind.Core.Extensions;
Expand Down Expand Up @@ -96,7 +97,17 @@ public override bool Equals(object? obj)

public override int GetHashCode()
{
return MemoryMarshal.Read<int>(Bytes);
byte[] bytes = Bytes;
long l0 = Unsafe.ReadUnaligned<long>(ref MemoryMarshal.GetArrayDataReference(bytes));
long l1 = Unsafe.ReadUnaligned<long>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), sizeof(long)));
benaadams marked this conversation as resolved.
Show resolved Hide resolved
long l2 = Unsafe.ReadUnaligned<long>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), sizeof(long) * 2));
long l3 = Unsafe.ReadUnaligned<long>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), sizeof(long) * 3));
long l4 = Unsafe.ReadUnaligned<long>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), sizeof(long) * 4));
long l5 = Unsafe.ReadUnaligned<long>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), sizeof(long) * 5));
long l6 = Unsafe.ReadUnaligned<long>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), sizeof(long) * 6));
long l7 = Unsafe.ReadUnaligned<long>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), sizeof(long) * 7));
l0 ^= l1 ^ l2 ^ l3 ^ l4 ^ l5 ^ l6 ^ l7;
benaadams marked this conversation as resolved.
Show resolved Hide resolved
return (int)(l0 ^ (l0 >> 32));
}

public override string ToString()
Expand Down
40 changes: 22 additions & 18 deletions src/Nethermind/Nethermind.Network.Stats/Model/Node.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using System.Net;
using Nethermind.Config;
using Nethermind.Core.Crypto;
Expand All @@ -12,11 +11,12 @@ namespace Nethermind.Stats.Model
/// <summary>
/// Represents a physical network node address and attributes that we assign to it (static, bootnode, trusted, etc.)
/// </summary>
public class Node : IFormattable
public sealed class Node : IFormattable, IEquatable<Node>
{
private string _clientId;
private string _paddedHost;
private string _paddedPort;
private int _hashCode;

/// <summary>
/// Node public key - same as in enode.
Expand Down Expand Up @@ -71,24 +71,23 @@ public string ClientId
public string EthDetails { get; set; }
public long CurrentReputation { get; set; }

public Node(PublicKey id, IPEndPoint address)
{
Id = id;
IdHash = Keccak.Compute(Id.PrefixedBytes);
SetIPEndPoint(address);
}

public Node(NetworkNode networkNode, bool isStatic = false)
: this(networkNode.NodeId, networkNode.Host, networkNode.Port, isStatic)
{
}

public Node(PublicKey id, string host, int port, bool isStatic = false)
: this(id, GetIPEndPoint(host, port), isStatic)
{
}

public Node(PublicKey id, IPEndPoint address, bool isStatic = false)
{
Id = id;
IdHash = Keccak.Compute(Id.PrefixedBytes);
SetIPEndPoint(host, port);
_hashCode = id.GetHashCode();
IsStatic = isStatic;
SetIPEndPoint(address);
}

private void SetIPEndPoint(IPEndPoint address)
Expand All @@ -102,9 +101,9 @@ private void SetIPEndPoint(IPEndPoint address)
_paddedPort = Port.ToString().PadLeft(5, ' ');
}

private void SetIPEndPoint(string host, int port)
private static IPEndPoint GetIPEndPoint(string host, int port)
{
SetIPEndPoint(new IPEndPoint(IPAddress.Parse(host), port));
return new IPEndPoint(IPAddress.Parse(host), port);
}

public override bool Equals(object obj)
Expand All @@ -122,7 +121,7 @@ public override bool Equals(object obj)
return false;
}

public override int GetHashCode() => HashCode.Combine(Id);
public override int GetHashCode() => _hashCode;

public override string ToString() => ToString(Format.WithPublicKey);

Expand All @@ -142,14 +141,19 @@ public string ToString(string format, IFormatProvider formatProvider)
};
}

public bool Equals(Node other)
{
if (ReferenceEquals(this, other)) return true;
if (other is null) return false;

return Id.Equals(other.Id);
}

public static bool operator ==(Node a, Node b)
{
if (ReferenceEquals(a, null))
{
return ReferenceEquals(b, null);
}
if (ReferenceEquals(a, b)) return true;

if (ReferenceEquals(b, null))
if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
{
return false;
}
Expand Down
51 changes: 21 additions & 30 deletions src/Nethermind/Nethermind.Network.Stats/NodeStatsLight.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;

using FastEnumUtility;
using Nethermind.Stats.Model;

Expand Down Expand Up @@ -70,10 +73,7 @@ public NodeStatsLight(Node node, decimal latestSpeedWeight = 0.25m)

private void Increment(NodeStatsEventType nodeStatsEventType)
{
lock (_statCountersArray)
{
_statCountersArray[(int)nodeStatsEventType]++;
}
Interlocked.Increment(ref _statCountersArray[(int)nodeStatsEventType]);
}

public void AddNodeStatsEvent(NodeStatsEventType nodeStatsEventType)
Expand Down Expand Up @@ -160,10 +160,7 @@ public void AddNodeStatsSyncEvent(NodeStatsEventType nodeStatsEventType)

public bool DidEventHappen(NodeStatsEventType nodeStatsEventType)
{
lock (_statCountersArray)
{
return _statCountersArray[(int)nodeStatsEventType] > 0;
}
return GetStat(nodeStatsEventType) > 0;
}

public void AddTransferSpeedCaptureEvent(TransferSpeedType transferSpeedType, long bytesPerMillisecond)
Expand Down Expand Up @@ -276,11 +273,7 @@ private bool IsDelayedDueToFailedConnection()

private int GetFailedConnectionDelay()
{
int failedConnectionFailed;
lock (_statCountersArray)
{
failedConnectionFailed = _statCountersArray[(int)NodeStatsEventType.ConnectionFailed];
}
int failedConnectionFailed = GetStat(NodeStatsEventType.ConnectionFailed);

if (failedConnectionFailed == 0)
{
Expand All @@ -298,11 +291,7 @@ private int GetFailedConnectionDelay()
private int GetDisconnectDelay()
{
int disconnectDelay;
int disconnectCount;
lock (_statCountersArray)
{
disconnectCount = _statCountersArray[(int)NodeStatsEventType.Disconnect];
}
int disconnectCount = GetStat(NodeStatsEventType.Disconnect);

if (disconnectCount == 0)
{
Expand All @@ -327,24 +316,26 @@ private long CalculateCurrentReputation()

private bool HasDisconnectedOnce => _lastLocalDisconnect.HasValue || _lastRemoteDisconnect.HasValue;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int GetStat(NodeStatsEventType nodeStatsEventType)
{
return Volatile.Read(ref _statCountersArray[(int)nodeStatsEventType]);
}

private long CalculateSessionReputation()
{
long discoveryReputation = 0;
long rlpxReputation = 0;
lock (_statCountersArray)
{

discoveryReputation += Math.Min(_statCountersArray[(int)NodeStatsEventType.DiscoveryPingIn], 10) * (_statCountersArray[(int)NodeStatsEventType.DiscoveryPingIn] == _statCountersArray[(int)NodeStatsEventType.DiscoveryPingOut] ? 2 : 1);
discoveryReputation += Math.Min(_statCountersArray[(int)NodeStatsEventType.DiscoveryNeighboursIn], 10) * 2;

discoveryReputation += Math.Min(GetStat(NodeStatsEventType.DiscoveryPingIn), 10) * (GetStat(NodeStatsEventType.DiscoveryPingIn) == GetStat(NodeStatsEventType.DiscoveryPingOut) ? 2 : 1);
discoveryReputation += Math.Min(GetStat(NodeStatsEventType.DiscoveryNeighboursIn), 10) * 2;

rlpxReputation += Math.Min(_statCountersArray[(int)NodeStatsEventType.P2PPingIn], 10) * (_statCountersArray[(int)NodeStatsEventType.P2PPingIn] == _statCountersArray[(int)NodeStatsEventType.P2PPingOut] ? 2 : 1);
rlpxReputation += _statCountersArray[(int)NodeStatsEventType.HandshakeCompleted] > 0 ? 10 : 0;
rlpxReputation += _statCountersArray[(int)NodeStatsEventType.P2PInitialized] > 0 ? 10 : 0;
rlpxReputation += _statCountersArray[(int)NodeStatsEventType.Eth62Initialized] > 0 ? 20 : 0;
rlpxReputation += _statCountersArray[(int)NodeStatsEventType.SyncStarted] > 0 ? 1000 : 0;
rlpxReputation += (rlpxReputation != 0 && !HasDisconnectedOnce) ? 1 : 0;
}
rlpxReputation += Math.Min(GetStat(NodeStatsEventType.P2PPingIn), 10) * (GetStat(NodeStatsEventType.P2PPingIn) == GetStat(NodeStatsEventType.P2PPingOut) ? 2 : 1);
rlpxReputation += GetStat(NodeStatsEventType.HandshakeCompleted) > 0 ? 10 : 0;
rlpxReputation += GetStat(NodeStatsEventType.P2PInitialized) > 0 ? 10 : 0;
rlpxReputation += GetStat(NodeStatsEventType.Eth62Initialized) > 0 ? 20 : 0;
rlpxReputation += GetStat(NodeStatsEventType.SyncStarted) > 0 ? 1000 : 0;
rlpxReputation += (rlpxReputation != 0 && !HasDisconnectedOnce) ? 1 : 0;

if (HasDisconnectedOnce)
{
Expand Down
30 changes: 7 additions & 23 deletions src/Nethermind/Nethermind.Network.Stats/NodeStatsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Timers;
using Nethermind.Core.Caching;
using Nethermind.Core.Timers;
using Nethermind.Logging;
using Nethermind.Stats.Model;
Expand All @@ -18,29 +15,12 @@ public class NodeStatsManager : INodeStatsManager, IDisposable
{
private class NodeComparer : IEqualityComparer<Node>
{
public bool Equals(Node x, Node y)
{
if (ReferenceEquals(x, null))
{
return ReferenceEquals(y, null);
}

if (ReferenceEquals(y, null))
{
return false;
}

return x.Id == y.Id;
}

public int GetHashCode(Node obj)
{
return obj?.GetHashCode() ?? 0;
}
public bool Equals(Node x, Node y) => ReferenceEquals(x, y) || x.Id == y.Id;
public int GetHashCode(Node obj) => obj.GetHashCode();
}

private readonly ILogger _logger;
private readonly ConcurrentDictionary<Node, INodeStats> _nodeStats = new ConcurrentDictionary<Node, INodeStats>(new NodeComparer());
private readonly ConcurrentDictionary<Node, INodeStats> _nodeStats = new(new NodeComparer());
private readonly ITimer _cleanupTimer;
private readonly int _maxCount;

Expand All @@ -56,6 +36,8 @@ public NodeStatsManager(ITimerFactory timerFactory, ILogManager logManager, int

private void CleanupTimerOnElapsed(object sender, EventArgs e)
{
_cleanupTimer.Stop();

int deleteCount = _nodeStats.Count - _maxCount;

if (deleteCount > 0)
Expand All @@ -74,6 +56,8 @@ private void CleanupTimerOnElapsed(object sender, EventArgs e)

if (_logger.IsDebug) _logger.Debug($"Removed {i} node stats.");
}

_cleanupTimer.Start();
}

private INodeStats AddStats(Node node)
Expand Down
11 changes: 9 additions & 2 deletions src/Nethermind/Nethermind.Network/Peer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only

using Nethermind.Network.P2P;
using Nethermind.Stats;
using Nethermind.Stats.Model;

namespace Nethermind.Network
Expand All @@ -15,11 +16,15 @@ namespace Nethermind.Network
/// The logic for choosing which session to drop has to be consistent between the two peers - we use the PublicKey
/// comparison to choose the connection direction in the same way on both sides.
/// </summary>
public class Peer
public sealed class Peer
{
public Peer(Node node)
public Peer(Node node) : this(node, null)
{ }

public Peer(Node node, INodeStats stats)
{
Node = node;
Stats = stats;
}

public bool IsAwaitingConnection { get; set; }
Expand All @@ -30,6 +35,8 @@ public Peer(Node node)
/// </summary>
public Node Node { get; }

internal INodeStats Stats { get; }

/// <summary>
/// An incoming session to the Node which can be in one of many states.
/// </summary>
Expand Down
Loading