Changeset 7909


Ignore:
Timestamp:
Feb 18, 2009, 5:19:36 PM (13 years ago)
Author:
charles
Message:

(trunk libT) experimental fix for #1829: High CPU use in refillPulse()

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/peer-mgr.c

    r7894 r7909  
    5353    BANDWIDTH_PERIOD_MSEC = 500,
    5454
     55    /* how frequently to age out old piece request lists */
     56    REFILL_UPKEEP_PERIOD_MSEC = 1000,
     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    tordbg( t, "creating new refill queue" );
     669    i->expirationDate = time( NULL ) + PIECE_LIST_SHELF_LIFE_SECS;
    652670    i->t = t;
    653671    i->pieces = getPreferredPieces( t, &i->pieceCount );
     
    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 );
     709blockIteratorFree( struct tr_blockIterator ** inout )
     710{
     711    struct tr_blockIterator * it = *inout;
     712
     713    if( it != NULL )
     714    {
     715        tr_free( it->blocks );
     716        tr_free( it->pieces );
     717        tr_free( it );
     718    }
     719
     720    *inout = NULL;
    696721}
    697722
     
    736761
    737762static int
     763refillUpkeep( void * vmgr )
     764{
     765    tr_torrent * tor = NULL;
     766    tr_peerMgr * mgr = vmgr;
     767    time_t now;
     768    managerLock( mgr );
     769
     770    now = time( NULL );
     771    while(( tor = tr_torrentNext( mgr->session, tor ))) {
     772        Torrent * t = tor->torrentPeers;
     773        if( t && t->refillQueue && ( t->refillQueue->expirationDate <= now ) ) {
     774            tordbg( t, "refill queue is past its shelf date; discarding." );
     775            blockIteratorFree( &t->refillQueue );
     776        }
     777    }
     778
     779    managerUnlock( mgr );
     780    return TRUE;
     781}
     782
     783static int
    738784refillPulse( void * vtorrent )
    739785{
     
    743789    tr_peer ** peers;
    744790    tr_webseed ** webseeds;
    745     struct tr_blockIterator * blockIterator;
    746791    Torrent * t = vtorrent;
    747792    tr_torrent * tor = t->tor;
     793    tr_bool hasNext = TRUE;
    748794
    749795    if( !t->isRunning )
     
    755801    tordbg( t, "Refilling Request Buffers..." );
    756802
    757     blockIterator = blockIteratorNew( t );
     803    if( t->refillQueue == NULL )
     804        t->refillQueue = blockIteratorNew( t );
     805
    758806    peers = getPeersUploadingToClient( t, &peerCount );
    759807    webseedCount = tr_ptrArraySize( &t->webseeds );
     
    762810
    763811    while( ( webseedCount || peerCount )
    764         && blockIteratorNext( blockIterator, &block ) )
     812        && (( hasNext = blockIteratorNext( t->refillQueue, &block ))) )
    765813    {
    766814        int j;
     
    821869
    822870    /* cleanup */
    823     blockIteratorFree( blockIterator );
    824871    tr_free( webseeds );
    825872    tr_free( peers );
     873
     874    /* if we're out of blocks to request, free the request queue */
     875    if( !hasNext )
     876        blockIteratorFree( &t->refillQueue );
    826877
    827878    t->refillTimer = NULL;
Note: See TracChangeset for help on using the changeset viewer.