diff --git a/core/java/src/net/i2p/util/FortunaRandomSource.java b/core/java/src/net/i2p/util/FortunaRandomSource.java index a470da3f0..8ce776341 100644 --- a/core/java/src/net/i2p/util/FortunaRandomSource.java +++ b/core/java/src/net/i2p/util/FortunaRandomSource.java @@ -157,11 +157,12 @@ public class FortunaRandomSource extends RandomSource implements EntropyHarveste * through 2^numBits-1 */ protected synchronized int nextBits(int numBits) { - int rv = 0; + long rv = 0; int bytes = (numBits + 7) / 8; for (int i = 0; i < bytes; i++) rv += ((_fortuna.nextByte() & 0xFF) << i*8); - return rv; + rv >>>= (64-numBits); + return (int)rv; } public EntropyHarvester harvester() { return this; } diff --git a/history.txt b/history.txt index ea89d5fb7..19957e77a 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,8 @@ -$Id: history.txt,v 1.455 2006/04/13 07:40:21 jrandom Exp $ +$Id: history.txt,v 1.456 2006/04/14 06:42:44 jrandom Exp $ + +2006-04-14 jrandom + * -28.00230115311259 is not between 0 and 1 in any universe I know. + * Made the bw-related tunnel join throttle much simpler 2006-04-14 jrandom * Make some more stats graphable, and allow some internal tweaking on the diff --git a/router/java/src/net/i2p/router/RouterThrottleImpl.java b/router/java/src/net/i2p/router/RouterThrottleImpl.java index 365c33f9f..0b54415ea 100644 --- a/router/java/src/net/i2p/router/RouterThrottleImpl.java +++ b/router/java/src/net/i2p/router/RouterThrottleImpl.java @@ -190,9 +190,16 @@ class RouterThrottleImpl implements RouterThrottle { // of another tunnel? rs = _context.statManager().getRate("tunnel.participatingMessageCount"); r = null; - if (rs != null) + double messagesPerTunnel = DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE; + if (rs != null) { r = rs.getRate(10*60*1000); - double messagesPerTunnel = (r != null ? r.getAverageValue() : 0d); + if (r != null) { + if (r.getLastEventCount() > 0) + messagesPerTunnel = r.getAverageValue(); + else + messagesPerTunnel = r.getLifetimeAverageValue(); + } + } if (messagesPerTunnel < DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE) messagesPerTunnel = DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE; int participatingTunnels = _context.tunnelManager().getParticipatingCount(); @@ -237,7 +244,7 @@ class RouterThrottleImpl implements RouterThrottle { return Math.max(send, recv); } - private static final int DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE = 600; // 1KBps + private static final int DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE = 60; // .1KBps private static final int MIN_AVAILABLE_BPS = 4*1024; // always leave at least 4KBps free when allowing /** @@ -248,15 +255,37 @@ class RouterThrottleImpl implements RouterThrottle { */ private boolean allowTunnel(double bytesAllocated, int numTunnels) { int maxKBps = Math.min(_context.bandwidthLimiter().getOutboundKBytesPerSecond(), _context.bandwidthLimiter().getInboundKBytesPerSecond()); - int used1s = get1sRate(_context); // dont throttle on the 1s rate, its too volatile + int used1s = 0; //get1sRate(_context); // dont throttle on the 1s rate, its too volatile int used1m = get1mRate(_context); int used5m = 0; //get5mRate(_context); // don't throttle on the 5m rate, as that'd hide available bandwidth int used = Math.max(Math.max(used1s, used1m), used5m); - int availBps = (int)(((maxKBps*1024) - used) * getSharePercentage()); + double share = getSharePercentage(); + int availBps = (int)(((maxKBps*1024)*share) - used); //(int)(((maxKBps*1024) - used) * getSharePercentage()); _context.statManager().addRateData("router.throttleTunnelBytesUsed", used, maxKBps); _context.statManager().addRateData("router.throttleTunnelBytesAllowed", availBps, (long)bytesAllocated); + if (true) { + // ok, ignore any predictions of 'bytesAllocated', since that makes poorly + // grounded conclusions about future use (or even the bursty use). Instead, + // simply say "do we have the bw to handle a new request"? + float maxBps = maxKBps * 1024f; + float pctFull = (maxBps - availBps) / (maxBps); + double probReject = Math.pow(pctFull, 16); // steep curve + double rand = _context.random().nextFloat(); + boolean reject = (availBps < MIN_AVAILABLE_BPS) || (rand <= probReject); + if (_log.shouldLog(Log.WARN)) + _log.warn("reject = " + reject + " avail/maxK/used " + availBps + "/" + maxKBps + "/" + + used + " pReject = " + probReject + " pFull = " + pctFull + " numTunnels = " + numTunnels + + "rand = " + rand + " est = " + bytesAllocated + " share = " + (float)share); + if (reject) { + return false; + } else { + return true; + } + } + + /* if (availBps <= 8*1024) { // lets be more conservative for people near their limit and assume 1KBps per tunnel @@ -280,7 +309,7 @@ class RouterThrottleImpl implements RouterThrottle { return true; } else { double probAllow = availBps / (allocatedBps + availBps); - boolean allow = (availBps > MIN_AVAILABLE_BPS) && (_context.random().nextDouble() <= probAllow); + boolean allow = (availBps > MIN_AVAILABLE_BPS) && (_context.random().nextFloat() <= probAllow); if (allow) { if (_log.shouldLog(Log.INFO)) _log.info("Probabalistically allowing the tunnel w/ " + (pctFull*100d) + "% of our " + availBps diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 9462a4130..708727f3b 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,9 +15,9 @@ import net.i2p.CoreVersion; * */ public class RouterVersion { - public final static String ID = "$Revision: 1.395 $ $Date: 2006/04/13 07:40:22 $"; + public final static String ID = "$Revision: 1.396 $ $Date: 2006/04/14 06:42:02 $"; public final static String VERSION = "0.6.1.15"; - public final static long BUILD = 1; + public final static long BUILD = 2; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java index 186cb3a97..764636676 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java @@ -49,6 +49,7 @@ class BuildHandler { _context.statManager().createRateStat("tunnel.dropLoadDelay", "How long we had to wait before finally giving up on an inbound request?", "Tunnels", new long[] { 60*1000, 10*60*1000 }); _context.statManager().createRateStat("tunnel.dropLoadBacklog", "How many requests were pending when they were so lagged that we had to drop a new inbound request??", "Tunnels", new long[] { 60*1000, 10*60*1000 }); _context.statManager().createRateStat("tunnel.dropLoadProactive", "What the estimated queue time was when we dropped an inbound request (period is num pending)", "Tunnels", new long[] { 60*1000, 10*60*1000 }); + _context.statManager().createRateStat("tunnel.dropLoadProactiveAbort", "How often we would have proactively dropped a request, but allowed it through?", "Tunnels", new long[] { 60*1000, 10*60*1000 }); _context.statManager().createRateStat("tunnel.handleRemaining", "How many pending inbound requests were left on the queue after one pass?", "Tunnels", new long[] { 60*1000, 10*60*1000 }); _context.statManager().createRateStat("tunnel.receiveRejectionProbabalistic", "How often we are rejected probabalistically?", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l }); @@ -371,7 +372,7 @@ class BuildHandler { * If we are dropping lots of requests before even trying to handle them, * I suppose you could call us "overloaded" */ - private final static int MAX_PROACTIVE_DROPS = 120; + private final static int MAX_PROACTIVE_DROPS = 240; private int countProactiveDrops() { int dropped = 0; @@ -413,7 +414,7 @@ class BuildHandler { int proactiveDrops = countProactiveDrops(); long recvDelay = System.currentTimeMillis()-state.recvTime; - if ( (response == 0) && ( (recvDelay > BuildRequestor.REQUEST_TIMEOUT/2) || (proactiveDrops > MAX_PROACTIVE_DROPS) ) ) { + if ( (response == 0) && ( (recvDelay > BuildRequestor.REQUEST_TIMEOUT) || (proactiveDrops > MAX_PROACTIVE_DROPS) ) ) { _context.statManager().addRateData("tunnel.rejectOverloaded", recvDelay, proactiveDrops); if (true || (proactiveDrops < MAX_PROACTIVE_DROPS*2)) response = TunnelHistory.TUNNEL_REJECT_TRANSIENT_OVERLOAD; @@ -603,10 +604,10 @@ class BuildHandler { _context.statManager().addRateData("tunnel.dropLoadBacklog", _inboundBuildMessages.size(), _inboundBuildMessages.size()); } else { int queueTime = estimateQueueTime(_inboundBuildMessages.size()); - float pDrop = queueTime/((float)BuildRequestor.REQUEST_TIMEOUT/2); - pDrop = pDrop * pDrop; + float pDrop = queueTime/((float)BuildRequestor.REQUEST_TIMEOUT); + pDrop = pDrop * pDrop * pDrop; float f = _context.random().nextFloat(); - if (pDrop > f) { + if ( (pDrop > f) && (allowProactiveDrop()) ) { _context.statManager().addRateData("tunnel.dropLoadProactive", queueTime, _inboundBuildMessages.size()); } else { _inboundBuildMessages.add(new BuildMessageState(receivedMessage, from, fromHash)); @@ -620,6 +621,16 @@ class BuildHandler { } } + private boolean allowProactiveDrop() { + String allow = _context.getProperty("router.allowProactiveDrop", "true"); + boolean rv = false; + if ( (allow == null) || (Boolean.valueOf(allow).booleanValue()) ) + rv = true; + if (!rv) + _context.statManager().addRateData("tunnel.dropLoadProactiveAbort", 1, 0); + return rv; + } + private int estimateQueueTime(int numPendingMessages) { int decryptTime = 200; RateStat rs = _context.statManager().getRate("crypto.elGamal.decrypt");