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 0c108e209e70a3a49ca38928b876524c43efc7d4..fb8e1dbf75926e4b0db85eb04f508a3d11737257 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 4d7e18b4a95e86097c1c46e534c701f1217bbab5..eed809db90aa2fa5432d781d62a4b8c45bafd3f9 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 c38398bd3dfe0bb550470f524b584bcb9e5ccf94..4ffd64d0b14b68f8d00295093de8e12150d52d9b 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 971dd2c8f14d81c4f40e81c30270fbf4e5585180..c51a66050dfe60924e21ebbf9a2bff3c413ba9a5 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 e7443cc6c4950d52313c4f357b34359bc056f392..51d825ca1782c4f5c83575575df8847f59999bf0 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 8ca88d851018e0de2f9584a0603ceb821c22844d..ddfce655580045c8740c885f425dc87cd2323973 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);