Profiles:

- Remove unused calculators and RateStats:
    CapacityCalculator, StrictSpeedCalculator, IsFailingCalculator;
    sendFailureSize, processSuccessRate, processfailureRate, commErrorRate,
    tunnelTestResponseTimeSlow
  - Reduced number of Rates in these RateStats:
    sendSuccessSize, receiveSize, rejectRate, failRate
  - ~5KB/profile savings total
  - Deflate speed calculation once an hour instead of once a day,
    to improve fast tier selection
This commit is contained in:
zzz
2009-04-02 18:55:40 +00:00
parent 53cb80636a
commit f6bc9e8707
9 changed files with 21 additions and 399 deletions

View File

@@ -16,9 +16,7 @@ import net.i2p.router.peermanager.IsFailingCalculator;
import net.i2p.router.peermanager.PeerManagerFacadeImpl;
import net.i2p.router.peermanager.ProfileManagerImpl;
import net.i2p.router.peermanager.ProfileOrganizer;
import net.i2p.router.peermanager.ReliabilityCalculator;
import net.i2p.router.peermanager.SpeedCalculator;
import net.i2p.router.peermanager.StrictSpeedCalculator;
import net.i2p.router.transport.CommSystemFacadeImpl;
import net.i2p.router.transport.FIFOBandwidthLimiter;
import net.i2p.router.transport.OutboundMessageRegistry;
@@ -65,9 +63,7 @@ public class RouterContext extends I2PAppContext {
private Calculator _isFailingCalc;
private Calculator _integrationCalc;
private Calculator _speedCalc;
private Calculator _reliabilityCalc;
private Calculator _capacityCalc;
private Calculator _oldSpeedCalc;
private static List _contexts = new ArrayList(1);
@@ -135,8 +131,6 @@ public class RouterContext extends I2PAppContext {
_isFailingCalc = new IsFailingCalculator(this);
_integrationCalc = new IntegrationCalculator(this);
_speedCalc = new SpeedCalculator(this);
_oldSpeedCalc = new StrictSpeedCalculator(this);
_reliabilityCalc = new ReliabilityCalculator(this);
_capacityCalc = new CapacityCalculator(this);
}
@@ -270,9 +264,6 @@ public class RouterContext extends I2PAppContext {
public Calculator integrationCalculator() { return _integrationCalc; }
/** how do we rank the speed of profiles? */
public Calculator speedCalculator() { return _speedCalc; }
public Calculator oldSpeedCalculator() { return _oldSpeedCalc; }
/** how do we rank the reliability of profiles? */
public Calculator reliabilityCalculator() { return _reliabilityCalc; }
/** how do we rank the capacity of profiles? */
public Calculator capacityCalculator() { return _capacityCalc; }
@@ -301,7 +292,6 @@ public class RouterContext extends I2PAppContext {
buf.append(_isFailingCalc).append('\n');
buf.append(_integrationCalc).append('\n');
buf.append(_speedCalc).append('\n');
buf.append(_reliabilityCalc).append('\n');
return buf.toString();
}

View File

@@ -1,82 +0,0 @@
package net.i2p.router.peermanager;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
/**
* Simple boolean calculation to determine whether the given profile is "failing" -
* meaning we shouldn't bother trying to get them to do something. However, if we
* have a specific need to contact them in particular - e.g. instructions in a garlic
* or leaseSet - we will try. The currently implemented algorithm determines that
* a profile is failing if withing the last few minutes, they've done something bad: <ul>
* <li>It has a comm error (TCP disconnect, etc) in the last minute or two</li>
* <li>They've failed to respond to a db message in the last minute or two</li>
* <li>They've rejected a tunnel in the last 5 minutes</li>
* <li>They've been unreachable any time in the last 5 minutes</li>
* </ul>
*
*/
public class IsFailingCalculator extends Calculator {
private Log _log;
private RouterContext _context;
/** if they haven't b0rked in the last 2 minutes, they're ok */
private final static long GRACE_PERIOD = 2*60*1000;
public IsFailingCalculator(RouterContext context) {
_context = context;
_log = context.logManager().getLog(IsFailingCalculator.class);
}
public boolean calcBoolean(PeerProfile profile) {
// have we failed in the last 119 seconds?
/*
if ( (profile.getCommError().getRate(60*1000).getCurrentEventCount() > 0) ||
(profile.getCommError().getRate(60*1000).getLastEventCount() > 0) ||
(profile.getCommError().getRate(10*60*1000).getCurrentEventCount() > 0) ) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Peer " + profile.getPeer().toBase64()
+ " is failing because it had a comm error recently ");
return true;
} else {
*/
//if ( (profile.getDBHistory().getFailedLookupRate().getRate(60*1000).getCurrentEventCount() > 0) ||
// (profile.getDBHistory().getFailedLookupRate().getRate(60*1000).getLastEventCount() > 0) ) {
// // are they overloaded (or disconnected)?
// return true;
//}
// this doesn't make sense with probabalistic rejections - we should be
// adequately dampening the capacity so these peers aren't queried
//Rate rejectRate = profile.getTunnelHistory().getRejectionRate().getRate(10*60*1000);
//if (rejectRate.getCurrentEventCount() >= 2) {
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Peer " + profile.getPeer().toBase64()
// + " is failing because they rejected some tunnels recently");
// return true;
//}
////
// the right way to behave would be to use some statistical
// analysis on the failure rate, and only mark the peer as failing
// if their rate exceeded the expected rate (mean, median, stddev, etc)
////
//Rate failedRate = profile.getTunnelHistory().getFailedRate().getRate(60*1000);
//if (failedRate.getCurrentEventCount() >= 2) {
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Peer " + profile.getPeer().toBase64()
// + " is failing because too many of their tunnels failed recently");
// return true;
//}
// if they have rejected us saying they're totally broken anytime in the last
// 10 minutes, dont bother 'em
if (profile.getTunnelHistory().getLastRejectedCritical() > _context.clock().now() - 10*60*1000)
return true;
return false;
//}
}
}

View File

@@ -37,25 +37,19 @@ public class PeerProfile {
private double _tunnelTestResponseTimeAvg;
// periodic rates
private RateStat _sendSuccessSize = null;
private RateStat _sendFailureSize = null;
private RateStat _receiveSize = null;
private RateStat _dbResponseTime = null;
private RateStat _tunnelCreateResponseTime = null;
private RateStat _tunnelTestResponseTime = null;
private RateStat _tunnelTestResponseTimeSlow = null;
private RateStat _commError = null;
private RateStat _dbIntroduction = null;
// calculation bonuses
private long _speedBonus;
private long _reliabilityBonus;
private long _capacityBonus;
private long _integrationBonus;
// calculation values
private double _speedValue;
private double _reliabilityValue;
private double _capacityValue;
private double _integrationValue;
private double _oldSpeedValue;
private boolean _isFailing;
// good vs bad behavior
private TunnelHistory _tunnelHistory;
@@ -72,7 +66,6 @@ public class PeerProfile {
_log = context.logManager().getLog(PeerProfile.class);
_expanded = false;
_speedValue = 0;
_reliabilityValue = 0;
_capacityValue = 0;
_integrationValue = 0;
_isFailing = false;
@@ -111,6 +104,11 @@ public class PeerProfile {
* given period?)
* Also mark active if it is connected, as this will tend to encourage use
* of already-connected peers.
*
* Note: this appears to be the only use for these two RateStats.
*
* @param period must be one of the periods in the RateStat constructors below
* (5*60*1000 or 60*60*1000)
*/
public boolean getIsActive(long period) {
if ( (getSendSuccessSize().getRate(period).getCurrentEventCount() > 0) ||
@@ -154,8 +152,6 @@ public class PeerProfile {
/** how large successfully sent messages are, calculated over a 1 minute, 1 hour, and 1 day period */
public RateStat getSendSuccessSize() { return _sendSuccessSize; }
/** how large messages that could not be sent were, calculated over a 1 minute, 1 hour, and 1 day period */
public RateStat getSendFailureSize() { return _sendFailureSize; }
/** how large received messages are, calculated over a 1 minute, 1 hour, and 1 day period */
public RateStat getReceiveSize() { return _receiveSize; }
/** how long it takes to get a db response from the peer (in milliseconds), calculated over a 1 minute, 1 hour, and 1 day period */
@@ -164,10 +160,6 @@ public class PeerProfile {
public RateStat getTunnelCreateResponseTime() { return _tunnelCreateResponseTime; }
/** how long it takes to successfully test a tunnel this peer participates in (in milliseconds), calculated over a 10 minute, 1 hour, and 1 day period */
public RateStat getTunnelTestResponseTime() { return _tunnelTestResponseTime; }
/** how long it takes to successfully test the peer (in milliseconds) when the time exceeds 5s */
public RateStat getTunnelTestResponseTimeSlow() { return _tunnelTestResponseTimeSlow; }
/** how long between communication errors with the peer (disconnection, etc), calculated over a 1 minute, 1 hour, and 1 day period */
public RateStat getCommError() { return _commError; }
/** how many new peers we get from dbSearchReplyMessages or dbStore messages, calculated over a 1 hour, 1 day, and 1 week period */
public RateStat getDbIntroduction() { return _dbIntroduction; }
@@ -179,14 +171,6 @@ public class PeerProfile {
public long getSpeedBonus() { return _speedBonus; }
public void setSpeedBonus(long bonus) { _speedBonus = bonus; }
/**
* extra factor added to the reliability ranking - this can be updated in the profile
* written to disk to affect how the algorithm ranks reliability. Negative values are
* penalties
*/
public long getReliabilityBonus() { return _reliabilityBonus; }
public void setReliabilityBonus(long bonus) { _reliabilityBonus = bonus; }
/**
* extra factor added to the capacity ranking - this can be updated in the profile
* written to disk to affect how the algorithm ranks capacity. Negative values are
@@ -210,14 +194,6 @@ public class PeerProfile {
*
*/
public double getSpeedValue() { return _speedValue; }
public double getOldSpeedValue() { return _oldSpeedValue; }
/**
* How likely are they to stay up and pass on messages over the next few minutes.
* Positive numbers means more likely, negative numbers means its probably not
* even worth trying.
*
*/
public double getReliabilityValue() { return _reliabilityValue; }
/**
* How many tunnels do we think this peer can handle over the next hour?
*
@@ -354,13 +330,10 @@ public class PeerProfile {
*/
public void shrinkProfile() {
_sendSuccessSize = null;
_sendFailureSize = null;
_receiveSize = null;
_dbResponseTime = null;
_tunnelCreateResponseTime = null;
_tunnelTestResponseTime = null;
_tunnelTestResponseTimeSlow = null;
_commError = null;
_dbIntroduction = null;
_tunnelHistory = null;
_dbHistory = null;
@@ -378,21 +351,15 @@ public class PeerProfile {
public void expandProfile() {
String group = (null == _peer ? "profileUnknown" : _peer.toBase64().substring(0,6));
if (_sendSuccessSize == null)
_sendSuccessSize = new RateStat("sendSuccessSize", "How large successfully sent messages are", group, new long[] { 60*1000l, 5*60*1000l, 60*60*1000l, 24*60*60*1000l });
if (_sendFailureSize == null)
_sendFailureSize = new RateStat("sendFailureSize", "How large messages that could not be sent were", group, new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000 } );
_sendSuccessSize = new RateStat("sendSuccessSize", "How large successfully sent messages are", group, new long[] { 5*60*1000l, 60*60*1000l });
if (_receiveSize == null)
_receiveSize = new RateStat("receiveSize", "How large received messages are", group, new long[] { 60*1000l, 5*60*1000l, 60*60*1000l, 24*60*60*1000 } );
_receiveSize = new RateStat("receiveSize", "How large received messages are", group, new long[] { 5*60*1000l, 60*60*1000l } );
if (_dbResponseTime == null)
_dbResponseTime = new RateStat("dbResponseTime", "how long it takes to get a db response from the peer (in milliseconds)", group, new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000 } );
if (_tunnelCreateResponseTime == null)
_tunnelCreateResponseTime = new RateStat("tunnelCreateResponseTime", "how long it takes to get a tunnel create response from the peer (in milliseconds)", group, new long[] { 10*60*1000l, 30*60*1000l, 60*60*1000l, 24*60*60*1000 } );
if (_tunnelTestResponseTime == null)
_tunnelTestResponseTime = new RateStat("tunnelTestResponseTime", "how long it takes to successfully test a tunnel this peer participates in (in milliseconds)", group, new long[] { 10*60*1000l, 30*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000 } );
if (_tunnelTestResponseTimeSlow == null)
_tunnelTestResponseTimeSlow = new RateStat("tunnelTestResponseTimeSlow", "how long it takes to successfully test a peer when the time exceeds 5s", group, new long[] { 10*60*1000l, 30*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l, });
if (_commError == null)
_commError = new RateStat("commErrorRate", "how long between communication errors with the peer (e.g. disconnection)", group, new long[] { 60*1000l, 10*60*1000l, 60*60*1000l, 24*60*60*1000 } );
if (_dbIntroduction == null)
_dbIntroduction = new RateStat("dbIntroduction", "how many new peers we get from dbSearchReplyMessages or dbStore messages", group, new long[] { 60*60*1000l, 6*60*60*1000l, 24*60*60*1000l });
@@ -402,18 +369,17 @@ public class PeerProfile {
_dbHistory = new DBHistory(_context, group);
_sendSuccessSize.setStatLog(_context.statManager().getStatLog());
_sendFailureSize.setStatLog(_context.statManager().getStatLog());
_receiveSize.setStatLog(_context.statManager().getStatLog());
_dbResponseTime.setStatLog(_context.statManager().getStatLog());
_tunnelCreateResponseTime.setStatLog(_context.statManager().getStatLog());
_tunnelTestResponseTime.setStatLog(_context.statManager().getStatLog());
_tunnelTestResponseTimeSlow.setStatLog(_context.statManager().getStatLog());
_commError.setStatLog(_context.statManager().getStatLog());
_dbIntroduction.setStatLog(_context.statManager().getStatLog());
_expanded = true;
}
/** once a day, on average, cut the measured throughtput values in half */
private static final long DROP_PERIOD_MINUTES = 24*60;
/** let's try once an hour times 3/4 */
private static final int DROP_PERIOD_MINUTES = 60;
private static final double DEGRADE_FACTOR = 0.75;
private long _lastCoalesceDate = System.currentTimeMillis();
private void coalesceThroughput() {
long now = System.currentTimeMillis();
@@ -430,46 +396,19 @@ public class PeerProfile {
break;
}
}
if (false && _log.shouldLog(Log.WARN) ) {
StringBuffer buf = new StringBuffer(128);
buf.append("Updating throughput after ").append(tot).append(" to ");
for (int i = 0; i < THROUGHPUT_COUNT; i++)
buf.append(_peakThroughput[i]).append(',');
buf.append(" for ").append(_peer.toBase64());
_log.warn(buf.toString());
}
} else {
if (_context.random().nextLong(DROP_PERIOD_MINUTES*2) <= 0) {
for (int i = 0; i < THROUGHPUT_COUNT; i++)
_peakThroughput[i] /= 2;
if (false && _log.shouldLog(Log.WARN) ) {
StringBuffer buf = new StringBuffer(128);
buf.append("Degrading the throughput measurements to ");
for (int i = 0; i < THROUGHPUT_COUNT; i++)
buf.append(_peakThroughput[i]).append(',');
buf.append(" for ").append(_peer.toBase64());
_log.warn(buf.toString());
}
if (_context.random().nextInt(DROP_PERIOD_MINUTES*2) <= 0) {
for (int i = 0; i < THROUGHPUT_COUNT; i++)
_peakThroughput[i] *= DEGRADE_FACTOR;
}
}
// we degrade the tunnel throughput here too, regardless of the current
// activity
if (_context.random().nextLong(DROP_PERIOD_MINUTES*2) <= 0) {
if (_context.random().nextInt(DROP_PERIOD_MINUTES*2) <= 0) {
for (int i = 0; i < THROUGHPUT_COUNT; i++) {
_peakTunnelThroughput[i] /= 2;
_peakTunnel1mThroughput[i] /= 2;
}
if (_log.shouldLog(Log.WARN) ) {
StringBuffer buf = new StringBuffer(128);
buf.append("Degrading the tunnel throughput measurements to ");
for (int i = 0; i < THROUGHPUT_COUNT; i++)
buf.append(_peakTunnel1mThroughput[i]).append(',');
buf.append(" for ").append(_peer.toBase64());
_log.warn(buf.toString());
_peakTunnelThroughput[i] *= DEGRADE_FACTOR;
_peakTunnel1mThroughput[i] *= DEGRADE_FACTOR;
}
}
_peakThroughputCurrentTotal = 0;
@@ -480,34 +419,27 @@ public class PeerProfile {
/** update the stats and rates (this should be called once a minute) */
public void coalesceStats() {
if (!_expanded) return;
_commError.coalesceStats();
_dbIntroduction.coalesceStats();
_dbResponseTime.coalesceStats();
_receiveSize.coalesceStats();
_sendFailureSize.coalesceStats();
_sendSuccessSize.coalesceStats();
_tunnelCreateResponseTime.coalesceStats();
_tunnelTestResponseTime.coalesceStats();
_tunnelTestResponseTimeSlow.coalesceStats();
_dbHistory.coalesceStats();
_tunnelHistory.coalesceStats();
coalesceThroughput();
_speedValue = calculateSpeed();
_oldSpeedValue = calculateOldSpeed();
_reliabilityValue = calculateReliability();
_capacityValue = calculateCapacity();
_integrationValue = calculateIntegration();
_isFailing = calculateIsFailing();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Coalesced: speed [" + _speedValue + "] reliability [" + _reliabilityValue + "] capacity [" + _capacityValue + "] integration [" + _integrationValue + "] failing? [" + _isFailing + "]");
_log.debug("Coalesced: speed [" + _speedValue + "] capacity [" + _capacityValue + "] integration [" + _integrationValue + "] failing? [" + _isFailing + "]");
}
private double calculateSpeed() { return _context.speedCalculator().calc(this); }
private double calculateOldSpeed() { return _context.oldSpeedCalculator().calc(this); }
private double calculateReliability() { return _context.reliabilityCalculator().calc(this); }
private double calculateCapacity() { return _context.capacityCalculator().calc(this); }
private double calculateIntegration() { return _context.integrationCalculator().calc(this); }
private boolean calculateIsFailing() { return _context.isFailingCalculator().calcBoolean(this); }
@@ -584,7 +516,6 @@ public class PeerProfile {
//profile.coalesceStats();
buf.append("Peer " + profile.getPeer().toBase64()
+ ":\t Speed:\t" + fmt.format(profile.calculateSpeed())
+ " Reliability:\t" + fmt.format(profile.calculateReliability())
+ " Capacity:\t" + fmt.format(profile.calculateCapacity())
+ " Integration:\t" + fmt.format(profile.calculateIntegration())
+ " Active?\t" + profile.getIsActive()

View File

@@ -50,7 +50,6 @@ public class ProfileManagerImpl implements ProfileManager {
PeerProfile data = getProfile(peer);
if (data == null) return;
data.setLastSendFailed(_context.clock().now());
data.getSendFailureSize().addData(0, 0); // yeah, should be a frequency...
}
/**
@@ -61,7 +60,6 @@ public class ProfileManagerImpl implements ProfileManager {
PeerProfile data = getProfile(peer);
if (data == null) return;
data.setLastSendFailed(_context.clock().now());
data.getSendFailureSize().addData(0, 0); // yeah, should be a frequency...
}
/**
@@ -74,8 +72,6 @@ public class ProfileManagerImpl implements ProfileManager {
PeerProfile data = getProfile(peer);
if (data == null) return;
data.setLastSendFailed(_context.clock().now());
data.getSendFailureSize().addData(1, 0); // yeah, should be a frequency...
data.getCommError().addData(1, 0); // see above
}
/**
@@ -125,8 +121,6 @@ public class ProfileManagerImpl implements ProfileManager {
if (data == null) return;
data.updateTunnelTestTimeAverage(responseTimeMs);
data.getTunnelTestResponseTime().addData(responseTimeMs, responseTimeMs);
if (responseTimeMs > getSlowThreshold())
data.getTunnelTestResponseTimeSlow().addData(responseTimeMs, responseTimeMs);
}
public void tunnelDataPushed(Hash peer, long rtt, int size) {

View File

@@ -1028,7 +1028,7 @@ public class ProfileOrganizer {
/**
* called after locking the reorganizeLock, place the profile in the appropriate tier.
* This is where we implement the (betterThanAverage ? goToPierX : goToPierY) algorithms
* This is where we implement the (betterThanAverage ? goToTierX : goToTierY) algorithms
*
*/
private void locked_placeProfile(PeerProfile profile) {
@@ -1153,7 +1153,6 @@ public class ProfileOrganizer {
organizer.isHighCapacity(peer) ? "IR " :
organizer.isFailing(peer) ? "IX " : "I ") + "]: "
+ "\t Speed:\t" + fmt.format(profile.getSpeedValue())
+ " Reliability:\t" + fmt.format(profile.getReliabilityValue())
+ " Capacity:\t" + fmt.format(profile.getCapacityValue())
+ " Integration:\t" + fmt.format(profile.getIntegrationValue())
+ " Active?\t" + profile.getIsActive()
@@ -1164,7 +1163,6 @@ public class ProfileOrganizer {
organizer.isHighCapacity(peer) ? "R " :
organizer.isFailing(peer) ? "X " : " ") + "]: "
+ "\t Speed:\t" + fmt.format(profile.getSpeedValue())
+ " Reliability:\t" + fmt.format(profile.getReliabilityValue())
+ " Capacity:\t" + fmt.format(profile.getCapacityValue())
+ " Integration:\t" + fmt.format(profile.getIntegrationValue())
+ " Active?\t" + profile.getIsActive()

View File

@@ -95,7 +95,6 @@ class ProfilePersistenceHelper {
if (_us != null)
buf.append("# as calculated by ").append(_us.toBase64()).append(NL);
buf.append("#").append(NL);
buf.append("# reliability: ").append(profile.getReliabilityValue()).append(NL);
buf.append("# capacity: ").append(profile.getCapacityValue()).append(NL);
buf.append("# integration: ").append(profile.getIntegrationValue()).append(NL);
buf.append("# speedValue: ").append(profile.getSpeedValue()).append(NL);
@@ -134,15 +133,12 @@ class ProfilePersistenceHelper {
if (profile.getIsExpanded()) {
// only write out expanded data if, uh, we've got it
profile.getCommError().store(out, "commError");
profile.getDbIntroduction().store(out, "dbIntroduction");
profile.getDbResponseTime().store(out, "dbResponseTime");
profile.getReceiveSize().store(out, "receiveSize");
profile.getSendFailureSize().store(out, "sendFailureSize");
profile.getSendSuccessSize().store(out, "sendSuccessSize");
profile.getTunnelCreateResponseTime().store(out, "tunnelCreateResponseTime");
profile.getTunnelTestResponseTime().store(out, "tunnelTestResponseTime");
profile.getTunnelTestResponseTimeSlow().store(out, "tunnelTestResponseTimeSlow");
}
}
@@ -217,15 +213,12 @@ class ProfilePersistenceHelper {
profile.getTunnelHistory().load(props);
profile.getDBHistory().load(props);
profile.getCommError().load(props, "commError", true);
profile.getDbIntroduction().load(props, "dbIntroduction", true);
profile.getDbResponseTime().load(props, "dbResponseTime", true);
profile.getReceiveSize().load(props, "receiveSize", true);
profile.getSendFailureSize().load(props, "sendFailureSize", true);
profile.getSendSuccessSize().load(props, "sendSuccessSize", true);
profile.getTunnelCreateResponseTime().load(props, "tunnelCreateResponseTime", true);
profile.getTunnelTestResponseTime().load(props, "tunnelTestResponseTime", true);
profile.getTunnelTestResponseTimeSlow().load(props, "tunnelTestResponseTimeSlow", true);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Loaded the profile for " + peer.toBase64() + " from " + file.getName());

View File

@@ -1,91 +0,0 @@
package net.i2p.router.peermanager;
import net.i2p.router.RouterContext;
import net.i2p.stat.RateStat;
import net.i2p.util.Log;
/**
* Determine how reliable the peer is - how likely they'll be able to respond or
* otherwise carry out whatever we ask them to (or even merely be reachable)
*
*/
public class ReliabilityCalculator extends Calculator {
private Log _log;
private RouterContext _context;
public ReliabilityCalculator(RouterContext context) {
_context = context;
_log = context.logManager().getLog(ReliabilityCalculator.class);
}
public double calc(PeerProfile profile) {
// if we've never succeeded (even if we've never tried), the reliability is zip
if (profile.getSendSuccessSize().getRate(60*60*1000).getLifetimeEventCount() < 0)
return profile.getReliabilityBonus();
long val = 0;
val += profile.getSendSuccessSize().getRate(60*1000).getCurrentEventCount() * 20;
val += profile.getSendSuccessSize().getRate(60*1000).getLastEventCount() * 10;
val += profile.getSendSuccessSize().getRate(60*60*1000).getLastEventCount() * 1;
val += profile.getSendSuccessSize().getRate(60*60*1000).getCurrentEventCount() * 5;
val += profile.getTunnelCreateResponseTime().getRate(10*60*1000).getLastEventCount() * 5;
val += profile.getTunnelCreateResponseTime().getRate(60*60*1000).getCurrentEventCount();
val += profile.getTunnelCreateResponseTime().getRate(60*60*1000).getLastEventCount();
//val -= profile.getSendFailureSize().getRate(60*1000).getLastEventCount() * 5;
//val -= profile.getSendFailureSize().getRate(60*60*1000).getCurrentEventCount()*2;
//val -= profile.getSendFailureSize().getRate(60*60*1000).getLastEventCount()*2;
RateStat rejRate = profile.getTunnelHistory().getRejectionRate();
if (rejRate.getRate(60*1000).getCurrentEventCount() > 0)
val -= 200;
if (rejRate.getRate(60*1000).getLastEventCount() > 0)
val -= 100;
if (rejRate.getRate(10*60*1000).getCurrentEventCount() > 0)
val -= 10;
if (rejRate.getRate(10*60*1000).getCurrentEventCount() > 0)
val -= 5;
// penalize them heavily for dropping netDb requests (though these could have
// failed due to tunnel timeouts, so don't be too mean)
if (profile.getDBHistory().getFailedLookupRate().getRate(60*1000).getCurrentEventCount() > 0)
val -= 10;
if (profile.getDBHistory().getFailedLookupRate().getRate(60*1000).getLastEventCount() > 0)
val -= 5;
// scream and shout on network errors
if (profile.getCommError().getRate(60*1000).getCurrentEventCount() > 0)
val -= 200;
if (profile.getCommError().getRate(60*1000).getLastEventCount() > 0)
val -= 200;
if (profile.getCommError().getRate(60*60*1000).getCurrentEventCount() > 0)
val -= 10;
if (profile.getCommError().getRate(60*60*1000).getLastEventCount() > 0)
val -= 10;
val -= profile.getCommError().getRate(24*60*60*1000).getCurrentEventCount() * 1;
//long now = _context.clock().now();
long timeSinceRejection = 61*60*1000; // now - profile.getTunnelHistory().getLastRejected();
if (timeSinceRejection > 60*60*1000) {
// noop. rejection was over 60 minutes ago
} else if (timeSinceRejection > 10*60*1000) {
val -= 10; // 10-60 minutes ago we got a rejection
} else if (timeSinceRejection > 60*1000) {
val -= 50; // 1-10 minutes ago we got a rejection
} else {
val -= 100; // we got a rejection within the last minute
}
//if ( (profile.getLastSendSuccessful() > 0) && (now - 24*60*60*1000 > profile.getLastSendSuccessful()) ) {
// // we know they're real, but we havent sent them a message successfully in over a day.
// val -= 1000;
//}
val += profile.getReliabilityBonus();
return val;
}
}

View File

@@ -1,90 +0,0 @@
package net.i2p.router.peermanager;
import net.i2p.router.RouterContext;
import net.i2p.stat.Rate;
import net.i2p.stat.RateStat;
import net.i2p.util.Log;
/**
* Simple speed calculator that just counts how many messages go through the
* tunnel.
*
*/
public class StrictSpeedCalculator extends Calculator {
private Log _log;
private RouterContext _context;
public StrictSpeedCalculator(RouterContext context) {
_context = context;
_log = context.logManager().getLog(StrictSpeedCalculator.class);
}
public double calc(PeerProfile profile) {
return countSuccesses(profile);
}
private double countSuccesses(PeerProfile profile) {
RateStat success = profile.getTunnelHistory().getProcessSuccessRate();
RateStat failure = profile.getTunnelHistory().getProcessFailureRate();
return messagesPerMinute(success, failure);
}
private double messagesPerMinute(RateStat success, RateStat failure) {
double rv = 0.0d;
if (success != null) {
Rate rate = null;
long periods[] = success.getPeriods();
for (int i = 0; i < periods.length; i++) {
rate = success.getRate(periods[i]);
if ( (rate != null) && (rate.getCurrentTotalValue() > 0) )
break;
}
double value = rate.getCurrentTotalValue();
value += rate.getLastTotalValue();
rv = value * 10.0d * 60.0d * 1000.0d / (double)rate.getPeriod();
// if any of the messages are getting fragmented and cannot be
// handled, penalize like crazy
Rate fail = failure.getRate(rate.getPeriod());
if (fail.getCurrentTotalValue() > 0)
rv /= fail.getCurrentTotalValue();
}
return rv;
}
/*
public double calc(PeerProfile profile) {
double successCount = countSuccesses(profile);
double failureCount = countFailures(profile);
double rv = successCount - 5*failureCount;
if (rv < 0)
rv = 0;
return rv;
}
private double countSuccesses(PeerProfile profile) {
RateStat success = profile.getTunnelHistory().getProcessSuccessRate();
return messagesPerMinute(success);
}
private double countFailures(PeerProfile profile) {
RateStat failure = profile.getTunnelHistory().getProcessFailureRate();
return messagesPerMinute(failure);
}
private double messagesPerMinute(RateStat stat) {
double rv = 0.0d;
if (stat != null) {
Rate rate = null;
long periods[] = stat.getPeriods();
for (int i = 0; i < periods.length; i++) {
rate = stat.getRate(periods[i]);
if ( (rate != null) && (rate.getCurrentTotalValue() > 0) )
break;
}
double value = rate.getCurrentTotalValue();
value += rate.getLastTotalValue();
rv = value * 60.0d * 1000.0d / (double)rate.getPeriod();
}
return rv;
}
*/
}

View File

@@ -26,8 +26,6 @@ public class TunnelHistory {
private volatile long _lastFailed;
private RateStat _rejectRate;
private RateStat _failRate;
private RateStat _processSuccessRate;
private RateStat _processFailureRate;
private String _statGroup;
/** probabalistic tunnel rejection due to a flood of requests */
@@ -47,14 +45,10 @@ public class TunnelHistory {
}
private void createRates(String statGroup) {
_rejectRate = new RateStat("tunnelHistory.rejectRate", "How often does this peer reject a tunnel request?", statGroup, new long[] { 60*1000l, 10*60*1000l, 30*60*1000l, 60*60*1000l, 24*60*60*1000l });
_failRate = new RateStat("tunnelHistory.failRate", "How often do tunnels this peer accepts fail?", statGroup, new long[] { 60*1000l, 10*60*1000l, 30*60*1000l, 60*60*1000l, 24*60*60*1000l });
_processSuccessRate = new RateStat("tunnelHistory.processSuccessRate", "How many messages does a tunnel process?", statGroup, new long[] { 5*60*1000l, 10*60*1000l, 30*60*1000l, 60*60*1000l, 24*60*60*1000l });
_processFailureRate = new RateStat("tunnelHistory.processfailureRate", "How many messages does a tunnel fail?", statGroup, new long[] { 5*60*1000l, 10*60*1000l, 30*60*1000l, 60*60*1000l, 24*60*60*1000l });
_rejectRate = new RateStat("tunnelHistory.rejectRate", "How often does this peer reject a tunnel request?", statGroup, new long[] { 10*60*1000l, 30*60*1000l, 60*60*1000l, 24*60*60*1000l });
_failRate = new RateStat("tunnelHistory.failRate", "How often do tunnels this peer accepts fail?", statGroup, new long[] { 10*60*1000l, 30*60*1000l, 60*60*1000l, 24*60*60*1000l });
_rejectRate.setStatLog(_context.statManager().getStatLog());
_failRate.setStatLog(_context.statManager().getStatLog());
_processSuccessRate.setStatLog(_context.statManager().getStatLog());
_processFailureRate.setStatLog(_context.statManager().getStatLog());
}
/** total tunnels the peer has agreed to participate in */
@@ -77,10 +71,7 @@ public class TunnelHistory {
public long getLastFailed() { return _lastFailed; }
public void incrementProcessed(int processedSuccessfully, int failedProcessing) {
if (processedSuccessfully > 0)
_processSuccessRate.addData(processedSuccessfully, 0);
if (failedProcessing > 0)
_processFailureRate.addData(failedProcessing, 0);
// old strict speed calculator
}
public void incrementAgreedTo() {
@@ -129,16 +120,12 @@ public class TunnelHistory {
public RateStat getRejectionRate() { return _rejectRate; }
public RateStat getFailedRate() { return _failRate; }
public RateStat getProcessSuccessRate() { return _processSuccessRate; }
public RateStat getProcessFailureRate() { return _processFailureRate; }
public void coalesceStats() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Coallescing stats");
_rejectRate.coalesceStats();
_failRate.coalesceStats();
_processFailureRate.coalesceStats();
_processSuccessRate.coalesceStats();
}
private final static String NL = System.getProperty("line.separator");
@@ -161,8 +148,6 @@ public class TunnelHistory {
out.write(buf.toString().getBytes());
_rejectRate.store(out, "tunnelHistory.rejectRate");
_failRate.store(out, "tunnelHistory.failRate");
_processSuccessRate.store(out, "tunnelHistory.processSuccessRate");
_processFailureRate.store(out, "tunnelHistory.processFailureRate");
}
private void add(StringBuffer buf, String name, long val, String description) {
@@ -187,12 +172,6 @@ public class TunnelHistory {
_failRate.load(props, "tunnelHistory.failRate", true);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Loading tunnelHistory.failRate");
_processFailureRate.load(props, "tunnelHistory.processFailureRate", true);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Loading tunnelHistory.processFailureRate");
_processSuccessRate.load(props, "tunnelHistory.processSuccessRate", true);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Loading tunnelHistory.processSuccessRate");
} catch (IllegalArgumentException iae) {
_log.warn("TunnelHistory rates are corrupt, resetting", iae);
createRates(_statGroup);