2007-03-08 zzz

* i2psnark changes to improve upload performance:
    *  Implement total uploader limit (10)
    *  Don't timeout non-piece messages out
    *  Change chunk size to 32K (was 64K)
    *  Change request limit to 64K (was 256K)
    * i2psnark: Disconnect from seeds when complete
This commit is contained in:
zzz
2007-03-08 18:55:17 +00:00
committed by zzz
parent 0aa0cd330f
commit 8e2849b7e5
8 changed files with 109 additions and 21 deletions

View File

@ -507,6 +507,21 @@ public class Peer implements Comparable
return count;
}
/**
* Return if a peer is a seeder
* Quite inefficient - a byte lookup table or counter in Bitfield would be much better
*/
public boolean isCompleted()
{
PeerState s = state;
if (s == null || s.bitfield == null)
return false;
for (int i = 0; i < s.bitfield.size(); i++)
if (!s.bitfield.get(i))
return false;
return true;
}
/**
* Push the total uploaded/downloaded onto a RATE_DEPTH deep stack
*/

View File

@ -41,6 +41,17 @@ class PeerCheckerTask extends TimerTask
{
synchronized(coordinator.peers)
{
Iterator it = coordinator.peers.iterator();
if ((!it.hasNext()) || coordinator.halted()) {
coordinator.peerCount = 0;
coordinator.interestedAndChoking = 0;
coordinator.setRateHistory(0, 0);
coordinator.uploaders = 0;
if (coordinator.halted())
cancel();
return;
}
// Calculate total uploading and worst downloader.
long worstdownload = Long.MAX_VALUE;
Peer worstDownloader = null;
@ -56,8 +67,7 @@ class PeerCheckerTask extends TimerTask
// Keep track of peers we remove now,
// we will add them back to the end of the list.
List removed = new ArrayList();
Iterator it = coordinator.peers.iterator();
int uploadLimit = coordinator.allowedUploaders();
while (it.hasNext())
{
Peer peer = (Peer)it.next();
@ -100,8 +110,9 @@ class PeerCheckerTask extends TimerTask
// If we are at our max uploaders and we have lots of other
// interested peers try to make some room.
// (Note use of coordinator.uploaders)
if (coordinator.uploaders >= PeerCoordinator.MAX_UPLOADERS
&& coordinator.interestedAndChoking > 0
if (((coordinator.uploaders == uploadLimit
&& coordinator.interestedAndChoking > 0)
|| coordinator.uploaders > uploadLimit)
&& !peer.isChoking())
{
// Check if it still wants pieces from us.
@ -186,8 +197,9 @@ class PeerCheckerTask extends TimerTask
coordinator.uploaders = uploaders;
// Remove the worst downloader if needed. (uploader if seeding)
if (uploaders >= PeerCoordinator.MAX_UPLOADERS
&& coordinator.interestedAndChoking > 0
if (((uploaders == uploadLimit
&& coordinator.interestedAndChoking > 0)
|| uploaders > uploadLimit)
&& worstDownloader != null)
{
if (Snark.debug >= Snark.DEBUG)
@ -216,8 +228,5 @@ class PeerCheckerTask extends TimerTask
coordinator.setRateHistory(uploaded, downloaded);
}
if (coordinator.halted()) {
cancel();
}
}
}

View File

@ -208,10 +208,12 @@ class PeerConnectionOut implements Runnable
/**
* Adds a message to the sendQueue and notifies the method waiting
* on the sendQueue to change.
* If a PIECE message only, add a timeout.
*/
private void addMessage(Message m)
{
SimpleTimer.getInstance().addEvent(new RemoveTooSlow(m), SEND_TIMEOUT);
if (m.type == Message.PIECE)
SimpleTimer.getInstance().addEvent(new RemoveTooSlow(m), SEND_TIMEOUT);
synchronized(sendQueue)
{
sendQueue.add(m);

View File

@ -170,7 +170,7 @@ public class PeerCoordinator implements PeerListener
setRate(down, downloaded_old);
}
private void setRate(long val, long array[])
private static void setRate(long val, long array[])
{
synchronized(array) {
for (int i = RATE_DEPTH-1; i > 0; i--)
@ -352,6 +352,7 @@ public class PeerCoordinator implements PeerListener
synchronized (peers) {
int count = 0;
int unchokedCount = 0;
int maxUploaders = allowedUploaders();
Iterator it = peers.iterator();
while (it.hasNext())
{
@ -360,7 +361,7 @@ public class PeerCoordinator implements PeerListener
if (peer.isChoking() && peer.isInterested())
{
count++;
if (uploaders < MAX_UPLOADERS)
if (uploaders < maxUploaders)
{
if (!peer.isChoked())
interested.add(unchokedCount++, peer);
@ -370,7 +371,7 @@ public class PeerCoordinator implements PeerListener
}
}
while (uploaders < MAX_UPLOADERS && interested.size() > 0)
while (uploaders < maxUploaders && interested.size() > 0)
{
Peer peer = (Peer)interested.remove(0);
if (_log.shouldLog(Log.DEBUG))
@ -586,14 +587,27 @@ public class PeerCoordinator implements PeerListener
}
// Announce to the world we have it!
// Disconnect from other seeders when we get the last piece
synchronized(peers)
{
List toDisconnect = new ArrayList();
Iterator it = peers.iterator();
while (it.hasNext())
{
Peer p = (Peer)it.next();
if (p.isConnected())
p.have(piece);
{
if (completed() && p.isCompleted())
toDisconnect.add(p);
else
p.have(piece);
}
}
it = toDisconnect.iterator();
while (it.hasNext())
{
Peer p = (Peer)it.next();
p.disconnect(true);
}
}
@ -615,7 +629,7 @@ public class PeerCoordinator implements PeerListener
{
synchronized(peers)
{
if (uploaders < MAX_UPLOADERS)
if (uploaders < allowedUploaders())
{
if(peer.isChoking())
{
@ -783,5 +797,20 @@ public class PeerCoordinator implements PeerListener
for (int i = 0; arr[i] >= 0; i++)
markUnrequestedIfOnlyOne(peer, arr[i]);
}
/** Return number of allowed uploaders for this torrent.
** Check with Snark to see if we are over the total upload limit.
*/
public int allowedUploaders()
{
if (Snark.overUploadLimit(uploaders)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Over limit, uploaders was: " + uploaders);
return uploaders - 1;
} else if (uploaders < MAX_UPLOADERS)
return uploaders + 1;
else
return MAX_UPLOADERS;
}
}

View File

@ -63,7 +63,8 @@ class PeerState
private boolean resend = false;
private final static int MAX_PIPELINE = 2;
private final static int PARTSIZE = 64*1024; // default was 16K, i2p-bt uses 64KB
private final static int PARTSIZE = 32*1024; // Snark was 16K, i2p-bt uses 64KB
private final static int MAX_PARTSIZE = 64*1024; // Don't let anybody request more than this
PeerState(Peer peer, PeerListener listener, MetaInfo metainfo,
PeerConnectionIn in, PeerConnectionOut out)
@ -173,7 +174,7 @@ class PeerState
|| begin < 0
|| begin > metainfo.getPieceLength(piece)
|| length <= 0
|| length > 4*PARTSIZE)
|| length > MAX_PARTSIZE)
{
// XXX - Protocol error -> disconnect?
if (_log.shouldLog(Log.WARN))

View File

@ -287,7 +287,7 @@ public class Snark
/*
* Don't start a tunnel if the torrent isn't going to be started.
* If we are starting,
* startTorrent() will call trackerclient.start() which will force a connect.
* startTorrent() will force a connect.
*
boolean ok = I2PSnarkUtil.instance().connect();
if (!ok) fatal("Unable to connect to I2P");
@ -368,6 +368,9 @@ public class Snark
activity = "Checking storage";
storage = new Storage(meta, slistener);
storage.check(rootDataDir);
// have to figure out when to reopen
// if (!start)
// storage.close();
}
catch (IOException ioe)
{
@ -751,4 +754,22 @@ public class Snark
public interface CompleteListener {
public void torrentComplete(Snark snark);
}
/** Maintain a total uploader cap
** This should be configurable
*/
private final static int MAX_TOTAL_UPLOADERS = 10;
public static boolean overUploadLimit(int uploaders) {
PeerCoordinatorSet coordinators = PeerCoordinatorSet.instance();
if (coordinators == null || uploaders <= 0)
return false;
int totalUploaders = 0;
for (Iterator iter = coordinators.iterator(); iter.hasNext(); ) {
PeerCoordinator c = (PeerCoordinator)iter.next();
if (!c.halted())
totalUploaders += c.uploaders;
}
Snark.debug("Total uploaders: " + totalUploaders, Snark.DEBUG);
return totalUploaders > MAX_TOTAL_UPLOADERS;
}
}

View File

@ -1,4 +1,15 @@
$Id: history.txt,v 1.555 2007-03-03 15:30:52 zzz Exp $
$Id: history.txt,v 1.556 2007-03-07 00:11:46 zzz Exp $
2007-03-08 zzz
* i2psnark changes to improve upload performance:
* Implement total uploader limit (10)
* Don't timeout non-piece messages out
* Change chunk size to 32K (was 64K)
* Change request limit to 64K (was 256K)
* i2psnark: Disconnect from seeds when complete
2007-03-07 zzz
* Remove dynamic router keys from config.jsp
2007-03-07 zzz
* Streaming lib changes to improve upstream performance during congestion:

View File

@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.491 $ $Date: 2007-03-03 15:30:52 $";
public final static String ID = "$Revision: 1.492 $ $Date: 2007-03-07 00:11:45 $";
public final static String VERSION = "0.6.1.27";
public final static long BUILD = 5;
public final static long BUILD = 6;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);