diff --git a/libtransmission/bandwidth.c b/libtransmission/bandwidth.c index 500d34bf6..01b7ad928 100644 --- a/libtransmission/bandwidth.c +++ b/libtransmission/bandwidth.c @@ -34,22 +34,32 @@ static unsigned int getSpeed_Bps( const struct bratecontrol * r, unsigned int interval_msec, uint64_t now ) { - uint64_t bytes = 0; - const uint64_t cutoff = (now?now:tr_time_msec()) - interval_msec; - int i = r->newest; + if( !now ) + now = tr_time_msec(); - for( ;; ) + if( now != r->cache_time ) { - if( r->transfers[i].date <= cutoff ) - break; + int i = r->newest; + uint64_t bytes = 0; + const uint64_t cutoff = now - interval_msec; + struct bratecontrol * rvolatile = (struct bratecontrol*) r; - bytes += r->transfers[i].size; + for( ;; ) + { + if( r->transfers[i].date <= cutoff ) + break; - if( --i == -1 ) i = HISTORY_SIZE - 1; /* circular history */ - if( i == r->newest ) break; /* we've come all the way around */ + bytes += r->transfers[i].size; + + if( --i == -1 ) i = HISTORY_SIZE - 1; /* circular history */ + if( i == r->newest ) break; /* we've come all the way around */ + } + + rvolatile->cache_val = (unsigned int)(( bytes * 1000u ) / interval_msec); + rvolatile->cache_time = now; } - return (unsigned int)(( bytes * 1000u ) / interval_msec); + return r->cache_val; } static void @@ -63,6 +73,9 @@ bytesUsed( const uint64_t now, struct bratecontrol * r, size_t size ) r->transfers[r->newest].date = now; r->transfers[r->newest].size = size; } + + /* invalidate cache_val*/ + r->cache_time = 0; } /****** @@ -88,7 +101,7 @@ tr_bandwidthConstruct( tr_bandwidth * b, tr_session * session, tr_bandwidth * pa { b->session = session; b->children = TR_PTR_ARRAY_INIT; - b->magicNumber = MAGIC_NUMBER; + b->magicNumber = BANDWIDTH_MAGIC_NUMBER; b->band[TR_UP].honorParentLimits = TRUE; b->band[TR_DOWN].honorParentLimits = TRUE; tr_bandwidthSetParent( b, parent ); @@ -215,7 +228,7 @@ phaseOne( tr_ptrArray * peerArray, tr_direction dir ) i = n ? tr_cryptoWeakRandInt( n ) : 0; /* pick a random starting point */ while( n > 1 ) { - const size_t increment = 256;//1024; + const size_t increment = 512;//1024; const int bytesUsed = tr_peerIoFlush( peers[i], dir, increment ); dbgmsg( "peer #%d of %d used %d bytes in this pass", i, n, bytesUsed ); @@ -319,20 +332,20 @@ bandwidthClamp( const tr_bandwidth * b, { if( b->band[dir].isLimited ) { - double current = tr_bandwidthGetRawSpeed_Bps( b, now, TR_DOWN ); - double desired = tr_bandwidthGetDesiredSpeed_Bps( b, TR_DOWN ); - double r = desired > 0.001 ? current / desired : 0; - size_t i; - byteCount = MIN( byteCount, b->band[dir].bytesLeft ); - if( r > 1.0 ) i = 0; - else if( r > 0.9 ) i = byteCount * 0.9; - else if( r > 0.8 ) i = byteCount * 0.8; - else i = byteCount; + /* if we're getting close to exceeding the speed limit, + * clamp down harder on the bytes available */ + if( byteCount > 0 ) + { + double current = tr_bandwidthGetRawSpeed_Bps( b, now, TR_DOWN ); + double desired = tr_bandwidthGetDesiredSpeed_Bps( b, TR_DOWN ); + double r = desired >= 1 ? current / desired : 0; - //fprintf( stderr, "--> %.4f (%f... %f) [%zu --> %zu]\n", r, current, desired, byteCount, i ); - byteCount = i; + if( r > 1.0 ) byteCount = 0; + else if( r > 0.9 ) byteCount *= 0.8; + else if( r > 0.8 ) byteCount *= 0.9; + } } if( b->parent && b->band[dir].honorParentLimits && ( byteCount > 0 ) ) diff --git a/libtransmission/bandwidth.h b/libtransmission/bandwidth.h index 151f0d8e7..471c5ec2a 100644 --- a/libtransmission/bandwidth.h +++ b/libtransmission/bandwidth.h @@ -38,7 +38,7 @@ enum INTERVAL_MSEC = HISTORY_MSEC, GRANULARITY_MSEC = 200, HISTORY_SIZE = ( INTERVAL_MSEC / GRANULARITY_MSEC ), - MAGIC_NUMBER = 43143 + BANDWIDTH_MAGIC_NUMBER = 43143 }; /* these are PRIVATE IMPLEMENTATION details that should not be touched. @@ -47,6 +47,8 @@ struct bratecontrol { int newest; struct { uint64_t date, size; } transfers[HISTORY_SIZE]; + uint64_t cache_time; + unsigned int cache_val; }; /* these are PRIVATE IMPLEMENTATION details that should not be touched. @@ -141,7 +143,7 @@ static inline void tr_bandwidthFree( tr_bandwidth * bandwidth ) /** @brief test to see if the pointer refers to a live bandwidth object */ static inline tr_bool tr_isBandwidth( const tr_bandwidth * b ) { - return ( b != NULL ) && ( b->magicNumber == MAGIC_NUMBER ); + return ( b != NULL ) && ( b->magicNumber == BANDWIDTH_MAGIC_NUMBER ); } /****** diff --git a/libtransmission/peer-io.c b/libtransmission/peer-io.c index 8a2ae57ec..b0dc39ece 100644 --- a/libtransmission/peer-io.c +++ b/libtransmission/peer-io.c @@ -39,8 +39,6 @@ #include "utils.h" -#define MAGIC_NUMBER 206745 - #ifdef WIN32 #define EAGAIN WSAEWOULDBLOCK #define EINTR WSAEINTR @@ -139,8 +137,6 @@ canReadWrapper( tr_peerIo * io ) dbgmsg( io, "canRead" ); - assert( tr_isPeerIo( io ) ); - assert( tr_isSession( io->session ) ); tr_peerIoRef( io ); session = io->session; @@ -160,8 +156,6 @@ canReadWrapper( tr_peerIo * io ) const size_t used = oldLen - evbuffer_get_length( io->inbuf ); const unsigned int overhead = guessPacketOverhead( used ); - assert( tr_isPeerIo( io ) ); - if( piece || (piece!=used) ) { if( piece ) @@ -197,20 +191,9 @@ canReadWrapper( tr_peerIo * io ) tr_sessionUnlock( session ); } - assert( tr_isPeerIo( io ) ); tr_peerIoUnref( io ); } -tr_bool -tr_isPeerIo( const tr_peerIo * io ) -{ - return ( io != NULL ) - && ( io->magicNumber == MAGIC_NUMBER ) - && ( io->refCount >= 0 ) - && ( tr_isBandwidth( &io->bandwidth ) ) - && ( tr_isAddress( &io->addr ) ); -} - static void event_read_cb( int fd, short event UNUSED, void * vio ) { @@ -564,7 +547,7 @@ tr_peerIoNew( tr_session * session, } io = tr_new0( tr_peerIo, 1 ); - io->magicNumber = MAGIC_NUMBER; + io->magicNumber = PEER_IO_MAGIC_NUMBER; io->refCount = 1; io->crypto = tr_cryptoNew( torrentHash, isIncoming ); io->session = session; diff --git a/libtransmission/peer-io.h b/libtransmission/peer-io.h index e764cf19f..df50c425d 100644 --- a/libtransmission/peer-io.h +++ b/libtransmission/peer-io.h @@ -144,8 +144,17 @@ void tr_peerIoUnrefImpl ( const char * file, #define tr_peerIoUnref(io) tr_peerIoUnrefImpl( __FILE__, __LINE__, (io) ); -tr_bool tr_isPeerIo ( const tr_peerIo * io ); +#define PEER_IO_MAGIC_NUMBER 206745 +static inline tr_bool +tr_isPeerIo( const tr_peerIo * io ) +{ + return ( io != NULL ) + && ( io->magicNumber == PEER_IO_MAGIC_NUMBER ) + && ( io->refCount >= 0 ) + && ( tr_isBandwidth( &io->bandwidth ) ) + && ( tr_isAddress( &io->addr ) ); +} /** *** @@ -355,17 +364,12 @@ void tr_peerIoBandwidthUsed( tr_peerIo * io, static inline tr_bool tr_peerIoHasBandwidthLeft( const tr_peerIo * io, tr_direction dir ) { - assert( tr_isPeerIo( io ) ); - return tr_bandwidthClamp( &io->bandwidth, dir, 1024 ) > 0; } static inline unsigned int tr_peerIoGetPieceSpeed_Bps( const tr_peerIo * io, uint64_t now, tr_direction dir ) { - assert( tr_isPeerIo( io ) ); - assert( tr_isDirection( dir ) ); - return tr_bandwidthGetPieceSpeed_Bps( &io->bandwidth, now, dir ); }