From 8b6751f419870525822dbfbf80144da0bdbcab3b Mon Sep 17 00:00:00 2001 From: zzz Date: Sat, 10 Apr 2010 15:42:08 +0000 Subject: [PATCH] Streaming: Fix the window size increment logic so it does it much more often. The code increased the window size by MSS * MSS / N, like in RFC 2581, but it did it only once every N, so that was like MSS * MSS / N**2. Now do it all the time, except for isolated packets like keepalives that aren't using more than one message of the window. Seems to speed up outbound significantly, without any noticable increase in stream.sendsBeforeAck. --- .../client/streaming/ConnectionOptions.java | 2 ++ .../streaming/ConnectionPacketHandler.java | 34 +++++++++++++++---- history.txt | 13 +++++++ .../src/net/i2p/router/RouterVersion.java | 2 +- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java index a3f691ece..ea4e1f069 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java @@ -386,8 +386,10 @@ public class ConnectionOptions extends I2PSocketOptionsImpl { private static final double RTT_DAMPENING = 0.875; public void updateRTT(int measuredValue) { + // the rttDev calculation matches that recommended in RFC 2988 (beta = 1/4) _rttDev = _rttDev + (int)(0.25d*(Math.abs(measuredValue-_rtt)-_rttDev)); int smoothed = (int)(RTT_DAMPENING*_rtt + (1-RTT_DAMPENING)*measuredValue); + // K = 4 _rto = smoothed + (_rttDev<<2); if (_rto < Connection.MIN_RESEND_DELAY) _rto = (int)Connection.MIN_RESEND_DELAY; diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java index b9ebbb7d2..5292b5f09 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java @@ -328,7 +328,19 @@ public class ConnectionPacketHandler { } long lowest = con.getHighestAckedThrough(); - if (lowest >= con.getCongestionWindowEnd()) { + // RFC 2581 + // Why wait until we get a whole cwin to start updating the window? + // That means we don't start increasing the window until after 1 RTT. + // And whether we increase the window or not (probably not since 1/N), + // we reset the CongestionWindowEnd and have to wait another RTT. + // So we add the acked > 1 and UnackedPacketsSent > 0 cases, + // so we almost always go through the window adjustment code, + // unless we're just sending a single packet now and then. + // This keeps the window size from going sky-high from ping traffic alone. + // Since we don't adjust the window down after idle? (RFC 2581 sec. 4.1) + if (lowest >= con.getCongestionWindowEnd() || + acked > 1 || + con.getUnackedPacketsSent() > 0) { // new packet that ack'ed uncongested data, or an empty ack int oldWindow = con.getOptions().getWindowSize(); int newWindowSize = oldWindow; @@ -352,11 +364,12 @@ public class ConnectionPacketHandler { newWindowSize += acked / factor; if (_log.shouldLog(Log.DEBUG)) _log.debug("slow start acks = " + acked + " for " + con); - } else if (trend < 0) { - // rtt is shrinking, so lets increment the cwin - newWindowSize++; - if (_log.shouldLog(Log.DEBUG)) - _log.debug("trend < 0 for " + con); + // this is too fast since we mostly disabled the CongestionWindowEnd test above + //} else if (trend < 0) { + // // rtt is shrinking, so lets increment the cwin + // newWindowSize++; + // if (_log.shouldLog(Log.DEBUG)) + // _log.debug("trend < 0 for " + con); } else { // congestion avoidance // linear growth - increase window 1/N per RTT @@ -368,6 +381,10 @@ public class ConnectionPacketHandler { if (_log.shouldLog(Log.DEBUG)) _log.debug("cong. avoid acks = " + acked + " for " + con); } + } else { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No change to window: " + con.getOptions().getWindowSize() + + " congested? " + congested + " acked: " + acked + " resends: " + numResends); } if (newWindowSize <= 0) @@ -380,6 +397,11 @@ public class ConnectionPacketHandler { _log.debug("New window size " + newWindowSize + "/" + oldWindow + "/" + con.getOptions().getWindowSize() + " congestionSeenAt: " + con.getLastCongestionSeenAt() + " (#resends: " + numResends + ") for " + con); + } else { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("No change to window: " + con.getOptions().getWindowSize() + + " highestAckedThrough: " + lowest + " congestionWindowEnd: " + con.getCongestionWindowEnd() + + " acked: " + acked + " unacked: " + con.getUnackedPacketsSent()); } con.windowAdjusted(); diff --git a/history.txt b/history.txt index 4a6e2d8ed..0b07ff332 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,16 @@ +2010-04-10 zzz + * i2psnark: + - Disconnect seeds that connect to a seed + - Lower per-torrent conn limits for large pieces + * Startup: + - Don't die horribly if there is a router.info file + but no router.keys file + http://forum.i2p/viewtopic.php?t=4424 + - Log tweaks + * Streaming: + - Fix the window size increment logic so it + does it much more often + 2010-04-08 zzz * Key Manager: Hopefully avoid some races at startup http://forum.i2p/viewtopic.php?t=4424 diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index fecba78d6..a6204817e 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 7; + public final static long BUILD = 8; /** for example "-test" */ public final static String EXTRA = "";