From 3678aa157e1e2c288ad42a30691f4fee7d538a43 Mon Sep 17 00:00:00 2001 From: zzz Date: Mon, 1 Nov 2010 14:35:01 +0000 Subject: [PATCH] * i2psnark: - Limit number of parallel requests of a single piece when in the end game - Shorten and weight the speed tracker so the display is more reflective of current speed --- .../java/src/org/klomp/snark/Peer.java | 47 ++++++------------ .../src/org/klomp/snark/PeerCoordinator.java | 48 ++++++++++++++----- .../java/src/org/klomp/snark/PeerState.java | 12 +++++ history.txt | 12 +++++ .../src/net/i2p/router/RouterVersion.java | 2 +- 5 files changed, 77 insertions(+), 44 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/Peer.java b/apps/i2psnark/java/src/org/klomp/snark/Peer.java index 0445ab205..55b6dcb2c 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Peer.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Peer.java @@ -56,8 +56,8 @@ public class Peer implements Comparable private long _id; final static long CHECK_PERIOD = PeerCoordinator.CHECK_PERIOD; // 40 seconds final static int RATE_DEPTH = PeerCoordinator.RATE_DEPTH; // make following arrays RATE_DEPTH long - private long uploaded_old[] = {-1,-1,-1,-1,-1,-1}; - private long downloaded_old[] = {-1,-1,-1,-1,-1,-1}; + private long uploaded_old[] = {-1,-1,-1}; + private long downloaded_old[] = {-1,-1,-1}; /** * Creates a disconnected peer given a PeerID, your own id and the @@ -403,6 +403,15 @@ public class Peer implements Comparable s.cancelPiece(piece); } + /** + * Are we currently requesting the piece? + * @since 0.8.1 + */ + boolean isRequesting(int p) { + PeerState s = state; + return s != null && s.isRequesting(p); + } + /** * Update the request queue. * Call after adding wanted pieces. @@ -572,17 +581,8 @@ public class Peer implements Comparable */ public void setRateHistory(long up, long down) { - setRate(up, uploaded_old); - setRate(down, downloaded_old); - } - - private void setRate(long val, long array[]) - { - synchronized(array) { - for (int i = RATE_DEPTH-1; i > 0; i--) - array[i] = array[i-1]; - array[0] = val; - } + PeerCoordinator.setRate(up, uploaded_old); + PeerCoordinator.setRate(down, downloaded_old); } /** @@ -590,28 +590,11 @@ public class Peer implements Comparable */ public long getUploadRate() { - return getRate(uploaded_old); + return PeerCoordinator.getRate(uploaded_old); } public long getDownloadRate() { - return getRate(downloaded_old); + return PeerCoordinator.getRate(downloaded_old); } - - private long getRate(long array[]) - { - long rate = 0; - int i = 0; - synchronized(array) { - for ( ; i < RATE_DEPTH; i++){ - if (array[i] < 0) - break; - rate += array[i]; - } - } - if (i == 0) - return 0; - return rate / (i * CHECK_PERIOD / 1000); - } - } diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java index 0fa74e954..510272459 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java @@ -57,9 +57,9 @@ public class PeerCoordinator implements PeerListener private long uploaded; private long downloaded; - final static int RATE_DEPTH = 6; // make following arrays RATE_DEPTH long - private long uploaded_old[] = {-1,-1,-1,-1,-1,-1}; - private long downloaded_old[] = {-1,-1,-1,-1,-1,-1}; + final static int RATE_DEPTH = 3; // make following arrays RATE_DEPTH long + private long uploaded_old[] = {-1,-1,-1}; + private long downloaded_old[] = {-1,-1,-1}; // synchronize on this when changing peers or downloaders final List peers = new ArrayList(); @@ -193,7 +193,7 @@ public class PeerCoordinator implements PeerListener setRate(down, downloaded_old); } - private static void setRate(long val, long array[]) + static void setRate(long val, long array[]) { synchronized(array) { for (int i = RATE_DEPTH-1; i > 0; i--) @@ -224,20 +224,23 @@ public class PeerCoordinator implements PeerListener return (r * 1000) / CHECK_PERIOD; } - private long getRate(long array[]) + static long getRate(long array[]) { long rate = 0; int i = 0; + int factor = 0; synchronized(array) { for ( ; i < RATE_DEPTH; i++) { if (array[i] < 0) break; - rate += array[i]; + int f = RATE_DEPTH - i; + rate += array[i] * f; + factor += f; } } if (i == 0) return 0; - return rate / (i * CHECK_PERIOD / 1000); + return rate / (factor * i * CHECK_PERIOD / 1000); } public MetaInfo getMetaInfo() @@ -509,6 +512,12 @@ public class PeerCoordinator implements PeerListener */ private static final int END_GAME_THRESHOLD = 8; + /** + * Max number of peers to get a piece from when in end game + * @since 0.8.1 + */ + private static final int MAX_PARALLEL_REQUESTS = 4; + /** * Returns one of pieces in the given BitField that is still wanted or * -1 if none of the given pieces are wanted. @@ -551,15 +560,32 @@ public class PeerCoordinator implements PeerListener if (wantedPieces.size() > END_GAME_THRESHOLD) return -1; // nothing to request and not in end game // let's not all get on the same piece + // Even better would be to sort by number of requests Collections.shuffle(requested, _random); Iterator it2 = requested.iterator(); while (piece == null && it2.hasNext()) { Piece p = it2.next(); - if (havePieces.get(p.getId())) - { + if (havePieces.get(p.getId())) { + // limit number of parallel requests + int requestedCount = 0; + synchronized(peers) { + for (Peer pr : peers) { + if (pr.isRequesting(p.getId())) { + if (pr.equals(peer)) { + // don't give it to him again + requestedCount = MAX_PARALLEL_REQUESTS; + break; + } + if (++requestedCount >= MAX_PARALLEL_REQUESTS) + break; + } + } + } + if (requestedCount >= MAX_PARALLEL_REQUESTS) + continue; piece = p; - } + } } if (piece == null) { if (_log.shouldLog(Log.WARN)) @@ -568,7 +594,7 @@ public class PeerCoordinator implements PeerListener // + " wanted = " + wantedPieces + " peerHas = " + havePieces); return -1; //If we still can't find a piece we want, so be it. } else { - // Should be a lot smarter here - limit # of parallel attempts and + // Should be a lot smarter here - // share blocks rather than starting from 0 with each peer. // This is where the flaws of the snark data model are really exposed. // Could also randomize within the duplicate set rather than strict rarest-first diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java index cadcbf866..4d34736a8 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java @@ -470,6 +470,18 @@ class PeerState } } + /** + * Are we currently requesting the piece? + * @since 0.8.1 + */ + synchronized boolean isRequesting(int piece) { + for (Request req : outstandingRequests) { + if (req.piece == piece) + return true; + } + return false; + } + /** * Starts or resumes requesting pieces. * @param resend should we resend outstanding requests? diff --git a/history.txt b/history.txt index ab77d569f..fcd33d6b4 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,15 @@ +2010-11-01 zzz + * ClientConnectionRunner: Add synch to fix race causing AIOOBE + (http://forum.i2p/viewtopic.php?t=5061) + * configlogging.jsp: Parse log limit with current locale + (ticket #118) + * i2psnark: + - Limit number of parallel requests of a single piece when in the end game + - Shorten and weight the speed tracker so the display is more + reflective of current speed + * logs.jsp: Add message if wrapper log not found + (ticket #103) + 2010-10-30 zzz * i2psnark: - Priority mapping bugfix diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index c10128fe6..fecba78d6 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 6; + public final static long BUILD = 7; /** for example "-test" */ public final static String EXTRA = "";