Changeset 2231


Ignore:
Timestamp:
Jun 29, 2007, 5:45:17 AM (15 years ago)
Author:
charles
Message:

lots of performance improvements. fun!

  • dynamically resize the request queue on a per-peer basis based on its speed
  • fix a huge bug that sabotaged the `swift' performance
  • on startup, unchoke peers much sooner
  • bump MAX_PEERS and PERCENT_PEER_WANTED
  • do a better job of estimating speed on torrents less than 30 seconds old.
  • getting an unrecognized extension ID, ignore it instead of stopping the torrent.
Location:
trunk/libtransmission
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/choking.c

    r2207 r2231  
    201201            else
    202202            {
    203                 if( tr_peerLastChoke( peer ) + 10000 < now )
     203                if( !tr_peerTimesChoked(peer) || tr_peerLastChoke( peer ) + 10000 < now )
    204204                    canUnchoke[canUnchokeCount++] = peer;
    205205            }
  • trunk/libtransmission/peer.c

    r2202 r2231  
    4646 * allow them to download this many bytes from us
    4747 */
    48 static const double SWIFT_REPAYMENT_RATIO = 1.1;
     48static const double SWIFT_REPAYMENT_RATIO = 1.33;
    4949
    5050/**
     
    7171*****/
    7272
    73 #define PERCENT_PEER_WANTED     25      /* Percent before we start relax peers min activeness */
     73#define PERCENT_PEER_WANTED     75      /* Percent before we start relax peers min activeness */
    7474#define MIN_UPLOAD_IDLE         60000   /* In high peer situations we wait only 1 min
    7575                                            until dropping peers for idling */
     
    8484#define MAX_CON_TIMEOUT         30000   /* Time to timeout connecting to peer,
    8585                                            during high peer situations */
    86 #define MAX_REQUEST_COUNT       32
    87 #define OUR_REQUEST_COUNT       12 /* TODO: we should detect if we are on a
    88                                       high-speed network and adapt */
    8986#define PEX_PEER_CUTOFF         50 /* only try to add new peers from pex if
    9087                                      we have fewer existing peers than this */
     
    151148
    152149    int                 optimistic;
     150    int                 timesChoked;
    153151    uint64_t            lastChoke;
    154152
     
    181179
    182180    int                 inRequestCount;
    183     tr_request_t        inRequests[OUR_REQUEST_COUNT];
     181    int                 inRequestMax;
     182    int                 inRequestAlloc;
     183    tr_request_t      * inRequests;
    184184    int                 inIndex;
    185185    int                 inBegin;
     
    188188
    189189    int                 outRequestCount;
    190     tr_request_t        outRequests[MAX_REQUEST_COUNT];
     190    int                 outRequestMax;
     191    int                 outRequestAlloc;
     192    tr_request_t      * outRequests;
    191193    uint64_t            outTotal;
    192194    uint64_t            outDate;
     
    234236    assert( 0 <= from && TR_PEER_FROM__MAX > from );
    235237
     238    peer->outRequestMax = peer->outRequestAlloc = 2;
     239    peer->outRequests = tr_new0( tr_request_t, peer->outRequestAlloc );
     240
     241    peer->inRequestMax = peer->inRequestAlloc = 2;
     242    peer->inRequests = tr_new0( tr_request_t, peer->inRequestAlloc );
     243
    236244    peer->socket = s;
    237245    peer->addr = addr;
     
    355363            peer->buf   = realloc( peer->buf, peer->size );
    356364        }
     365#if 0
    357366        /* Never read more than 1K each time, otherwise the rate
    358367           control is no use */
    359368        ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],
    360                           MIN( 1024, peer->size - peer->pos ) );
     369                          MIN( 1024, peer->size - peer->pos ) );
     370#else
     371        /* Hm, it doesn't *seem* to break rate control... */
     372        ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],
     373                          peer->size - peer->pos );
     374#endif
     375
    361376        if( ret & TR_NET_CLOSE )
    362377        {
     
    596611        && !peer->peerChoking
    597612        && !peer->banned
    598         &&  peer->inRequestCount < OUR_REQUEST_COUNT )
     613        &&  peer->inRequestCount < peer->inRequestMax )
    599614    {
    600615        int i;
     
    602617        int * pool = getPreferredPieces ( tor, peer, &poolSize, &endgame );
    603618
    604         /* TODO: add some asserts to see if this bitfield is really necessary */
    605         tr_bitfield_t * requestedBlocks = tr_bitfieldNew( tor->blockCount );
    606         for( i=0; i<peer->inRequestCount; ++i) {
    607             const tr_request_t * r = &peer->inRequests[i];
    608             const int block = tr_block( r->index, r->begin );
    609             tr_bitfieldAdd( requestedBlocks, block );
    610         }
    611 
    612         for( i=0; i<poolSize && peer->inRequestCount<OUR_REQUEST_COUNT;  )
     619        for( i=0; i<poolSize && peer->inRequestCount<peer->inRequestMax;  )
    613620        {
    614621            int unused;
     
    618625                : tr_cpMissingBlockInPiece ( tor->completion, piece );
    619626
    620             if( block>=0 && (endgame || !tr_bitfieldHas( requestedBlocks, block ) ) )
    621             {
    622                 tr_bitfieldAdd( requestedBlocks, block );
     627            if( block>=0 )
    623628                sendRequest( tor, peer, block );
    624             }
    625629            else ++i;
    626630        }
    627631
    628         tr_bitfieldFree( requestedBlocks );
    629632        free( pool );
    630633    }
     
    683686{
    684687    return tr_rcRate( peer->upload );
     688}
     689
     690int tr_peerTimesChoked( const tr_peer_t * peer )
     691{
     692    return peer->timesChoked;
    685693}
    686694
     
    689697    sendChoke( peer, 1 );
    690698    peer->lastChoke = tr_date();
     699    ++peer->timesChoked;
    691700}
    692701
     
    838847
    839848    tr_torrentWriterLock( tor );
     849
     850    for( i=0; i<tor->peerCount; ++i )
     851    {
     852        /* preferred # of seconds for the request queue's turnaround time.
     853           this is just an arbitrary number. */
     854        const int queueTime = 5;
     855        int j;
     856        tr_peer_t * peer = tor->peers[ i ];
     857
     858        if( !tr_peerIsConnected( peer ) )
     859            continue;
     860
     861        /* decide how deep the request queue should be */
     862        peer->outRequestMax = queueTime * tr_rcRate(peer->download) / tor->blockSize;
     863        peer->inRequestMax += 2; /* room to grow */
     864
     865        /* make room for new requests */
     866        if( peer->outRequestAlloc < peer->outRequestMax ) {
     867            peer->outRequestAlloc = peer->outRequestMax;
     868            peer->outRequests = tr_renew( tr_request_t, peer->outRequests, peer->outRequestAlloc );
     869        }
     870
     871        /* decide how deep the request queue should be */
     872        peer->inRequestMax = queueTime * tr_rcRate(peer->download) / (tor->blockSize/1024);
     873        peer->inRequestMax += 2; /* room to grow */
     874
     875        /* make room for new requests */
     876        if( peer->inRequestAlloc < peer->inRequestMax ) {
     877            peer->inRequestAlloc = peer->inRequestMax;
     878            peer->inRequests = tr_renew( tr_request_t, peer->inRequests, peer->inRequestAlloc );
     879        }
     880
     881        /* queue shrank... notify completion that we won't be sending those requests */
     882        for( j=peer->inRequestMax; j<peer->inRequestCount; ++j ) {
     883            tr_request_t * r = &peer->inRequests[j];
     884            tr_cpDownloaderRem( tor->completion, tr_block(r->index,r->begin) );
     885        }
     886    }
    840887
    841888    deadbeats = tr_calloc( tor->peerCount, sizeof(tr_peer_t*) );
     
    848895    if( deadbeatCount )
    849896    {
    850         const double ul_KiBsec = tr_rcRate( tor->upload );
     897        const double ul_KiBsec = tr_rcRate( tor->download );
    851898        const double ul_KiB = ul_KiBsec * SWIFT_REFRESH_INTERVAL_SEC;
    852899        const double ul_bytes = ul_KiB * 1024;
  • trunk/libtransmission/peer.h

    r2177 r2231  
    4646int         tr_peerAmInterested    ( const tr_peer_t * );
    4747int         tr_peerIsChoking       ( const tr_peer_t * );
     48int         tr_peerTimesChoked     ( const tr_peer_t * );
    4849int         tr_peerIsInterested    ( const tr_peer_t * );
    4950float       tr_peerProgress        ( const tr_peer_t * );
  • trunk/libtransmission/peerparse.h

    r2177 r2231  
    238238    }
    239239
    240     if( peer->outRequestCount >= MAX_REQUEST_COUNT )
     240    if( peer->outRequestCount >= peer->outRequestMax )
    241241    {
    242242        tr_err( "Too many requests" );
     
    524524                peer_dbg( "GET  unknown extended message '%hhu'", extid );
    525525            }
    526             return 1;
     526            /* ignore the unknown extension */
     527            return 0;
    527528        case AZ_MSG_BT_KEEP_ALIVE:
    528529            return TR_OK;
     
    537538    }
    538539
    539     peer_dbg( "GET  unknown message '%d'", id );
     540    tr_err( "GET  unknown message '%d'", id );
    540541    return TR_ERROR;
    541542}
  • trunk/libtransmission/ratecontrol.c

    r2004 r2231  
    166166{
    167167    tr_transfer_t * t = NULL;
    168     uint64_t now, start;
    169     int i, total;
    170 
    171     now = tr_date();
     168    uint64_t now, then, start;
     169    float total = 0;
     170    int i;
     171
     172    now = then = tr_date();
    172173    start = now - interval;
    173174
    174175    /* Browse the history back in time */
    175     total = 0;
    176176    for( i = r->transferStop; i != r->transferStart; i-- )
    177177    {
    178178        t = &r->transfers[i];
    179         if( t->date < start )
     179        then = t->date;
     180        if( then < start )
    180181            break;
    181182
     
    185186            i = HISTORY_SIZE; /* Loop */
    186187    }
     188#if 0
    187189    if( ( r->transferStop + 1 ) % HISTORY_SIZE == r->transferStart
    188190        && i == r->transferStart )
     
    193195        interval = now - t->date;
    194196    }
    195 
    196     return ( 1000.0f / 1024.0f ) * total / interval;
    197 }
    198 
     197#endif
     198
     199    if( now == then )
     200        return 0.0;
     201    return ( 1000.0f / 1024.0f ) * total / (now - then);
     202}
     203
  • trunk/libtransmission/shared.c

    r2202 r2231  
    2727
    2828/* Maximum number of peers that we keep in our local list */
    29 #define MAX_PEER_COUNT 42
     29/* This is an arbitrary number, but it seems to work well */
     30#define MAX_PEER_COUNT 128
    3031
    3132struct tr_shared_s
  • trunk/libtransmission/torrent.c

    r2222 r2231  
    545545    for( i=0; i<tor->peerCount; ++i ) {
    546546        const tr_peer_t * peer = tor->peers[i];
     547            ++s->peersTotal;
    547548        if( tr_peerIsConnected( peer ) ) {
    548             ++s->peersTotal;
    549549            ++s->peersFrom[tr_peerIsFrom(peer)];
    550550            if( tr_peerAmInterested( peer ) && !tr_peerIsChoking( peer ) )
     
    954954
    955955        /* sleep a little while */
    956         tr_wait( tor->runStatus == TR_RUN_STOPPED ? 1000 : 100 );
     956        tr_wait( tor->runStatus == TR_RUN_STOPPED ? 1600 : 800 );
    957957
    958958        /* if we're stopping... */
  • trunk/libtransmission/utils.h

    r2206 r2231  
    181181#define tr_new0(struct_type, n_structs)          \
    182182    ((struct_type *) tr_malloc0 (((size_t) sizeof (struct_type)) * ((size_t) (n_structs))))
     183#define tr_renew(struct_type, mem, n_structs)    \
     184    ((struct_type *) realloc ((mem), ((size_t) sizeof (struct_type)) * ((size_t) (n_structs))))
    183185
    184186void* tr_malloc  ( size_t );
Note: See TracChangeset for help on using the changeset viewer.