Changeset 7949


Ignore:
Timestamp:
Feb 25, 2009, 10:15:19 PM (13 years ago)
Author:
charles
Message:

(1.5x libT) backport #1829: High CPU use in refillPulse()

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/1.5x/libtransmission/peer-mgr.c

    r7875 r7949  
    5353    BANDWIDTH_PERIOD_MSEC = 500,
    5454
     55    /* how frequently to age out old piece request lists */
     56    REFILL_UPKEEP_PERIOD_MSEC = 10000,
     57
    5558    /* how frequently to decide which peers live and die */
    5659    RECONNECT_PERIOD_MSEC = 500,
     
    7174    /* number of bad pieces a peer is allowed to send before we ban them */
    7275    MAX_BAD_PIECES_PER_PEER = 5,
     76
     77    /* amount of time to keep a list of request pieces lying around
     78       before it's considered too old and needs to be rebuilt */
     79    PIECE_LIST_SHELF_LIFE_SECS = 60,
    7380
    7481    /* use for bitwise operations w/peer_atom.myflags */
     
    118125};
    119126
     127struct tr_blockIterator
     128{
     129    time_t expirationDate;
     130    struct tr_torrent_peers * t;
     131    tr_block_index_t blockIndex, blockCount, *blocks;
     132    tr_piece_index_t pieceIndex, pieceCount, *pieces;
     133};
     134
    120135typedef struct tr_torrent_peers
    121136{
    122     tr_bool         isRunning;
    123 
    124     uint8_t         hash[SHA_DIGEST_LENGTH];
    125     int         *   pendingRequestCount;
    126     tr_ptrArray     outgoingHandshakes; /* tr_handshake */
    127     tr_ptrArray     pool; /* struct peer_atom */
    128     tr_ptrArray     peers; /* tr_peer */
    129     tr_ptrArray     webseeds; /* tr_webseed */
    130     tr_timer *      refillTimer;
    131     tr_torrent *    tor;
    132     tr_peer *       optimistic; /* the optimistic peer, or NULL if none */
    133 
    134     struct tr_peerMgr * manager;
     137    tr_bool                    isRunning;
     138
     139    uint8_t                    hash[SHA_DIGEST_LENGTH];
     140    int                      * pendingRequestCount;
     141    tr_ptrArray                outgoingHandshakes; /* tr_handshake */
     142    tr_ptrArray                pool; /* struct peer_atom */
     143    tr_ptrArray                peers; /* tr_peer */
     144    tr_ptrArray                webseeds; /* tr_webseed */
     145    tr_timer                 * refillTimer;
     146    tr_torrent               * tor;
     147    tr_peer                  * optimistic; /* the optimistic peer, or NULL if none */
     148    struct tr_blockIterator  * refillQueue; /* used in refillPulse() */
     149
     150    struct tr_peerMgr        * manager;
    135151}
    136152Torrent;
     
    143159    tr_timer        * rechokeTimer;
    144160    tr_timer        * reconnectTimer;
     161    tr_timer        * refillUpkeepTimer;
    145162};
    146163
     
    368385}
    369386
     387static void blockIteratorFree( struct tr_blockIterator ** inout );
     388
    370389static void
    371390torrentDestructor( void * vt )
     
    384403    tr_timerFree( &t->refillTimer );
    385404
     405    blockIteratorFree( &t->refillQueue );
    386406    tr_ptrArrayDestruct( &t->webseeds, (PtrArrayForeachFunc)tr_webseedFree );
    387407    tr_ptrArrayDestruct( &t->pool, (PtrArrayForeachFunc)tr_free );
     
    427447static int rechokePulse   ( void * vmgr );
    428448static int reconnectPulse ( void * vmgr );
     449static int refillUpkeep   ( void * vmgr );
    429450
    430451tr_peerMgr*
     
    435456    m->session = session;
    436457    m->incomingHandshakes = TR_PTR_ARRAY_INIT;
    437     m->bandwidthTimer = tr_timerNew( session, bandwidthPulse, m, BANDWIDTH_PERIOD_MSEC );
    438     m->rechokeTimer   = tr_timerNew( session, rechokePulse,   m, RECHOKE_PERIOD_MSEC );
    439     m->reconnectTimer = tr_timerNew( session, reconnectPulse, m, RECONNECT_PERIOD_MSEC );
     458    m->bandwidthTimer    = tr_timerNew( session, bandwidthPulse, m, BANDWIDTH_PERIOD_MSEC );
     459    m->rechokeTimer      = tr_timerNew( session, rechokePulse,   m, RECHOKE_PERIOD_MSEC );
     460    m->reconnectTimer    = tr_timerNew( session, reconnectPulse, m, RECONNECT_PERIOD_MSEC );
     461    m->refillUpkeepTimer = tr_timerNew( session, refillUpkeep,   m, REFILL_UPKEEP_PERIOD_MSEC );
    440462
    441463    rechokePulse( m );
     
    449471    managerLock( manager );
    450472
     473    tr_timerFree( &manager->refillUpkeepTimer );
    451474    tr_timerFree( &manager->reconnectTimer );
    452475    tr_timerFree( &manager->rechokeTimer );
     
    639662}
    640663
    641 struct tr_blockIterator
    642 {
    643     Torrent * t;
    644     tr_block_index_t blockIndex, blockCount, *blocks;
    645     tr_piece_index_t pieceIndex, pieceCount, *pieces;
    646 };
    647 
    648664static struct tr_blockIterator*
    649665blockIteratorNew( Torrent * t )
    650666{
    651667    struct tr_blockIterator * i = tr_new0( struct tr_blockIterator, 1 );
     668    i->expirationDate = time( NULL ) + PIECE_LIST_SHELF_LIFE_SECS;
    652669    i->t = t;
    653670    i->pieces = getPreferredPieces( t, &i->pieceCount );
    654671    i->blocks = tr_new0( tr_block_index_t, t->tor->blockCountInPiece );
     672    tordbg( t, "creating new refill queue.. it contains %"PRIu32" pieces", i->pieceCount );
    655673    return i;
    656674}
    657675
    658 static int
     676static tr_bool
    659677blockIteratorNext( struct tr_blockIterator * i, tr_block_index_t * setme )
    660678{
    661     int found;
     679    tr_bool found;
    662680    Torrent * t = i->t;
    663681    tr_torrent * tor = t->tor;
     
    689707
    690708static void
    691 blockIteratorFree( struct tr_blockIterator * i )
    692 {
    693     tr_free( i->blocks );
    694     tr_free( i->pieces );
    695     tr_free( i );
     709blockIteratorSkipCurrentPiece( struct tr_blockIterator * i )
     710{
     711    i->blockIndex = i->blockCount;
     712}
     713
     714static void
     715blockIteratorFree( struct tr_blockIterator ** inout )
     716{
     717    struct tr_blockIterator * it = *inout;
     718
     719    if( it != NULL )
     720    {
     721        tr_free( it->blocks );
     722        tr_free( it->pieces );
     723        tr_free( it );
     724    }
     725
     726    *inout = NULL;
    696727}
    697728
     
    736767
    737768static int
     769refillUpkeep( void * vmgr )
     770{
     771    tr_torrent * tor = NULL;
     772    tr_peerMgr * mgr = vmgr;
     773    time_t now;
     774    managerLock( mgr );
     775
     776    now = time( NULL );
     777    while(( tor = tr_torrentNext( mgr->session, tor ))) {
     778        Torrent * t = tor->torrentPeers;
     779        if( t && t->refillQueue && ( t->refillQueue->expirationDate <= now ) ) {
     780            tordbg( t, "refill queue is past its shelf date; discarding." );
     781            blockIteratorFree( &t->refillQueue );
     782        }
     783    }
     784
     785    managerUnlock( mgr );
     786    return TRUE;
     787}
     788
     789static int
    738790refillPulse( void * vtorrent )
    739791{
     
    743795    tr_peer ** peers;
    744796    tr_webseed ** webseeds;
    745     struct tr_blockIterator * blockIterator;
    746797    Torrent * t = vtorrent;
    747798    tr_torrent * tor = t->tor;
     799    tr_bool hasNext = TRUE;
    748800
    749801    if( !t->isRunning )
     
    755807    tordbg( t, "Refilling Request Buffers..." );
    756808
    757     blockIterator = blockIteratorNew( t );
     809    if( t->refillQueue == NULL )
     810        t->refillQueue = blockIteratorNew( t );
     811
    758812    peers = getPeersUploadingToClient( t, &peerCount );
    759813    webseedCount = tr_ptrArraySize( &t->webseeds );
     
    762816
    763817    while( ( webseedCount || peerCount )
    764         && blockIteratorNext( blockIterator, &block ) )
     818        && (( hasNext = blockIteratorNext( t->refillQueue, &block ))) )
    765819    {
    766820        int j;
    767         int handled = FALSE;
     821        tr_bool handled = FALSE;
    768822
    769823        const tr_piece_index_t index = tr_torBlockPiece( tor, block );
    770824        const uint32_t offset = getBlockOffsetInPiece( tor, block );
    771825        const uint32_t length = tr_torBlockCountBytes( tor, block );
     826
     827        assert( block < tor->blockCount );
    772828
    773829        /* find a peer who can ask for this block */
     
    818874            }
    819875        }
     876
     877        if( !handled )
     878            blockIteratorSkipCurrentPiece( t->refillQueue );
    820879    }
    821880
    822881    /* cleanup */
    823     blockIteratorFree( blockIterator );
    824882    tr_free( webseeds );
    825883    tr_free( peers );
     884
     885    if( !hasNext ) {
     886        tordbg( t, "refill queue has no more blocks to request... freeing (webseed count: %d, peer count: %d)", webseedCount, peerCount );
     887        blockIteratorFree( &t->refillQueue );
     888    }
    826889
    827890    t->refillTimer = NULL;
Note: See TracChangeset for help on using the changeset viewer.