fix the high CPU load during endgame.
This commit is contained in:
parent
339005346c
commit
e352d56925
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue