forked from I2P_Developers/i2p.i2p
CoDel for build handler
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
package net.i2p.router.tunnel.pool;
|
package net.i2p.router.tunnel.pool;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
|
||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
import net.i2p.data.ByteArray;
|
import net.i2p.data.ByteArray;
|
||||||
@@ -28,6 +28,8 @@ import net.i2p.router.tunnel.BuildMessageProcessor;
|
|||||||
import net.i2p.router.tunnel.BuildReplyHandler;
|
import net.i2p.router.tunnel.BuildReplyHandler;
|
||||||
import net.i2p.router.tunnel.HopConfig;
|
import net.i2p.router.tunnel.HopConfig;
|
||||||
import net.i2p.router.tunnel.TunnelDispatcher;
|
import net.i2p.router.tunnel.TunnelDispatcher;
|
||||||
|
import net.i2p.router.util.CDQEntry;
|
||||||
|
import net.i2p.router.util.CoDelBlockingQueue;
|
||||||
import net.i2p.stat.Rate;
|
import net.i2p.stat.Rate;
|
||||||
import net.i2p.stat.RateStat;
|
import net.i2p.stat.RateStat;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
@@ -51,7 +53,7 @@ class BuildHandler implements Runnable {
|
|||||||
private final BuildExecutor _exec;
|
private final BuildExecutor _exec;
|
||||||
private final Job _buildMessageHandlerJob;
|
private final Job _buildMessageHandlerJob;
|
||||||
private final Job _buildReplyMessageHandlerJob;
|
private final Job _buildReplyMessageHandlerJob;
|
||||||
private final LinkedBlockingQueue<BuildMessageState> _inboundBuildMessages;
|
private final BlockingQueue<BuildMessageState> _inboundBuildMessages;
|
||||||
private final BuildMessageProcessor _processor;
|
private final BuildMessageProcessor _processor;
|
||||||
private final ParticipatingThrottler _throttler;
|
private final ParticipatingThrottler _throttler;
|
||||||
private volatile boolean _isRunning;
|
private volatile boolean _isRunning;
|
||||||
@@ -79,7 +81,7 @@ class BuildHandler implements Runnable {
|
|||||||
_exec = exec;
|
_exec = exec;
|
||||||
// Queue size = 12 * share BW / 48K
|
// Queue size = 12 * share BW / 48K
|
||||||
int sz = Math.min(MAX_QUEUE, Math.max(MIN_QUEUE, TunnelDispatcher.getShareBandwidth(ctx) * MIN_QUEUE / 48));
|
int sz = Math.min(MAX_QUEUE, Math.max(MIN_QUEUE, TunnelDispatcher.getShareBandwidth(ctx) * MIN_QUEUE / 48));
|
||||||
_inboundBuildMessages = new LinkedBlockingQueue(sz);
|
_inboundBuildMessages = new CoDelBlockingQueue(ctx, "BuildHandler", sz);
|
||||||
|
|
||||||
_context.statManager().createRateStat("tunnel.reject.10", "How often we reject a tunnel probabalistically", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
_context.statManager().createRateStat("tunnel.reject.10", "How often we reject a tunnel probabalistically", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
||||||
_context.statManager().createRateStat("tunnel.reject.20", "How often we reject a tunnel because of transient overload", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
_context.statManager().createRateStat("tunnel.reject.20", "How often we reject a tunnel because of transient overload", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
||||||
@@ -137,7 +139,7 @@ class BuildHandler implements Runnable {
|
|||||||
public synchronized void shutdown(int numThreads) {
|
public synchronized void shutdown(int numThreads) {
|
||||||
_isRunning = false;
|
_isRunning = false;
|
||||||
_inboundBuildMessages.clear();
|
_inboundBuildMessages.clear();
|
||||||
BuildMessageState poison = new BuildMessageState(null, null, null);
|
BuildMessageState poison = new BuildMessageState(_context, null, null, null);
|
||||||
for (int i = 0; i < numThreads; i++) {
|
for (int i = 0; i < numThreads; i++) {
|
||||||
_inboundBuildMessages.offer(poison);
|
_inboundBuildMessages.offer(poison);
|
||||||
}
|
}
|
||||||
@@ -765,6 +767,7 @@ class BuildHandler implements Runnable {
|
|||||||
_context.statManager().addRateData("tunnel.buildReplyTooSlow", 1, 0);
|
_context.statManager().addRateData("tunnel.buildReplyTooSlow", 1, 0);
|
||||||
} else {
|
} else {
|
||||||
int sz = _inboundBuildMessages.size();
|
int sz = _inboundBuildMessages.size();
|
||||||
|
// Can probably remove this check, since CoDel is in use
|
||||||
BuildMessageState cur = _inboundBuildMessages.peek();
|
BuildMessageState cur = _inboundBuildMessages.peek();
|
||||||
boolean accept = true;
|
boolean accept = true;
|
||||||
if (cur != null) {
|
if (cur != null) {
|
||||||
@@ -773,21 +776,21 @@ class BuildHandler implements Runnable {
|
|||||||
_context.statManager().addRateData("tunnel.dropLoad", age, sz);
|
_context.statManager().addRateData("tunnel.dropLoad", age, sz);
|
||||||
_context.throttle().setTunnelStatus(_x("Dropping tunnel requests: High load"));
|
_context.throttle().setTunnelStatus(_x("Dropping tunnel requests: High load"));
|
||||||
// if the queue is backlogged, stop adding new messages
|
// if the queue is backlogged, stop adding new messages
|
||||||
_context.statManager().addRateData("tunnel.dropLoadBacklog", sz, sz);
|
|
||||||
accept = false;
|
accept = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (accept) {
|
if (accept) {
|
||||||
int queueTime = estimateQueueTime(sz);
|
// This is expensive and rarely seen, use CoDel instead
|
||||||
float pDrop = queueTime/((float)BuildRequestor.REQUEST_TIMEOUT*3);
|
//int queueTime = estimateQueueTime(sz);
|
||||||
pDrop = (float)Math.pow(pDrop, 16); // steeeep
|
//float pDrop = queueTime/((float)BuildRequestor.REQUEST_TIMEOUT*3);
|
||||||
float f = _context.random().nextFloat();
|
//pDrop = (float)Math.pow(pDrop, 16); // steeeep
|
||||||
|
//float f = _context.random().nextFloat();
|
||||||
//if ( (pDrop > f) && (allowProactiveDrop()) ) {
|
//if ( (pDrop > f) && (allowProactiveDrop()) ) {
|
||||||
if (pDrop > f) {
|
//if (pDrop > f) {
|
||||||
_context.throttle().setTunnelStatus(_x("Dropping tunnel requests: Queue time"));
|
// _context.throttle().setTunnelStatus(_x("Dropping tunnel requests: Queue time"));
|
||||||
_context.statManager().addRateData("tunnel.dropLoadProactive", queueTime, sz);
|
// _context.statManager().addRateData("tunnel.dropLoadProactive", queueTime, sz);
|
||||||
} else {
|
//} else {
|
||||||
accept = _inboundBuildMessages.offer(new BuildMessageState(receivedMessage, from, fromHash));
|
accept = _inboundBuildMessages.offer(new BuildMessageState(_context, receivedMessage, from, fromHash));
|
||||||
if (accept) {
|
if (accept) {
|
||||||
// wake up the Executor to call handleInboundRequests()
|
// wake up the Executor to call handleInboundRequests()
|
||||||
_exec.repoll();
|
_exec.repoll();
|
||||||
@@ -795,7 +798,7 @@ class BuildHandler implements Runnable {
|
|||||||
_context.throttle().setTunnelStatus(_x("Dropping tunnel requests: High load"));
|
_context.throttle().setTunnelStatus(_x("Dropping tunnel requests: High load"));
|
||||||
_context.statManager().addRateData("tunnel.dropLoadBacklog", sz, sz);
|
_context.statManager().addRateData("tunnel.dropLoadBacklog", sz, sz);
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -812,6 +815,7 @@ class BuildHandler implements Runnable {
|
|||||||
}
|
}
|
||||||
****/
|
****/
|
||||||
|
|
||||||
|
/****
|
||||||
private int estimateQueueTime(int numPendingMessages) {
|
private int estimateQueueTime(int numPendingMessages) {
|
||||||
int decryptTime = 200;
|
int decryptTime = 200;
|
||||||
RateStat rs = _context.statManager().getRate("tunnel.decryptRequestTime");
|
RateStat rs = _context.statManager().getRate("tunnel.decryptRequestTime");
|
||||||
@@ -832,8 +836,9 @@ class BuildHandler implements Runnable {
|
|||||||
estimatedQueueTime *= 1.2f; // lets leave some cpu to spare, 'eh?
|
estimatedQueueTime *= 1.2f; // lets leave some cpu to spare, 'eh?
|
||||||
return (int)estimatedQueueTime;
|
return (int)estimatedQueueTime;
|
||||||
}
|
}
|
||||||
|
****/
|
||||||
|
|
||||||
|
/** */
|
||||||
private class TunnelBuildReplyMessageHandlerJobBuilder implements HandlerJobBuilder {
|
private class TunnelBuildReplyMessageHandlerJobBuilder implements HandlerJobBuilder {
|
||||||
public Job createJob(I2NPMessage receivedMessage, RouterIdentity from, Hash fromHash) {
|
public Job createJob(I2NPMessage receivedMessage, RouterIdentity from, Hash fromHash) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
@@ -845,16 +850,32 @@ class BuildHandler implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** normal inbound requests from other people */
|
/** normal inbound requests from other people */
|
||||||
private static class BuildMessageState {
|
private static class BuildMessageState implements CDQEntry {
|
||||||
|
private final RouterContext _ctx;
|
||||||
final TunnelBuildMessage msg;
|
final TunnelBuildMessage msg;
|
||||||
final RouterIdentity from;
|
final RouterIdentity from;
|
||||||
final Hash fromHash;
|
final Hash fromHash;
|
||||||
final long recvTime;
|
final long recvTime;
|
||||||
public BuildMessageState(I2NPMessage m, RouterIdentity f, Hash h) {
|
|
||||||
|
public BuildMessageState(RouterContext ctx, I2NPMessage m, RouterIdentity f, Hash h) {
|
||||||
|
_ctx = ctx;
|
||||||
msg = (TunnelBuildMessage)m;
|
msg = (TunnelBuildMessage)m;
|
||||||
from = f;
|
from = f;
|
||||||
fromHash = h;
|
fromHash = h;
|
||||||
recvTime = System.currentTimeMillis();
|
recvTime = ctx.clock().now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnqueueTime(long time) {
|
||||||
|
// set at instantiation, which is just before enqueueing
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getEnqueueTime() {
|
||||||
|
return recvTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drop() {
|
||||||
|
_ctx.throttle().setTunnelStatus(_x("Dropping tunnel requests: Queue time"));
|
||||||
|
_ctx.statManager().addRateData("tunnel.dropLoadProactive", _ctx.clock().now() - recvTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user