Changeset 2303


Ignore:
Timestamp:
Jul 7, 2007, 4:13:13 AM (16 years ago)
Author:
charles
Message:

fix broken rate control.

Location:
trunk/libtransmission
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/peer.c

    r2297 r2303  
    378378            peer->buf   = realloc( peer->buf, peer->size );
    379379        }
    380 #if 0
    381         /* Never read more than 1K each time, otherwise the rate
    382            control is no use */
     380
     381        /* Read in smallish chunks, otherwise we might read more
     382         * than the download cap is supposed to allow us */
    383383        ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],
    384384                          MIN( 1024, peer->size - peer->pos ) );
    385 #else
    386         /* Hm, it doesn't *seem* to break rate control... */
    387         ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],
    388                           peer->size - peer->pos );
    389 #endif
    390385
    391386        if( ret & TR_NET_CLOSE )
     
    569564    {
    570565        if( SWIFT_ENABLED && !isSeeding && (peer->credit<0) )
    571         {
    572566            break;
    573         }
    574567
    575568        if( tor->customUploadLimit
    576569            ? !tr_rcCanTransfer( tor->upload )
    577570            : !tr_rcCanTransfer( tor->handle->upload ) )
    578         {
    579571            break;
    580         }
    581572
    582573        ret = tr_netSend( peer->socket, p, size );
    583574        if( ret & TR_NET_CLOSE )
    584         {
    585575            return TR_ERROR;
    586         }
    587         else if( ret & TR_NET_BLOCK )
    588         {
     576
     577        if( ret & TR_NET_BLOCK )
    589578            break;
    590         }
    591579
    592580        blockSent( peer, ret );
     
    602590       
    603591        if( !tr_peerAmChoking( peer ) )
    604         {
    605592            tor->activityDate = date;
    606         }
    607593
    608594        /* In case this block is done, you may have messages
  • trunk/libtransmission/ratecontrol.c

    r2231 r2303  
    2626#include "shared.h"
    2727
    28 /* Maximum number of packets we keep track of. Since most packets are
    29  * 1 KB, it means we remember the last 2 MB transferred */
    30 #define HISTORY_SIZE 2048
     28#define GRANULARITY_MSEC 200
     29#define SHORT_INTERVAL_MSEC 1000
     30#define LONG_INTERVAL_MSEC 10000
     31#define HISTORY_SIZE (LONG_INTERVAL_MSEC / GRANULARITY_MSEC)
    3132
    32 /* How far back we go to calculate rates to be displayed in the
    33  * interface */
    34 #define LONG_INTERVAL 30000 /* 30 secs */
    35 
    36 /* How far back we go to calculate pseudo-instantaneous transfer rates,
    37  * for the actual rate control */
    38 #define SHORT_INTERVAL 1000 /* 1 sec */
    39 
    40 
    41 /***********************************************************************
    42  * Structures
    43  **********************************************************************/
    44 typedef struct tr_transfer_s
     33typedef struct
    4534{
    4635    uint64_t date;
     
    5140struct tr_ratecontrol_s
    5241{
    53     tr_lock_t     lock;
    54     int           limit;
    55 
    56     /* Circular history: it's empty if transferStop == transferStart,
    57      * full if ( transferStop + 1 ) % HISTORY_SIZE == transferStart */
     42    tr_rwlock_t lock;
     43    int limit;
     44    int newest;
    5845    tr_transfer_t transfers[HISTORY_SIZE];
    59     int           transferStart;
    60     int           transferStop;
    6146};
    6247
     48/* return the xfer rate over the last `interval' seconds in KiB/sec */
     49static float
     50rateForInterval( const tr_ratecontrol_t * r, int interval_msec )
     51{
     52    uint64_t bytes = 0;
     53    const uint64_t now = tr_date ();
     54    int i = r->newest;
     55    int real_interval_msec = 0;
     56    for( ;; )
     57    {
     58        if( r->transfers[i].date + interval_msec < now )
     59            break;
    6360
    64 /***********************************************************************
    65  * Local prototypes
    66  **********************************************************************/
    67 static float rateForInterval( tr_ratecontrol_t * r, int interval );
     61        bytes += r->transfers[i].size;
     62        real_interval_msec = now - r->transfers[i].date;
    6863
     64        if( --i == -1 ) i = HISTORY_SIZE - 1; /* circular history */
     65        if( i == r->newest ) break; /* we've come all the way around */
     66    }
    6967
    70 /***********************************************************************
    71  * Exported functions
    72  **********************************************************************/
     68    return !bytes || !real_interval_msec
     69        ? 0.0
     70        : (bytes/1024.0) * (1000.0/real_interval_msec);
     71}
    7372
    74 tr_ratecontrol_t * tr_rcInit()
     73/***
     74****
     75***/
     76
     77tr_ratecontrol_t*
     78tr_rcInit( void )
    7579{
    76     tr_ratecontrol_t * r;
    77 
    78     r        = calloc( 1, sizeof( tr_ratecontrol_t ) );
     80    tr_ratecontrol_t * r = tr_new0( tr_ratecontrol_t, 1 );
    7981    r->limit = -1;
    80     tr_lockInit( &r->lock );
    81 
     82    tr_rwInit( &r->lock );
    8283    return r;
    8384}
    8485
    85 void tr_rcSetLimit( tr_ratecontrol_t * r, int limit )
     86void
     87tr_rcClose( tr_ratecontrol_t * r )
    8688{
    87     tr_lockLock( &r->lock );
    88     r->limit = limit;
    89     tr_lockUnlock( &r->lock );
     89    tr_rcReset( r );
     90    tr_rwClose( &r->lock );
     91    tr_free( r );
    9092}
    9193
    92 int tr_rcCanTransfer( tr_ratecontrol_t * r )
     94/***
     95****
     96***/
     97
     98int
     99tr_rcCanTransfer( const tr_ratecontrol_t * r )
    93100{
    94101    int ret;
     102    tr_rwReaderLock( (tr_rwlock_t*)&r->lock );
    95103
    96     tr_lockLock( &r->lock );
    97     ret = ( r->limit <= 0 ) ? ( r->limit < 0 ) :
    98             ( rateForInterval( r, SHORT_INTERVAL ) < r->limit );
    99     tr_lockUnlock( &r->lock );
     104    if( r->limit < 0 ) /* unbounded */
     105        ret = TRUE;
     106    else if( !r->limit ) /* off */
     107        ret = FALSE;
     108    else
     109        ret = rateForInterval( r, SHORT_INTERVAL_MSEC ) < r->limit;
    100110
     111    tr_rwReaderUnlock( (tr_rwlock_t*)&r->lock );
    101112    return ret;
    102113}
    103114
    104 void tr_rcTransferred( tr_ratecontrol_t * r, int size )
    105 {
    106     tr_transfer_t * t;
    107 
    108     if( size < 100 )
    109     {
    110         /* Don't count small messages */
    111         return;
    112     }
    113    
    114     tr_lockLock( &r->lock );
    115 
    116     r->transferStop = ( r->transferStop + 1 ) % HISTORY_SIZE;
    117     if( r->transferStop == r->transferStart )
    118         /* History is full, forget about the first (oldest) item */
    119         r->transferStart = ( r->transferStart + 1 ) % HISTORY_SIZE;
    120 
    121     t = &r->transfers[r->transferStop];
    122     t->date = tr_date();
    123     t->size = size;
    124 
    125     tr_lockUnlock( &r->lock );
    126 }
    127 
    128 float tr_rcRate( tr_ratecontrol_t * r )
     115float
     116tr_rcRate( const tr_ratecontrol_t * r )
    129117{
    130118    float ret;
     119    tr_rwReaderLock( (tr_rwlock_t*)&r->lock );
    131120
    132     tr_lockLock( &r->lock );
    133     ret = rateForInterval( r, LONG_INTERVAL );
    134     tr_lockUnlock( &r->lock );
     121    ret = rateForInterval( r, LONG_INTERVAL_MSEC );
    135122
     123    tr_rwReaderUnlock( (tr_rwlock_t*)&r->lock );
    136124    return ret;
    137125}
    138126
    139 void tr_rcReset( tr_ratecontrol_t * r )
     127/***
     128****
     129***/
     130
     131void
     132tr_rcTransferred( tr_ratecontrol_t * r, int size )
    140133{
    141     tr_lockLock( &r->lock );
    142     r->transferStart = 0;
    143     r->transferStop = 0;
    144     tr_lockUnlock( &r->lock );
     134    uint64_t now;
     135
     136    if( size < 100 ) /* don't count small messages */
     137        return;
     138   
     139    tr_rwWriterLock( &r->lock );
     140
     141    now = tr_date ();
     142    if( r->transfers[r->newest].date + GRANULARITY_MSEC >= now )
     143        r->transfers[r->newest].size += size;
     144    else {
     145        if( ++r->newest == HISTORY_SIZE ) r->newest = 0;
     146        r->transfers[r->newest].date = now;
     147        r->transfers[r->newest].size = size;
     148    }
     149
     150    tr_rwWriterUnlock( &r->lock );
    145151}
    146152
    147 void tr_rcClose( tr_ratecontrol_t * r )
     153void
     154tr_rcReset( tr_ratecontrol_t * r )
    148155{
    149     tr_rcReset( r );
    150     tr_lockClose( &r->lock );
    151     free( r );
     156    tr_rwWriterLock( &r->lock );
     157    r->newest = 0;
     158    memset( r->transfers, 0, sizeof(tr_transfer_t) * HISTORY_SIZE );
     159    tr_rwWriterUnlock( &r->lock );
    152160}
    153161
    154 
    155 /***********************************************************************
    156  * Local functions
    157  **********************************************************************/
    158 
    159 /***********************************************************************
    160  * rateForInterval
    161  ***********************************************************************
    162  * Returns the transfer rate in KB/s on the last 'interval'
    163  * milliseconds
    164  **********************************************************************/
    165 static float rateForInterval( tr_ratecontrol_t * r, int interval )
     162void
     163tr_rcSetLimit( tr_ratecontrol_t * r, int limit )
    166164{
    167     tr_transfer_t * t = NULL;
    168     uint64_t now, then, start;
    169     float total = 0;
    170     int i;
    171 
    172     now = then = tr_date();
    173     start = now - interval;
    174 
    175     /* Browse the history back in time */
    176     for( i = r->transferStop; i != r->transferStart; i-- )
    177     {
    178         t = &r->transfers[i];
    179         then = t->date;
    180         if( then < start )
    181             break;
    182 
    183         total += t->size;
    184 
    185         if( !i )
    186             i = HISTORY_SIZE; /* Loop */
    187     }
    188 #if 0
    189     if( ( r->transferStop + 1 ) % HISTORY_SIZE == r->transferStart
    190         && i == r->transferStart )
    191     {
    192         /* High bandwidth -> the history isn't big enough to remember
    193          * everything transferred since 'interval' ms ago. Correct the
    194          * interval so that we return the correct rate */
    195         interval = now - t->date;
    196     }
    197 #endif
    198 
    199     if( now == then )
    200         return 0.0;
    201     return ( 1000.0f / 1024.0f ) * total / (now - then);
     165    tr_rwWriterLock( &r->lock );
     166    r->limit = limit;
     167    tr_rwWriterUnlock( &r->lock );
    202168}
    203 
  • trunk/libtransmission/ratecontrol.h

    r1869 r2303  
    2525typedef struct tr_ratecontrol_s tr_ratecontrol_t;
    2626
    27 tr_ratecontrol_t * tr_rcInit();
     27tr_ratecontrol_t * tr_rcInit( void );
    2828void               tr_rcSetLimit( tr_ratecontrol_t *, int );
    29 int                tr_rcCanTransfer( tr_ratecontrol_t * );
     29int                tr_rcCanTransfer( const tr_ratecontrol_t * );
    3030void               tr_rcTransferred( tr_ratecontrol_t *, int );
    31 float              tr_rcRate( tr_ratecontrol_t * );
     31float              tr_rcRate( const tr_ratecontrol_t * );
    3232void               tr_rcReset( tr_ratecontrol_t * );
    3333void               tr_rcClose( tr_ratecontrol_t * );
Note: See TracChangeset for help on using the changeset viewer.