From d6891d4b7a3c2cc36eb21b8b9093a593af01e2cc Mon Sep 17 00:00:00 2001 From: zzz <zzz@i2pmail.org> Date: Sun, 15 Jan 2023 08:17:09 -0500 Subject: [PATCH] Console: Show smoothed receive BPS for SSU peers Don't show zero send/receive BPS after 15 sec idle; show smoothed value, so display isn't mostly zeros. BPS sorters will now work correctly and totals are more accurate. Pass now to send/receive BPS methods and BW estimator Comment out UDPTransport.noteSend() Fix alignment issue in NTCP peers table Show 0 instead of 0.00 for zero BPS Change rounding mode of formatters --- .../i2p/router/web/helpers/PeerHelper.java | 19 +++++++++++++++---- .../i2p/router/web/helpers/UDPSorters.java | 9 +++++++-- .../jsp/themes/console/light/console.css | 3 --- .../i2p/router/transport/udp/PeerState.java | 17 ++++++++++++----- .../udp/SimpleBandwidthEstimator.java | 9 ++++++++- .../router/transport/udp/UDPTransport.java | 6 ++++-- 6 files changed, 46 insertions(+), 17 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/helpers/PeerHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/helpers/PeerHelper.java index 0c108e209e..fb8e1dbf75 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/helpers/PeerHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/helpers/PeerHelper.java @@ -3,6 +3,7 @@ package net.i2p.router.web.helpers; import java.io.IOException; import java.io.Serializable; import java.io.Writer; +import java.math.RoundingMode; import java.util.Comparator; import java.text.DecimalFormat; import java.text.NumberFormat; @@ -418,8 +419,8 @@ public class PeerHelper extends HelperBase { .append("\">").append(_t("Dir")).append("</a></th>" + "<th>").append(_t("IPv6")).append("</th>" + "<th>").append(_t("Version")).append("</th>" + - "<th align=\"right\"><a href=\"#def.idle\">").append(_t("Idle")).append("</a></th>" + - "<th align=\"right\"><a href=\"#def.rate\">").append(_t("In/Out")).append("</a></th>" + + "<th><a href=\"#def.idle\">").append(_t("Idle")).append("</a></th>" + + "<th><a href=\"#def.rate\">").append(_t("In/Out")).append("</a></th>" + "<th align=\"right\"><a href=\"#def.up\">").append(_t("Up")).append("</a></th>" + "<th align=\"right\"><a href=\"#def.skew\">").append(_t("Skew")).append("</a></th>" + "<th align=\"right\"><a href=\"#def.recv\">").append(_t("RX")).append("</a></th>" + @@ -518,8 +519,13 @@ public class PeerHelper extends HelperBase { } private static final NumberFormat _rateFmt = new DecimalFormat("#,##0.00"); + static { + _rateFmt.setRoundingMode(RoundingMode.HALF_UP); + } private static String formatRate(float rate) { + if (rate < 0.005f) + return "0"; synchronized (_rateFmt) { return _rateFmt.format(rate); } } @@ -704,8 +710,8 @@ public class PeerHelper extends HelperBase { buf.append("<span class=\"left\">").append(DataHelper.formatDuration2(idleOut)); buf.append("</span></td>"); - int recvBps = (idleIn > 15*1000 ? 0 : peer.getReceiveBps()); - int sendBps = (idleOut > 15*1000 ? 0 : peer.getSendBps()); + int recvBps = peer.getReceiveBps(now); + int sendBps = peer.getSendBps(now); buf.append("<td class=\"cells\" align=\"center\" nowrap><span class=\"right\">"); buf.append(formatKBps(recvBps)); @@ -892,8 +898,13 @@ public class PeerHelper extends HelperBase { } private static final DecimalFormat _fmt = new DecimalFormat("#,##0.00"); + static { + _fmt.setRoundingMode(RoundingMode.HALF_UP); + } private static final String formatKBps(int bps) { + if (bps < 5) + return "0"; synchronized (_fmt) { return _fmt.format((float)bps/1000); } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/helpers/UDPSorters.java b/apps/routerconsole/java/src/net/i2p/router/web/helpers/UDPSorters.java index 4d7e18b4a9..eed809db90 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/helpers/UDPSorters.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/helpers/UDPSorters.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.util.Collections; import java.util.Comparator; +import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; import net.i2p.router.transport.udp.PeerState; @@ -120,9 +121,11 @@ class UDPSorters { } static class RateInComparator extends PeerComparator { + private final long now = I2PAppContext.getGlobalContext().clock().now(); + @Override public int compare(PeerState l, PeerState r) { - int rv = l.getReceiveBps() - r.getReceiveBps(); + int rv = l.getReceiveBps(now) - r.getReceiveBps(now); if (rv == 0) // fallback on alpha return super.compare(l, r); else @@ -131,9 +134,11 @@ class UDPSorters { } static class RateOutComparator extends PeerComparator { + private final long now = I2PAppContext.getGlobalContext().clock().now(); + @Override public int compare(PeerState l, PeerState r) { - int rv = l.getSendBps() - r.getSendBps(); + int rv = l.getSendBps(now) - r.getSendBps(now); if (rv == 0) // fallback on alpha return super.compare(l, r); else diff --git a/apps/routerconsole/jsp/themes/console/light/console.css b/apps/routerconsole/jsp/themes/console/light/console.css index c38398bd3d..4ffd64d0b1 100644 --- a/apps/routerconsole/jsp/themes/console/light/console.css +++ b/apps/routerconsole/jsp/themes/console/light/console.css @@ -5598,12 +5598,10 @@ img+tt { /* /peers */ -#ntcpconnections th:nth-child(6), #ntcpconnections th:nth-child(7), #ntcpconnections th:nth-child(8), #ntcpconnections th:nth-child(9), #ntcpconnections th:nth-child(10), -#ntcpconnections td:nth-child(6), #ntcpconnections td:nth-child(7), #ntcpconnections td:nth-child(8), #ntcpconnections td:nth-child(9), @@ -5624,7 +5622,6 @@ img+tt { #ntcpconnections .tablefooter td:nth-child(3), #ntcpconnections .tablefooter td:nth-child(4), #ntcpconnections .tablefooter td:nth-child(5), -#ntcpconnections .tablefooter td:nth-child(6), #udpconnections .tablefooter td:nth-child(3), #udpconnections .tablefooter td:nth-child(4), #udpconnections .tablefooter td:nth-child(7), diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState.java b/router/java/src/net/i2p/router/transport/udp/PeerState.java index 971dd2c8f1..c51a66050d 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java @@ -25,7 +25,6 @@ import net.i2p.router.transport.udp.InboundMessageFragments.ModifiableLong; import net.i2p.router.util.CachedIteratorCollection; import net.i2p.router.util.CoDelPriorityBlockingQueue; import net.i2p.router.util.PriBlockingQueue; -import net.i2p.util.BandwidthEstimator; import net.i2p.util.ConcurrentHashSet; import net.i2p.util.Log; import net.i2p.util.SimpleTimer2; @@ -116,7 +115,7 @@ public class PeerState { /** how many bytes can we send to the peer in the current second */ private int _sendWindowBytesRemaining; private final Object _sendWindowBytesRemainingLock = new Object(); - private final BandwidthEstimator _bwEstimator; + private final SimpleBandwidthEstimator _bwEstimator; // smoothed value, for display only private int _receiveBps; private int _receiveBytes; @@ -640,13 +639,21 @@ public class PeerState { * The Westwood+ bandwidth estimate * @return the smoothed send transfer rate */ - public int getSendBps() { return (int) (_bwEstimator.getBandwidthEstimate() * 1000); } + public int getSendBps(long now) { return (int) (_bwEstimator.getBandwidthEstimate(now) * 1000); } /** * An approximation, for display only * @return the smoothed receive transfer rate */ - public synchronized int getReceiveBps() { return _receiveBps; } + public synchronized int getReceiveBps(long now) { + long duration = now - _receivePeriodBegin; + if (duration >= 1000) { + _receiveBps = (int)(0.9f*_receiveBps + 0.1f*(_receiveBytes * (1000f/duration))); + _receiveBytes = 0; + _receivePeriodBegin = now; + } + return _receiveBps; + } int incrementConsecutiveFailedSends() { synchronized(_outboundMessages) { @@ -870,7 +877,7 @@ public class PeerState { bwe = -1; // for log below } else { _sendWindowBytes = getVersion() == 2 ? PeerState2.MAX_MTU : (isIPv6() ? MAX_IPV6_MTU : LARGE_MTU); - bwe = _bwEstimator.getBandwidthEstimate(); + bwe = _bwEstimator.getBandwidthEstimate(now); _slowStartThreshold = Math.max( (int)(bwe * _rtt), 2 * _mtu); } diff --git a/router/java/src/net/i2p/router/transport/udp/SimpleBandwidthEstimator.java b/router/java/src/net/i2p/router/transport/udp/SimpleBandwidthEstimator.java index e7443cc6c4..51d825ca17 100644 --- a/router/java/src/net/i2p/router/transport/udp/SimpleBandwidthEstimator.java +++ b/router/java/src/net/i2p/router/transport/udp/SimpleBandwidthEstimator.java @@ -87,7 +87,14 @@ class SimpleBandwidthEstimator implements BandwidthEstimator { * @return the current bandwidth estimate in bytes/ms. */ public float getBandwidthEstimate() { - long now = _context.clock().now(); + return getBandwidthEstimate(_context.clock().now()); + } + + /** + * @return the current bandwidth estimate in bytes/ms. + * @since 0.9.58 + */ + public float getBandwidthEstimate(long now) { // avoid deadlock int rtt = _state.getRTT(); // anti-aliasing filter diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index 8ca88d8510..ddfce65558 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -3487,11 +3487,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority if (_log.shouldLog(Log.DEBUG)) _log.debug("Failed sending " + msg + " to " + msg.getPeer()); } - noteSend(msg, false); + //noteSend(msg, false); if (m != null) super.afterSend(m, false); } +/* private void noteSend(OutboundMessageState msg, boolean successful) { // bail before we do all the work if (!_context.messageHistory().getDoLog()) @@ -3529,6 +3530,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority (p != null ? p.getRemotePeer() : null), successful, buf.toString()); } } +*/ public void failed(OutNetMessage msg, String reason) { if (msg == null) return; @@ -3545,7 +3547,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority if (msg == null) return; if (_log.shouldLog(Log.DEBUG)) _log.debug("Sending message succeeded: " + msg); - noteSend(msg, true); + //noteSend(msg, true); OutNetMessage m = msg.getMessage(); if (m != null) super.afterSend(m, true); -- GitLab