From 2c6d9533591eca2081d2c7fcd93195e316aa9be2 Mon Sep 17 00:00:00 2001 From: jrandom Date: Wed, 1 Mar 2006 23:01:20 +0000 Subject: [PATCH] 2006-03-01 jrandom * More aggressive tunnel throttling as we approach our bandwidth limit, and throttle based off periods wider than 1 second. * Included Doubtful Salmon's syndie stylings (thanks!) --- apps/syndie/jsp/syndie.css | 356 ++++++++++++++++++ history.txt | 7 +- router/java/src/net/i2p/router/Router.java | 25 +- .../net/i2p/router/RouterThrottleImpl.java | 92 ++--- .../src/net/i2p/router/RouterVersion.java | 4 +- .../transport/FIFOBandwidthLimiter.java | 9 - 6 files changed, 414 insertions(+), 79 deletions(-) diff --git a/apps/syndie/jsp/syndie.css b/apps/syndie/jsp/syndie.css index 4812574b2..0f13e8b40 100644 --- a/apps/syndie/jsp/syndie.css +++ b/apps/syndie/jsp/syndie.css @@ -85,4 +85,360 @@ td.s_detail_summDetail { td.s_summary_summ { font-size: 0.8em; background-color: #DDDDFF; +} + + +body { + margin : 0px; + padding : 0px; + width: 99%; + font-family : Arial, sans-serif, Helvetica; + background-color : #FFF; + color : black; + font-size : 100%; + + /* we've avoided Tantek Hacks so far, + ** but we can't avoid using the non-w3c method of + ** box rendering. (and therefore one of mozilla's + ** proprietry -moz properties (which hopefully they'll + ** drop soon). + */ + -moz-box-sizing : border-box; + box-sizing : border-box; +} +a:link{color:#007} +a:visited{color:#606} +a:hover{color:#720} +a:active{color:#900} + +select { + min-width: 1.5em; +} +.overallTable { + border-spacing: 0px; + border-collapse: collapse; + float: left; +} +.topNav { + background-color: #BBB; +} +.topNav_user { + text-align: left; + float: left; + display: inline; +} +.topNav_admin { + text-align: right; + float: right; + margin: 0 5px 0 0; + display: inline; +} +.controlBar { + margin: 0em; + padding: 0em; +// border: medium solid #DDF; + background-color: #EEF; + color: inherit; + font-size: small; + clear: left; /* fixes a bug in Opera */ +} +.controlBarRight { + text-align: right; +} +.threadEven { + background-color: #FFF; + white-space: nowrap; +} +.threadOdd { + background-color: #FFC; + white-space: nowrap; +} +.threadLeft { + text-align: left; + align: left; +} +.threadNav { + background-color: #EEF; + border: medium solid #CCF; +} +.threadNavRight { + text-align: right; + float: right; + background-color: #EEF; +} +.rightOffset { + float: right; + margin: 0 5px 0 0; + display: inline; +} +.threadInfoLeft { + float: left; + margin: 5px 0px 0 0; + display: inline; +} +.threadInfoRight { + float: right; + margin: 0 5px 0 0; + display: inline; +} +.postMeta { + border-top: 1px solid black; + background-color: #FFB; +} +.postMetaSubject { + text-align: left; + font-size: large; +} +.postMetaLink { + text-align: right; +} +.postDetails { + background-color: #FFC; +} +.postReply { + background-color: #CCF; +} +.postReplyText { + background-color: #CCF; +} +.postReplyOptions { + background-color: #CCF; +} +.syndieBlogTopNav { + padding: 0.5em; + width: 98%; + border: medium solid #CCF; + background-color: #EEF; + font-size: small; +} +.syndieBlogTopNavUser { + text-align: left; +} +.syndieBlogTopNavAdmin { + text-align: right; +} +.syndieBlogHeader { + width: 100%; + font-size: 1.4em; + background-color: #000; + text-align: Left; + float: Left; +} +.syndieBlogHeader a { + color: #FFF; + padding: 4px; +} +.syndieBlogHeader a:hover { + color:#88F; + padding: 4px; +} +.syndieBlogLogo { + float: left; + display: inline; +} +.syndieBlogLinks { + width: 20%; + float: left; +} +.syndieBlogLinkGroup { + font-size: 0.8em; + background-color: #DDD; + border: 1px solid black; + margin: 5px; + padding: 2px; +} +.syndieBlogLinkGroup ul { + list-style: none; +} +.syndieBlogLinkGroup li { +} +.syndieBlogLinkGroupName { + font-weight: bold; + width: 100%; + border-bottom: 1px dashed black; + display: block; +} +.syndieBlogPostInfoGroup { + font-size: 0.8em; + background-color: #FFEA9F; + border: 1px solid black; + margin: 5px; + padding: 2px; +} +.syndieBlogPostInfoGroup ol { + list-style: none; +} +.syndieBlogPostInfoGroup li { +} +.syndieBlogPostInfoGroup li a { + display: block; +} +.syndieBlogPostInfoGroupName { + font-weight: bold; + width: 100%; + border-bottom: 1px dashed black; + display: block; +} +.syndieBlogMeta { + text-align: left; + font-size: 0.8em; + background-color: #DDD; + border: 1px solid black; + margin: 5px; + padding: 2px; +} +.syndieBlogBody { + width: 80%; + float: left; +} +.syndieBlogPost { + border: 1px solid black; + margin-top: 5px; + margin-right: 5px; +} +.syndieBlogPostHeader { + background-color: #FFB; + padding: 2px; +} +.syndieBlogPostSubject { + font-weight: bold; +} +.syndieBlogPostFrom { + text-align: right; +} +.syndieBlogPostSummary { + background-color: #FFF; + padding: 2px; +} +.syndieBlogPostDetails { + background-color: #FFC; + padding: 2px; +} +.syndieBlogNav { + text-align: center; +} +.syndieBlogComments { + border: none; + margin-top: 5px; + margin-left: 0px; + float: left; +} +.syndieBlogComments ul { + list-style: none; + margin-left: 10px; +} +.syndieBlogCommentInfoGroup { + font-size: 0.8em; + margin-right: 5px; +} +.syndieBlogCommentInfoGroup ol { + list-style: none; +} +.syndieBlogCommentInfoGroup li { +} +.syndieBlogCommentInfoGroup li a { + display: block; +} +.syndieBlogCommentInfoGroupName { + font-size: 0.8em; + font-weight: bold; +} + +.syndieBlogFavorites { + float: left; + margin: 5px 0px 0 0; + display: inline; +} +.syndieBlogList { + float: right; + margin: 5px 0px 0 0; + display: inline; +} +.b_topnavUser { + text-align: right; + background-color: #CCD; +} +.b_topnavHome { + background-color: #CCD; + color: #000; + width: 50px; + text-align: left; +} +.b_topnav { + background-color: #CCD; +} +.b_content { +} +.s_summary_overall { +} +.s_detail_overall { +} +.s_detail_subject { + font-size: 0.8em; + text-align: left; + background-color: #CCF; +} +.s_detail_quote { + margin-left: 1em; + border: 1px solid #DBDBDB; + background-color: #E0E0E0; +} +.s_detail_italic { + font-style: italic; +} +.s_detail_bold { + font-style: normal; + font-weight: bold; +} +.s_detail_underline { + font-style: normal; + text-decoration: underline; +} +.s_detail_meta { + font-size: 0.8em; + text-align: right; + background-color: #CCF; +} + +.s_summary_subject { + font-size: 0.8em; + text-align: left; + background-color: #CCF; +} +.s_summary_meta { + font-size: 0.8em; + text-align: right; + background-color: #CCF; +} +.s_summary_quote { + margin-left: 1em; + border-width: 1px solid #DBDBDB; + background-color: #E0E0E0; +} +.s_summary_italic { + font-style: italic; +} +.s_summary_bold { + font-style: normal; + font-weight: bold; +} +.s_summary_underline { + font-style: normal; + text-decoration: underline; +} +.s_summary_summDetail { + font-size: 0.8em; +} +.s_detail_summDetail { +} +.s_detail_summDetailBlog { +} +.s_detail_summDetailBlogLink { +} +td.s_detail_summDetail { + background-color: #CCF; +} +td.s_summary_summ { width: 80%; + font-size: 0.8em; + background-color: #CCF; } \ No newline at end of file diff --git a/history.txt b/history.txt index 857d07769..ddacc81ba 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,9 @@ -$Id: history.txt,v 1.422 2006/02/27 14:05:41 jrandom Exp $ +$Id: history.txt,v 1.423 2006/02/27 22:55:18 zzz Exp $ + +2006-03-01 jrandom + * More aggressive tunnel throttling as we approach our bandwidth limit, + and throttle based off periods wider than 1 second. + * Included Doubtful Salmon's syndie stylings (thanks!) 2006-02-27 zzz * Update error page templates to add \r, Connection: close, and diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index 6577dad77..6d1b9f071 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -1016,12 +1016,26 @@ class CoalesceStatsJob extends JobImpl { super(ctx); ctx.statManager().createRateStat("bw.receiveBps", "How fast we receive data (in KBps)", "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); ctx.statManager().createRateStat("bw.sendBps", "How fast we send data (in KBps)", "Bandwidth", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); + ctx.statManager().createRateStat("bw.sendRate", "Low level bandwidth send rate, averaged every minute", "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); + ctx.statManager().createRateStat("bw.recvRate", "Low level bandwidth receive rate, averaged every minute", "Bandwidth", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); ctx.statManager().createRateStat("router.activePeers", "How many peers we are actively talking with", "Throttle", new long[] { 5*60*1000, 60*60*1000 }); ctx.statManager().createRateStat("router.highCapacityPeers", "How many high capacity peers we know", "Throttle", new long[] { 5*60*1000, 60*60*1000 }); ctx.statManager().createRateStat("router.fastPeers", "How many fast peers we know", "Throttle", new long[] { 5*60*1000, 60*60*1000 }); } public String getName() { return "Coalesce stats"; } public void runJob() { + int active = getContext().commSystem().countActivePeers(); + getContext().statManager().addRateData("router.activePeers", active, 60*1000); + + int fast = getContext().profileOrganizer().countFastPeers(); + getContext().statManager().addRateData("router.fastPeers", fast, 60*1000); + + int highCap = getContext().profileOrganizer().countHighCapacityPeers(); + getContext().statManager().addRateData("router.highCapacityPeers", highCap, 60*1000); + + getContext().statManager().addRateData("bw.sendRate", (long)getContext().bandwidthLimiter().getSendBps(), 0); + getContext().statManager().addRateData("bw.recvRate", (long)getContext().bandwidthLimiter().getReceiveBps(), 0); + getContext().statManager().coalesceStats(); RateStat receiveRate = getContext().statManager().getRate("transport.receiveMessageSize"); @@ -1043,16 +1057,7 @@ class CoalesceStatsJob extends JobImpl { getContext().statManager().addRateData("bw.sendBps", (long)KBps, 60*1000); } } - - int active = getContext().commSystem().countActivePeers(); - getContext().statManager().addRateData("router.activePeers", active, 60*1000); - - int fast = getContext().profileOrganizer().countFastPeers(); - getContext().statManager().addRateData("router.fastPeers", fast, 60*1000); - - int highCap = getContext().profileOrganizer().countHighCapacityPeers(); - getContext().statManager().addRateData("router.highCapacityPeers", highCap, 60*1000); - + requeue(60*1000); } } diff --git a/router/java/src/net/i2p/router/RouterThrottleImpl.java b/router/java/src/net/i2p/router/RouterThrottleImpl.java index ca4a804a2..63f8bc3f9 100644 --- a/router/java/src/net/i2p/router/RouterThrottleImpl.java +++ b/router/java/src/net/i2p/router/RouterThrottleImpl.java @@ -88,36 +88,8 @@ class RouterThrottleImpl implements RouterThrottle { } long lag = _context.jobQueue().getMaxLag(); - /* - RateStat rs = _context.statManager().getRate("router.throttleNetworkCause"); - Rate r = null; - if (rs != null) - r = rs.getRate(60*1000); - long throttleEvents = (r != null ? r.getCurrentEventCount() + r.getLastEventCount() : 0); - if (throttleEvents > THROTTLE_EVENT_LIMIT) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Refusing tunnel request with the job lag of " + lag - + " since there have been " + throttleEvents - + " throttle events in the last 15 minutes or so"); - _context.statManager().addRateData("router.throttleTunnelCause", lag, lag); - return TunnelHistory.TUNNEL_REJECT_TRANSIENT_OVERLOAD; - } - */ - RateStat rs = _context.statManager().getRate("transport.sendProcessingTime"); Rate r = null; - /* - if (rs != null) - r = rs.getRate(1*60*1000); - double processTime = (r != null ? r.getAverageValue() : 0); - if (processTime > 2000) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Refusing tunnel request with the job lag of " + lag - + "since the 10 minute message processing time is too slow (" + processTime + ")"); - _context.statManager().addRateData("router.throttleTunnelProcessingTime10m", (long)processTime, (long)processTime); - return TunnelHistory.TUNNEL_REJECT_TRANSIENT_OVERLOAD; - } - */ if (rs != null) r = rs.getRate(60*1000); double processTime = (r != null ? r.getAverageValue() : 0); @@ -129,27 +101,6 @@ class RouterThrottleImpl implements RouterThrottle { return TunnelHistory.TUNNEL_REJECT_TRANSIENT_OVERLOAD; } - /* - rs = _context.statManager().getRate("transport.sendMessageFailureLifetime"); - r = null; - if (rs != null) - r = rs.getRate(60*1000); - double failCount = (r != null ? r.getCurrentEventCount() + r.getLastEventCount() : 0); - if (failCount > 100) { - long periods = r.getLifetimePeriods(); - long maxFailCount = r.getExtremeEventCount(); - if ( (periods > 0) && (maxFailCount > 100) ) { - if (_context.random().nextInt((int)maxFailCount) <= failCount) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Refusing tunnel request with the job lag of " + lag - + "since the 1 minute message failure count is too high (" + failCount + "/" + maxFailCount + ")"); - _context.statManager().addRateData("router.throttleTunnelFailCount1m", (long)failCount, (long)maxFailCount); - return TunnelHistory.TUNNEL_REJECT_TRANSIENT_OVERLOAD; - } - } - } - */ - int numTunnels = _context.tunnelManager().getParticipatingCount(); if (numTunnels > getMinThrottleTunnels()) { @@ -244,9 +195,7 @@ class RouterThrottleImpl implements RouterThrottle { double messagesPerTunnel = (r != null ? r.getAverageValue() : 0d); if (messagesPerTunnel < DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE) messagesPerTunnel = DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE; - int participatingTunnels = (r != null ? (int) (r.getLastEventCount() + r.getCurrentEventCount()) : 0); - if (participatingTunnels <= 0) - participatingTunnels = _context.tunnelManager().getParticipatingCount(); + int participatingTunnels = _context.tunnelManager().getParticipatingCount(); double bytesAllocated = messagesPerTunnel * participatingTunnels * 1024; if (!allowTunnel(bytesAllocated, numTunnels)) { @@ -261,6 +210,32 @@ class RouterThrottleImpl implements RouterThrottle { + " tunnels with lag of " + lag + ")"); return TUNNEL_ACCEPT; } + + private int get1sRate() { + return (int)Math.max(_context.bandwidthLimiter().getSendBps(), _context.bandwidthLimiter().getReceiveBps()); + } + private int get1mRate() { + int send = 0; + RateStat rs = _context.statManager().getRate("bw.sendRate"); + if (rs != null) + send = (int)rs.getRate(1*60*1000).getAverageValue(); + int recv = 0; + rs = _context.statManager().getRate("bw.recvRate"); + if (rs != null) + recv = (int)rs.getRate(1*60*1000).getAverageValue(); + return Math.max(send, recv); + } + private int get5mRate() { + int send = 0; + RateStat rs = _context.statManager().getRate("bw.sendRate"); + if (rs != null) + send = (int)rs.getRate(5*60*1000).getAverageValue(); + int recv = 0; + rs = _context.statManager().getRate("bw.recvRate"); + if (rs != null) + recv = (int)rs.getRate(5*60*1000).getAverageValue(); + return Math.max(send, recv); + } private static final int DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE = 600; // 1KBps @@ -272,14 +247,17 @@ class RouterThrottleImpl implements RouterThrottle { */ private boolean allowTunnel(double bytesAllocated, int numTunnels) { int maxKBps = Math.min(_context.bandwidthLimiter().getOutboundKBytesPerSecond(), _context.bandwidthLimiter().getInboundKBytesPerSecond()); - int used = (int)Math.max(_context.bandwidthLimiter().getSendBps(), _context.bandwidthLimiter().getReceiveBps()); + int used1s = get1sRate(); + int used1m = get1mRate(); + int used5m = get5mRate(); + int used = Math.max(Math.max(used1s, used1m), used5m); int availBps = (int)(((maxKBps*1024) - used) * getSharePercentage()); _context.statManager().addRateData("router.throttleTunnelBytesUsed", used, maxKBps); _context.statManager().addRateData("router.throttleTunnelBytesAllowed", availBps, (long)bytesAllocated); - if (maxKBps <= 8) { - // lets be more conservative for dialup users and assume 1KBps per tunnel + if (availBps <= 8*1024) { + // lets be more conservative for people near their limit and assume 1KBps per tunnel return ( (numTunnels + 1)*1024 < availBps); } @@ -295,8 +273,8 @@ class RouterThrottleImpl implements RouterThrottle { + "Bps/" + allocatedKBps + "KBps allocated through " + numTunnels + " tunnels"); return true; } else { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Rejecting the tunnel w/ " + pctFull + " of our " + availBps + if (_log.shouldLog(Log.WARN)) + _log.warn("Rejecting the tunnel w/ " + pctFull + " of our " + availBps + "Bps allowed (" + toAllocate + "bytes / " + allocatedKBps + "KBps) through " + numTunnels + " tunnels"); return false; diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 32168b08f..06b1adf74 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.363 $ $Date: 2006/02/27 14:05:40 $"; + public final static String ID = "$Revision: 1.364 $ $Date: 2006/02/27 22:55:19 $"; public final static String VERSION = "0.6.1.12"; - 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/transport/FIFOBandwidthLimiter.java b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java index 802093afc..7c5a00f01 100644 --- a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java +++ b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java @@ -47,7 +47,6 @@ public class FIFOBandwidthLimiter { private long _lastTotalSent; private long _lastTotalReceived; private long _lastStatsUpdated; - private long _lastRateUpdated; private float _sendBps; private float _recvBps; @@ -65,8 +64,6 @@ public class FIFOBandwidthLimiter { _context.statManager().createRateStat("bwLimiter.pendingInboundRequests", "How many inbound requests are ahead of the current one (ignoring ones with 0)?", "BandwidthLimiter", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); _context.statManager().createRateStat("bwLimiter.outboundDelayedTime", "How long it takes to honor an outbound request (ignoring ones with that go instantly)?", "BandwidthLimiter", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); _context.statManager().createRateStat("bwLimiter.inboundDelayedTime", "How long it takes to honor an inbound request (ignoring ones with that go instantly)?", "BandwidthLimiter", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); - _context.statManager().createRateStat("bw.sendRate", "Low level bandwidth send rate, averaged every minute", "BandwidthLimiter", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); - _context.statManager().createRateStat("bw.recvRate", "Low level bandwidth receive rate, averaged every minute", "BandwidthLimiter", new long[] { 60*1000l, 5*60*1000l, 10*60*1000l, 60*60*1000l }); _pendingInboundRequests = new ArrayList(16); _pendingOutboundRequests = new ArrayList(16); _lastTotalSent = _totalAllocatedOutboundBytes; @@ -74,7 +71,6 @@ public class FIFOBandwidthLimiter { _sendBps = 0; _recvBps = 0; _lastStatsUpdated = now(); - _lastRateUpdated = _lastStatsUpdated; _refiller = new FIFOBandwidthRefiller(_context, this); I2PThread t = new I2PThread(_refiller); t.setName("BWRefiller" + (++__id)); @@ -295,11 +291,6 @@ public class FIFOBandwidthLimiter { _context.statManager().getStatLog().addData("bw", "bw.recvBps1s", (long)_recvBps, recv); } } - if (60*1000 + _lastRateUpdated <= now) { - _lastRateUpdated = now; - _context.statManager().addRateData("bw.sendRate", (long)_sendBps, 0); - _context.statManager().addRateData("bw.recvRate", (long)_recvBps, 0); - } } /**