Author: toad
Date: 2009-01-09 18:48:27 +0000 (Fri, 09 Jan 2009)
New Revision: 24991

Modified:
   trunk/freenet/src/freenet/node/NodeStats.java
Log:
Transfer speed optimiser: New mechanism for limiting incoming requests.
If we cannot complete all our current requests, assuming the average bandwidth 
usage for each type, in 5 seconds, then don't accept a request.
Is adjusted for really slow nodes, but adjustment is not necessary for 12K/sec 
or higher.
The objective here is to improve transfer speed of individual requests, which 
typically take 18 seconds at the moment.
Improving on this should significantly improve latency for latency-sensitive 
stuff most notably fproxy on a new node.
Until this is deployed across the network and has had time to settle, it *may 
reduce performance significantly* because we assume that other nodes have the 
same code!


Modified: trunk/freenet/src/freenet/node/NodeStats.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeStats.java       2009-01-09 18:04:46 UTC 
(rev 24990)
+++ trunk/freenet/src/freenet/node/NodeStats.java       2009-01-09 18:48:27 UTC 
(rev 24991)
@@ -631,6 +631,138 @@
                        return "Input bandwidth liability 
("+bandwidthLiabilityInput+" > "+bandwidthAvailableInput+")";
                }
                
+               // We want fast transfers!
+               // We want it to be *possible* for all transfers currently 
running to complete in a short period.
+               // This does NOT assume they are all successful, it uses the 
averages.
+               // As of 09/01/09, the typical successful CHK fetch takes 
around 18 seconds ...
+               
+               // Accept a transfer if our *current* load can be completed in 
the target time.
+               // We do not care what the new request we are considering is.
+               // This is more or less equivalent to what we do above but lets 
more requests through.
+               
+               numRemoteCHKRequests--;
+               numRemoteSSKRequests--;
+               numRemoteCHKInserts--;
+               numRemoteSSKInserts--;
+               numLocalCHKRequests--;
+               numLocalSSKRequests--;
+               numLocalCHKInserts--;
+               numLocalSSKInserts--;
+               
+               final double TRANSFER_EVERYTHING_TIME = 5.0; // 5 seconds target
+               
+               double completionBandwidthOutput;
+               if(ignoreLocalVsRemoteBandwidthLiability) {
+                       completionBandwidthOutput = 
+                               remoteChkFetchBytesSentAverage.currentValue() * 
(numRemoteCHKRequests + numLocalCHKRequests) +
+                               remoteSskFetchBytesSentAverage.currentValue() * 
(numRemoteSSKRequests + numLocalSSKRequests) +
+                               remoteChkInsertBytesSentAverage.currentValue() 
* (numRemoteCHKInserts + numLocalCHKInserts) +
+                               remoteSskInsertBytesSentAverage.currentValue() 
* (numRemoteSSKInserts + numLocalSSKInserts);
+               } else {
+               completionBandwidthOutput =
+                       remoteChkFetchBytesSentAverage.currentValue() * 
numRemoteCHKRequests +
+                       localChkFetchBytesSentAverage.currentValue() * 
numLocalCHKRequests +
+                       remoteSskFetchBytesSentAverage.currentValue() * 
numRemoteSSKRequests +
+                       localSskFetchBytesSentAverage.currentValue() * 
numLocalSSKRequests +
+                       remoteChkInsertBytesSentAverage.currentValue() * 
numRemoteCHKInserts +
+                       localChkInsertBytesSentAverage.currentValue() * 
numLocalCHKInserts +
+                       remoteSskInsertBytesSentAverage.currentValue() * 
numRemoteSSKInserts +
+                       localSskInsertBytesSentAverage.currentValue() * 
numLocalSSKInserts +
+                       successfulChkOfferReplyBytesSentAverage.currentValue() 
* numCHKOfferReplies +
+                       successfulSskOfferReplyBytesSentAverage.currentValue() 
* numSSKOfferReplies;
+               }
+               
+               int outputLimit = node.getOutputBandwidthLimit();
+               
+               double outputBandwidthAvailableInTargetTime = outputLimit * 
TRANSFER_EVERYTHING_TIME;
+               
+               // Increase the target for slow nodes.
+               
+               double minimum =
+                       remoteChkFetchBytesSentAverage.currentValue() +
+                       localChkFetchBytesSentAverage.currentValue() +
+                       remoteSskFetchBytesSentAverage.currentValue() +
+                       localSskFetchBytesSentAverage.currentValue() +
+                       remoteChkInsertBytesSentAverage.currentValue() +
+                       localChkInsertBytesSentAverage.currentValue() +
+                       remoteSskInsertBytesSentAverage.currentValue() +
+                       localSskInsertBytesSentAverage.currentValue() +
+                       successfulChkOfferReplyBytesSentAverage.currentValue() +
+                       successfulSskOfferReplyBytesSentAverage.currentValue();
+               minimum /= 2; // roughly one of each type, averaged over remote 
and local; FIXME get a real non-specific average
+               
+               if(outputBandwidthAvailableInTargetTime < minimum) {
+                       outputBandwidthAvailableInTargetTime = minimum;
+                       if(logMINOR) Logger.minor(this, "Increased minimum time 
to transfer everything to "+(minimum / outputLimit)+"s = "+minimum+"B to 
compensate for slow node");
+               }
+               
+               if(logMINOR) Logger.minor(this, TRANSFER_EVERYTHING_TIME+" 
second limit: "+outputBandwidthAvailableInTargetTime+" expected transfers: 
"+completionBandwidthOutput);
+               
+               if(completionBandwidthOutput > 
outputBandwidthAvailableInTargetTime) {
+                       pInstantRejectIncoming.report(1.0);
+                       rejected("Transfer speed (output)", isLocal);
+                       return "Transfer speed (output) 
("+bandwidthLiabilityOutput+" > "+bandwidthAvailableOutput+")";
+               }
+               
+               
+               
+               double completionBandwidthInput;
+               if(ignoreLocalVsRemoteBandwidthLiability) {
+                       completionBandwidthInput =
+                               
remoteChkFetchBytesReceivedAverage.currentValue() * (numRemoteCHKRequests + 
numLocalCHKRequests) +
+                               
remoteSskFetchBytesReceivedAverage.currentValue() * (numRemoteSSKRequests + 
numLocalSSKRequests) +
+                               
remoteChkInsertBytesReceivedAverage.currentValue() * (numRemoteCHKInserts + 
numLocalCHKInserts) +
+                               
remoteSskInsertBytesReceivedAverage.currentValue() * (numRemoteSSKInserts + 
numLocalSSKInserts);
+               } else {
+               completionBandwidthInput =
+                       // For receiving data, local requests are the same as 
remote ones
+                       remoteChkFetchBytesReceivedAverage.currentValue() * 
numRemoteCHKRequests +
+                       localChkFetchBytesReceivedAverage.currentValue() * 
numLocalCHKRequests +
+                       remoteSskFetchBytesReceivedAverage.currentValue() * 
numRemoteSSKRequests +
+                       localSskFetchBytesReceivedAverage.currentValue() * 
numLocalSSKRequests +
+                       // Local inserts don't receive the data to relay, so 
use the local variant
+                       remoteChkInsertBytesReceivedAverage.currentValue() * 
numRemoteCHKInserts +
+                       localChkInsertBytesReceivedAverage.currentValue() * 
numLocalCHKInserts +
+                       remoteSskInsertBytesReceivedAverage.currentValue() * 
numRemoteSSKInserts +
+                       localSskInsertBytesReceivedAverage.currentValue() * 
numLocalSSKInserts +
+                       
successfulChkOfferReplyBytesReceivedAverage.currentValue() * numCHKOfferReplies 
+
+                       
successfulSskOfferReplyBytesReceivedAverage.currentValue() * numSSKOfferReplies;
+               }
+               int inputLimit = node.getInputBandwidthLimit();
+               double inputBandwidthAvailableInTargetTime =
+                       inputLimit * TRANSFER_EVERYTHING_TIME;
+               
+               // Increase the target for slow nodes.
+               
+               minimum =
+                       remoteChkFetchBytesReceivedAverage.currentValue() +
+                       localChkFetchBytesReceivedAverage.currentValue() +
+                       remoteSskFetchBytesReceivedAverage.currentValue() +
+                       localSskFetchBytesReceivedAverage.currentValue() +
+                       remoteChkInsertBytesReceivedAverage.currentValue() +
+                       localChkInsertBytesReceivedAverage.currentValue() +
+                       remoteSskInsertBytesReceivedAverage.currentValue() +
+                       localSskInsertBytesReceivedAverage.currentValue() +
+                       
successfulChkOfferReplyBytesReceivedAverage.currentValue() +
+                       
successfulSskOfferReplyBytesReceivedAverage.currentValue();
+               minimum /= 2; // roughly one of each type, averaged over remote 
and local; FIXME get a real non-specific average
+               
+               if(inputBandwidthAvailableInTargetTime < minimum) {
+                       inputBandwidthAvailableInTargetTime = minimum;
+                       if(logMINOR) Logger.minor(this, "Increased minimum time 
to transfer everything (input) to "+(minimum / inputLimit)+"s = "+minimum+"B to 
compensate for slow node");
+               }
+               
+
+               
+               if(bandwidthAvailableInput < 0){
+                       Logger.error(this, "Negative available bandwidth: 
"+inputBandwidthAvailableInTargetTime+" 
node.ibwlimit="+node.getInputBandwidthLimit()+" 
node.obwlimit="+node.getOutputBandwidthLimit()+" 
node.inputLimitDefault="+node.inputLimitDefault);
+               }
+               if(completionBandwidthInput > 
inputBandwidthAvailableInTargetTime) {
+                       pInstantRejectIncoming.report(1.0);
+                       rejected("Transfer speed (input)", isLocal);
+                       return "Transfer speed (input) 
("+bandwidthLiabilityInput+" > "+bandwidthAvailableInput+")";
+               }
+               
                // Do we have the bandwidth?
                double expected = this.getThrottle(isLocal, isInsert, isSSK, 
true).currentValue();
                int expectedSent = (int)Math.max(expected / overheadFraction, 
0);

_______________________________________________
cvs mailing list
[email protected]
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs

Reply via email to