Fields Summary |
---|
private static final String | CONFIG_MIN_UP |
private static final String | CONFIG_MAX_UP |
private static final String | CONFIG_MAX_INC |
private static final String | CONFIG_MAX_DEC |
private static final String | CONFIG_CHOKE_PING |
private static final String | CONFIG_DOWNADJ_ENABLE |
private static final String | CONFIG_DOWNADJ_RATIO |
private static final String | CONFIG_LATENCY_FACTOR |
private static final String | CONFIG_FORCED_MIN |
private static int | PING_CHOKE_TIME |
private static int | MIN_UP |
private static int | MAX_UP |
private static boolean | ADJUST_DOWNLOAD_ENABLE |
private static float | ADJUST_DOWNLOAD_RATIO |
private static int | MAX_INCREMENT |
private static int | MAX_DECREMENT |
private static int | LATENCY_FACTOR |
private static int | FORCED_MIN_SPEED |
private static final String[] | CONFIG_PARAMS |
private static final int | UNLIMITED |
private static final int | MODE_RUNNING |
private static final int | MODE_FORCED_MIN |
private static final int | MODE_FORCED_MAX |
private static final int | FORCED_MAX_TICKS |
private static final int | FORCED_MIN_TICKS |
private static final int | FORCED_MIN_AT_START_TICK_LIMIT |
private static final int | PING_AVERAGE_HISTORY_COUNT |
private static final int | IDLE_UPLOAD_SPEED |
private static final int | INITIAL_IDLE_AVERAGE |
private static final int | MIN_IDLE_AVERAGE |
private static final int | INCREASING |
private static final int | DECREASING |
private com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderAdapter | adapter |
private com.aelitis.azureus.core.util.average.Average | upload_average |
private com.aelitis.azureus.core.util.average.Average | upload_short_average |
private com.aelitis.azureus.core.util.average.Average | upload_short_prot_average |
private com.aelitis.azureus.core.util.average.Average | ping_average_history |
private com.aelitis.azureus.core.util.average.Average | choke_speed_average |
private Map | ping_sources |
private volatile int | replacement_contacts |
private int | mode |
private volatile int | mode_ticks |
private int | saved_limit |
private int | direction |
private int | ticks |
private int | idle_ticks |
private int | idle_average |
private boolean | idle_average_set |
private int | max_ping |
private int | max_upload_average |
Methods Summary |
---|
public void | calculate(com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource[] sources)
int min_rtt = UNLIMITED;
for (int i=0;i<sources.length;i++){
int rtt = sources[i].getPingTime();
if ( rtt > 0 && rtt < min_rtt ){
min_rtt = rtt;
}
}
String str = "";
int ping_total = 0;
int ping_count = 0;
for (int i=0;i<sources.length;i++){
pingSource ps;
synchronized( ping_sources ){
ps = (pingSource)ping_sources.get( sources[i] );
}
int rtt = sources[i].getPingTime();
str += (i==0?"":",") + rtt;
// discount anything 5*min reported unless min is really small, in which case round
// up as we're only trying to catch badly behaved ones
if ( ps != null ){
boolean good_ping = rtt < 5 * Math.max( min_rtt, 75 );
ps.pingReceived( rtt, good_ping );
if ( !good_ping ){
rtt = -1;
}
}
if ( rtt != -1 ){
ping_total += rtt;
ping_count++;
}
}
if ( ping_count == 0 ){
// all failed
return;
}
int ping_average = ping_total/ping_count;
int running_average = (int)ping_average_history.update( ping_average );
if ( ping_average > max_ping ){
max_ping = ping_average;
}
int up_average = (int)upload_average.getAverage();
// if we're uploading slowly or the current ping rate is better than our current idle average
// then we count this towards establishing the baseline
if ( up_average <= IDLE_UPLOAD_SPEED || ( running_average < idle_average && !idle_average_set )){
idle_ticks++;
if ( idle_ticks >= PING_AVERAGE_HISTORY_COUNT ){
idle_average = Math.max( running_average, MIN_IDLE_AVERAGE );
log( "New idle average: " + idle_average );
idle_average_set = true;
}
}else{
if ( up_average > max_upload_average ){
max_upload_average = up_average;
log( "New max upload:" + max_upload_average );
}
idle_ticks = 0;
}
if ( idle_average_set && running_average < idle_average ){
// bump down if we happen to come across lower idle values
idle_average = Math.max( running_average, MIN_IDLE_AVERAGE );
}
int current_speed = adapter.getCurrentDataUploadSpeed() + adapter.getCurrentProtocolUploadSpeed();
int current_limit = adapter.getCurrentUploadLimit();
int new_limit = current_limit;
log(
"Pings: " + str + ", average=" + ping_average +", running_average=" + running_average +
",idle_average=" + idle_average + ", speed=" + current_speed + ",limit=" + current_limit +
",choke = " + (int)choke_speed_average.getAverage());
if ( mode == MODE_FORCED_MAX ){
if ( mode_ticks > FORCED_MAX_TICKS ){
mode = MODE_RUNNING;
current_limit = new_limit = saved_limit;
}
}else if ( mode == MODE_FORCED_MIN ){
if ( idle_average_set || mode_ticks > FORCED_MIN_TICKS ){
log( "Mode -> running" );
if ( !idle_average_set ){
idle_average = Math.max( running_average, MIN_IDLE_AVERAGE );
idle_average_set = true;
}
mode = MODE_RUNNING;
mode_ticks = 0;
current_limit = new_limit = saved_limit;
}else if ( mode_ticks == 5 ){
// we've had 5 secs of min up speed, clear out the ping average now
// to get accurate times
ping_average_history.reset();
}
}
if ( mode == MODE_RUNNING ){
if ( ( ticks > FORCED_MIN_AT_START_TICK_LIMIT && !idle_average_set ) ||
( replacement_contacts >= 2 && idle_average_set )){
// we've been running a while but no min set, or we've got some new untested
// contacts - force it
log( "Mode -> forced min" );
mode = MODE_FORCED_MIN;
mode_ticks = 0;
saved_limit = current_limit;
idle_average_set = false;
idle_ticks = 0;
replacement_contacts= 0;
new_limit = FORCED_MIN_SPEED;
}else{
int short_up = (int)upload_short_average.getAverage();
int choke_speed = (int)choke_speed_average.getAverage();
int choke_time = PING_CHOKE_TIME;
int latency_factor = LATENCY_FACTOR;
if ( running_average < 2* idle_average && ping_average < choke_time ){
direction = INCREASING;
int diff = running_average - idle_average;
if ( diff < 100 ){
diff = 100;
}
int increment = 1024 * ( diff / latency_factor );
// if we're close to the last choke-speed then decrease increments
int max_inc = MAX_INCREMENT;
if ( new_limit + 2*1024 > choke_speed ){
max_inc = 1024;
}else if ( new_limit + 5*1024 > choke_speed ){
max_inc += 3*1024;
}
new_limit += Math.min( increment, max_inc );
}else if ( ping_average > 4*idle_average || ping_average > choke_time ){
if ( direction == INCREASING ){
if ( idle_average_set ){
choke_speed_average.update( short_up );
}
}
direction = DECREASING;
int decrement = 1024 * (( ping_average - (3*idle_average )) / latency_factor );
new_limit -= Math.min( decrement, MAX_DECREMENT );
// don't drop below the current protocol upload speed. This is to address
// the situation whereby it is downloading that is choking the line - killing
// protocol upspeed kills the downspeed
if ( new_limit < upload_short_prot_average.getAverage() + 1024 ){
new_limit = (int)upload_short_prot_average.getAverage() + 1024;
}
}
if ( new_limit < 1024 ){
new_limit = 1024;
}
}
// final tidy up
int min_up = MIN_UP;
int max_up = MAX_UP;
if ( min_up > 0 && new_limit < min_up && mode != MODE_FORCED_MIN ){
new_limit = min_up;
}else if ( max_up > 0 && new_limit > max_up && mode != MODE_FORCED_MAX ){
new_limit = max_up;
}
// if we're not achieving the current limit and the advice is to increase it, don't
// bother
if ( new_limit > current_limit && current_speed < ( current_limit - 10*1024 )){
new_limit = current_limit;
}
}
// round limit up to nearest K
new_limit = (( new_limit + 1023 )/1024) * 1024;
adapter.setCurrentUploadLimit( new_limit );
if ( ADJUST_DOWNLOAD_ENABLE && !( Float.isInfinite( ADJUST_DOWNLOAD_RATIO ) || Float.isNaN( ADJUST_DOWNLOAD_RATIO ))){
int dl_limit = (int)(new_limit * ADJUST_DOWNLOAD_RATIO);
adapter.setCurrentDownloadLimit( dl_limit );
}
|
public void | destroy()
|
public boolean | getAdjustsDownloadLimits()
return( ADJUST_DOWNLOAD_ENABLE );
|
public int | getCurrentChokeSpeed()Returns the current view of when choking occurs
return((int)choke_speed_average.getAverage());
|
public int | getCurrentPingMillis()
return( (int)ping_average_history.getAverage());
|
public int | getIdlePingMillis()
return( idle_average );
|
public int | getMaxPingMillis()
return( max_ping );
|
public int | getMaxUploadSpeed()
return( max_upload_average );
|
protected void | log(java.lang.String str)
adapter.log( str );
|
public void | pingSourceFailed(com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource source)
synchronized( ping_sources ){
ping_sources.remove( source );
}
|
public void | pingSourceFound(com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource source, boolean is_replacement)
if ( is_replacement ){
replacement_contacts++;
}
synchronized( ping_sources ){
ping_sources.put( source, new pingSource( source ));
}
|
public void | reset()
ticks = 0;
mode = MODE_RUNNING;
mode_ticks = 0;
idle_ticks = 0;
idle_average = INITIAL_IDLE_AVERAGE;
idle_average_set = false;
max_upload_average = 0;
direction = INCREASING;
max_ping = 0;
replacement_contacts = 0;
ping_sources = new HashMap();
choke_speed_average.reset();
upload_average.reset();
upload_short_average.reset();
upload_short_prot_average.reset();
ping_average_history.reset();
|
public void | updateStats()
int current_protocol_speed = adapter.getCurrentProtocolUploadSpeed();
int current_data_speed = adapter.getCurrentDataUploadSpeed();
int current_speed = current_protocol_speed + current_data_speed;
upload_average.update( current_speed );
upload_short_average.update( current_speed );
upload_short_prot_average.update( current_protocol_speed );
mode_ticks++;
ticks++;
|