Changeset 11892


Ignore:
Timestamp:
Feb 15, 2011, 4:04:56 PM (11 years ago)
Author:
jordan
Message:

(trunk libT) #3656 "endgame could be faster" -- fixed. Patch by harrydb.

Location:
trunk/libtransmission
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/completion.c

    r11797 r11892  
    2828    cp->sizeNow = 0;
    2929    cp->sizeWhenDoneIsDirty = 1;
     30    cp->blocksWantedIsDirty = 1;
    3031    cp->haveValidIsDirty = 1;
    3132}
     
    5556{
    5657    cp->sizeWhenDoneIsDirty = 1;
     58    cp->blocksWantedIsDirty = 1;
     59}
     60
     61tr_block_index_t
     62tr_cpBlocksMissing( const tr_completion * ccp )
     63{
     64    if( ccp->blocksWantedIsDirty )
     65    {
     66        tr_completion *    cp = (tr_completion *) ccp; /* mutable */
     67        const tr_torrent * tor = cp->tor;
     68        const tr_info *    info = &tor->info;
     69        tr_piece_index_t   i;
     70        tr_block_index_t   wanted = 0;
     71        tr_block_index_t   complete = 0;
     72
     73        for( i = 0; i < info->pieceCount; ++i )
     74        {
     75            if( info->pieces[i].dnd )
     76                continue;
     77
     78            wanted += tr_torPieceCountBlocks( tor, i );
     79            complete += cp->completeBlocks[i];
     80        }
     81
     82        cp->blocksWantedLazy = wanted;
     83        cp->blocksWantedCompleteLazy = complete;
     84        cp->blocksWantedIsDirty = FALSE;
     85    }
     86
     87    return ccp->blocksWantedLazy - ccp->blocksWantedCompleteLazy;
    5788}
    5889
     
    133164            cp->sizeNow -= tr_torBlockCountBytes( tor, block );
    134165
     166    if( !tor->info.pieces[piece].dnd )
     167        cp->blocksWantedCompleteLazy -= cp->completeBlocks[piece];
     168
    135169    cp->sizeWhenDoneIsDirty = 1;
    136170    cp->haveValidIsDirty = 1;
     
    159193
    160194        cp->sizeNow += blockSize;
     195        if( !tor->info.pieces[piece].dnd )
     196            cp->blocksWantedCompleteLazy++;
    161197
    162198        cp->haveValidIsDirty = 1;
     
    180216        cp->completeBlocks[i] = tr_torPieceCountBlocks( tor, i );
    181217    cp->sizeWhenDoneIsDirty = 1;
     218    cp->blocksWantedIsDirty = 1;
    182219    cp->haveValidIsDirty = 1;
    183220}
     
    211248        /* invalidate the fields that are lazy-evaluated */
    212249        cp->sizeWhenDoneIsDirty = TRUE;
     250        cp->blocksWantedIsDirty = TRUE;
    213251        cp->haveValidIsDirty = TRUE;
    214252
  • trunk/libtransmission/completion.h

    r11709 r11892  
    2626{
    2727    tr_bool  sizeWhenDoneIsDirty;
     28    tr_bool  blocksWantedIsDirty;
    2829    tr_bool  haveValidIsDirty;
    2930
     
    3839    /* a block is complete if and only if we have it */
    3940    uint16_t *  completeBlocks;
     41
     42    /* total number of blocks that we want downloaded
     43       DON'T access this directly; it's a lazy field.
     44       Used by tr_cpBlocksMissing(). */
     45    tr_block_index_t    blocksWantedLazy;
     46
     47    /* total number of completed blocks that we want downloaded
     48       DON'T access this directly; it's a lazy field.
     49       Used by tr_cpBlocksMissing(). */
     50    tr_block_index_t    blocksWantedCompleteLazy;
    4051
    4152    /* number of bytes we'll have when done downloading. [0..info.totalSize]
     
    6980
    7081uint64_t                   tr_cpHaveValid( const tr_completion * );
     82
     83tr_block_index_t           tr_cpBlocksMissing( const tr_completion * );
    7184
    7285uint64_t                   tr_cpSizeWhenDone( const tr_completion * );
  • trunk/libtransmission/peer-mgr.c

    r11881 r11892  
    205205    int                        maxPeers;
    206206    time_t                     lastCancel;
     207
     208    /* Before the endgame this should be 0. In endgame, is contains the average
     209     * number of pending requests per peer. Only peers which have more pending
     210     * requests are considered 'fast' are allowed to request a block that's
     211     * already been requested from another (slower?) peer. */
     212    int                        endgame;
    207213}
    208214Torrent;
     
    721727}
    722728
    723 /* how many peers are we currently requesting this block from... */
    724 static int
    725 countBlockRequests( Torrent * t, tr_block_index_t block )
     729/**
     730 * Find the peers are we currently requesting the block
     731 * with index @a block from and append them to @a peerArr.
     732 */
     733static void
     734getBlockRequestPeers( Torrent * t, tr_block_index_t block,
     735                      tr_ptrArray * peerArr )
    726736{
    727737    tr_bool exact;
    728     int i, n, pos;
     738    int i, pos;
    729739    struct block_request key;
    730740
     
    737747    assert( !exact ); /* shouldn't have a request with .peer == NULL */
    738748
    739     n = 0;
    740     for( i=pos; i<t->requestCount; ++i ) {
    741         if( t->requests[i].block == block )
    742             ++n;
    743         else
     749    for( i = pos; i < t->requestCount; ++i )
     750    {
     751        if( t->requests[i].block != block )
    744752            break;
    745     }
    746 
    747     return n;
     753        tr_ptrArrayAppend( peerArr, t->requests[i].peer );
     754    }
    748755}
    749756
     
    849856}
    850857
    851 static tr_bool
    852 isInEndgame( Torrent * t )
    853 {
    854     tr_bool endgame = FALSE;
    855 
    856     if( ( t->pieces != NULL ) && ( t->pieceCount > 0 ) )
    857     {
    858         const struct weighted_piece * p = t->pieces;
    859         const int pending = p->requestCount;
    860         const int missing = tr_cpMissingBlocksInPiece( &t->tor->completion, p->index );
    861         endgame = pending >= missing;
    862     }
    863 
    864     /*if( endgame ) fprintf( stderr, "ENDGAME reached\n" );*/
    865     return endgame;
     858static int
     859countActiveWebseeds( const Torrent * t )
     860{
     861    int activeCount = 0;
     862    const tr_webseed ** w = (const tr_webseed **) tr_ptrArrayBase( &t->webseeds );
     863    const tr_webseed ** const wend = w + tr_ptrArraySize( &t->webseeds );
     864
     865    for( ; w!=wend; ++w )
     866        if( tr_webseedIsActive( *w ) )
     867            ++activeCount;
     868
     869    return activeCount;
     870}
     871
     872static void
     873updateEndgame( Torrent * t )
     874{
     875    const tr_torrent * tor = t->tor;
     876    const tr_block_index_t missing = tr_cpBlocksMissing( &tor->completion );
     877
     878    assert( t->requestCount >= 0 );
     879
     880    if( (tr_block_index_t) t->requestCount < missing )
     881    {
     882        /* not in endgame */
     883        t->endgame = 0;
     884    }
     885    else if( !t->endgame ) /* only recalculate when endgame first begins */
     886    {
     887        int numDownloading = 0;
     888        const tr_peer ** p = (const tr_peer **) tr_ptrArrayBase( &t->peers );
     889        const tr_peer ** const pend = p + tr_ptrArraySize( &t->peers );
     890
     891        /* add the active bittorrent peers... */
     892        for( ; p!=pend; ++p )
     893            if( (*p)->pendingReqsToPeer > 0 )
     894                ++numDownloading;
     895
     896        /* add the active webseeds... */
     897        numDownloading += countActiveWebseeds( t );
     898
     899        /* average number of pending requests per downloading peer */
     900        t->endgame = t->requestCount / MAX( numDownloading, 1 );
     901    }
    866902}
    867903
     
    875911assertWeightedPiecesAreSorted( Torrent * t )
    876912{
    877     if( !isInEndgame( t ) )
     913    if( !t->endgame )
    878914    {
    879915        int i;
     
    10691105    int got;
    10701106    Torrent * t;
    1071     tr_bool endgame;
    10721107    struct weighted_piece * pieces;
    10731108    const tr_bitset * have = &peer->have;
     
    10881123        pieceListRebuild( t );
    10891124
    1090     endgame = isInEndgame( t );
    1091 
     1125    updateEndgame( t );
    10921126    pieces = t->pieces;
    10931127    for( i=0; i<t->pieceCount && got<numwant; ++i )
    10941128    {
    10951129        struct weighted_piece * p = pieces + i;
    1096         const int missing = tr_cpMissingBlocksInPiece( &tor->completion, p->index );
    1097         const int maxDuplicatesPerBlock = endgame ? 3 : 1;
    1098 
    1099         if( p->requestCount > ( missing * maxDuplicatesPerBlock ) )
    1100             continue;
    11011130
    11021131        /* if the peer has this piece that we want... */
     
    11051134            tr_block_index_t b = tr_torPieceFirstBlock( tor, p->index );
    11061135            const tr_block_index_t e = b + tr_torPieceCountBlocks( tor, p->index );
     1136            tr_ptrArray peerArr = TR_PTR_ARRAY_INIT;
    11071137
    11081138            for( ; b!=e && got<numwant; ++b )
    11091139            {
     1140                int peerCount;
     1141                tr_peer ** peers;
     1142
    11101143                /* don't request blocks we've already got */
    11111144                if( tr_cpBlockIsCompleteFast( &tor->completion, b ) )
    11121145                    continue;
    11131146
    1114                 /* don't send the same request to the same peer twice */
    1115                 if( tr_peerMgrDidPeerRequest( tor, peer, b ) )
    1116                     continue;
    1117 
    1118                 /* don't send the same request to any peer too many times */
    1119                 if( countBlockRequests( t, b ) >= maxDuplicatesPerBlock )
    1120                     continue;
     1147                /* always add peer if this block has no peers yet */
     1148                tr_ptrArrayClear( &peerArr );
     1149                getBlockRequestPeers( t, b, &peerArr );
     1150                peers = (tr_peer **) tr_ptrArrayPeek( &peerArr, &peerCount );
     1151                if( peerCount != 0 )
     1152                {
     1153                    /* don't make a second block request until the endgame */
     1154                    if( !t->endgame )
     1155                        continue;
     1156
     1157                    /* don't have more than two peers requesting this block */
     1158                    if( peerCount > 1 )
     1159                        continue;
     1160
     1161                    /* don't send the same request to the same peer twice */
     1162                    if( peer == peers[0] )
     1163                        continue;
     1164
     1165                    /* in the endgame allow an additional peer to download a
     1166                       block but only if the peer seems to be handling requests
     1167                       relatively fast */
     1168                    if( peer->pendingReqsToPeer + numwant - got < t->endgame )
     1169                        continue;
     1170                }
    11211171
    11221172                /* update the caller's table */
     
    11271177                ++p->requestCount;
    11281178            }
     1179
     1180            tr_ptrArrayDestruct( &peerArr, NULL );
    11291181        }
    11301182    }
     
    14311483            tr_torrent * tor = t->tor;
    14321484            tr_block_index_t block = _tr_block( tor, e->pieceIndex, e->offset );
    1433 
    1434             requestListRemove( t, block, peer );
    1435             pieceListRemoveRequest( t, block );
     1485            int i, peerCount;
     1486            tr_peer ** peers;
     1487            tr_ptrArray peerArr = TR_PTR_ARRAY_INIT;
     1488
     1489            removeRequestFromTables( t, block, peer );
     1490            getBlockRequestPeers( t, block, &peerArr );
     1491            peers = (tr_peer **) tr_ptrArrayPeek( &peerArr, &peerCount );
     1492
     1493            /* remove additional block requests and send cancel to peers */
     1494            for( i=0; i<peerCount; i++ ) {
     1495                tr_peer * p = peers[i];
     1496                assert( p != peer );
     1497                if( p->msgs ) {
     1498                    tr_historyAdd( p->cancelsSentToPeer, tr_time( ), 1 );
     1499                    tr_peerMsgsCancel( p->msgs, block );
     1500                }
     1501                removeRequestFromTables( t, block, p );
     1502            }
     1503
     1504            tr_ptrArrayDestruct( &peerArr, FALSE );
    14361505
    14371506            if( peer && peer->blocksSentToClient )
     
    21892258    const Torrent * t = tor->torrentPeers;
    21902259    const tr_peer ** peers;
    2191     const tr_webseed ** webseeds;
    21922260
    21932261    assert( tr_torrentIsLocked( tor ) );
     
    22282296    }
    22292297
    2230     webseeds = (const tr_webseed**) tr_ptrArrayBase( &t->webseeds );
    2231     size = tr_ptrArraySize( &t->webseeds );
    2232     for( i=0; i<size; ++i )
    2233         if( tr_webseedIsActive( webseeds[i] ) )
    2234             ++*setmeWebseedsSendingToUs;
     2298    *setmeWebseedsSendingToUs = countActiveWebseeds( t );
    22352299}
    22362300
Note: See TracChangeset for help on using the changeset viewer.