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);