fix the high CPU load during endgame.

This commit is contained in:
Charles Kerr 2007-07-24 18:59:37 +00:00
parent 339005346c
commit e352d56925
2 changed files with 64 additions and 36 deletions

View File

@ -645,34 +645,63 @@ writeEnd:
&& !peer->banned && !peer->banned
&& peer->inRequestCount < peer->inRequestMax ) && peer->inRequestCount < peer->inRequestMax )
{ {
int i;
int poolSize = 0; int poolSize = 0;
int * pool = getPreferredPieces ( tor, peer, &poolSize ); int endgame = FALSE;
const int endgame = !poolSize; int openSlots = peer->inRequestMax - peer->inRequestCount;
int * pool = getPreferredPieces ( tor, peer, &poolSize, &endgame );
if( endgame ) /* endgame -- request everything we don't already have */ if( !endgame )
{ {
for( i=0; i<tor->blockCount && peer->inRequestCount<peer->inRequestMax; ++i ) /* pool is sorted from most to least desirable pieces,
so work our way through starting at beginning */
int p;
for( p=0; p<poolSize && openSlots>0; )
{ {
if( !isBlockInteresting( tor, peer, i ) ) const int piece = pool[p];
continue; const int block = tr_cpMissingBlockInPiece ( tor->completion, piece );
if( tr_bitfieldHas( peer->reqfield, i ) ) /* we've already asked them for it */ if( block < 0 )
continue; ++p;
if( !peer->reqfield ) else {
peer->reqfield = tr_bitfieldNew( tor->blockCount ); sendRequest( tor, peer, block );
tr_bitfieldAdd( peer->reqfield, i ); --openSlots;
sendRequest( tor, peer, i ); }
} }
} }
else for( i=0; i<poolSize && peer->inRequestCount<peer->inRequestMax; ) else
{ {
int unused; /* During endgame we remove the constraint of not asking for
const int piece = pool[i]; pieces we've already requested from a different peer.
const int block = tr_cpMissingBlockInPiece ( tor->completion, piece ); So if we follow the non-endgame approach of walking through
[0..poolCount) we'll bog down asking all peers for 1, then
all peers for 2, and so on. Randomize our starting point
into "pool" to reduce such overlap */
int piecesLeft = poolSize;
int p = tr_rand( poolSize );
for( ; openSlots>0 && piecesLeft>0; --piecesLeft, p=(p+1)%poolSize )
{
const int piece = pool[p];
const int firstBlock = tr_pieceStartBlock( piece );
const int n = tr_pieceCountBlocks( piece );
const int end = firstBlock + n;
int block;
for( block=firstBlock; block<end; ++block )
{
/* don't ask for it if we've already got it */
if( tr_cpBlockIsComplete( tor->completion, block ))
continue;
if( block>=0 ) /* don't ask for it twice from the same peer */
sendRequest( tor, peer, block ); if( tr_bitfieldHas( peer->reqfield, block ) )
else ++i; continue;
/* ask peer for the piece */
if( !peer->reqfield )
peer->reqfield = tr_bitfieldNew( tor->blockCount );
tr_bitfieldAdd( peer->reqfield, block );
sendRequest( tor, peer, block );
--openSlots;
}
}
} }
tr_free( pool ); tr_free( pool );

View File

@ -181,19 +181,6 @@ static int isPieceInteresting( const tr_torrent_t * tor,
return 1; return 1;
} }
static int isBlockInteresting( const tr_torrent_t * tor,
const tr_peer_t * peer,
int block )
{
if( tr_cpBlockIsComplete( tor->completion, block )) /* we already have it */
return 0;
if( !isPieceInteresting( tor, peer, tr_blockPiece( block ))) /* is piece interesting? */
return 0;
return 1;
}
/*********************************************************************** /***********************************************************************
* isInteresting * isInteresting
*********************************************************************** ***********************************************************************
@ -263,12 +250,14 @@ int comparePieces (const void * aIn, const void * bIn)
static int* getPreferredPieces( const tr_torrent_t * tor, static int* getPreferredPieces( const tr_torrent_t * tor,
const tr_peer_t * peer, const tr_peer_t * peer,
int * pieceCount ) int * pieceCount,
int * isEndgame )
{ {
const tr_info_t * inf = &tor->info; const tr_info_t * inf = &tor->info;
int i; int i;
int poolSize = 0; int poolSize = 0;
int endgame = FALSE;
int * pool = tr_new( int, inf->pieceCount ); int * pool = tr_new( int, inf->pieceCount );
for( i=0; i<inf->pieceCount; ++i ) for( i=0; i<inf->pieceCount; ++i )
@ -276,14 +265,23 @@ static int* getPreferredPieces( const tr_torrent_t * tor,
if( tr_cpMissingBlocksForPiece( tor->completion, i ) ) if( tr_cpMissingBlocksForPiece( tor->completion, i ) )
pool[poolSize++] = i; pool[poolSize++] = i;
if( !poolSize ) {
endgame = TRUE;
for( i=0; i<inf->pieceCount; ++i )
if( isPieceInteresting( tor, peer, i ) )
pool[poolSize++] = i;
}
#if 0 #if 0
fprintf (stderr, "old pool: "); fprintf (stderr, "old pool: ");
for (i=0; i<15 && i<poolSize; ++i ) fprintf (stderr, "%d, ", pool[i] ); for (i=0; i<15 && i<poolSize; ++i ) fprintf (stderr, "%d, ", pool[i] );
fprintf (stderr, "\n"); fprintf (stderr, "\n");
#endif #endif
/* sort the rest from most interesting to least */ /* sort the rest from most interesting to least...
if( poolSize > 1 ) but not in endgame, because it asks for pieces in a
scattershot manner anyway and doesn't need them sorted */
if( !endgame && ( poolSize > 1 ) )
{ {
PieceCompareData * p = tr_new( PieceCompareData, poolSize ); PieceCompareData * p = tr_new( PieceCompareData, poolSize );
@ -316,6 +314,7 @@ for (i=0; i<15 && i<poolSize; ++i ) fprintf (stderr, "%d, ", pool[i] );
fprintf (stderr, "\n"); fprintf (stderr, "\n");
#endif #endif
*isEndgame = endgame;
*pieceCount = poolSize; *pieceCount = poolSize;
return pool; return pool;
} }