Changeset 1426
- Timestamp:
- Jan 22, 2007, 10:58:51 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/ratecontrol.c
r1372 r1426 25 25 #include "transmission.h" 26 26 27 #define MAX_HISTORY 30 28 29 typedef struct tr_transfer_s tr_transfer_t; 27 /* Maximum number of packets we keep track of. Since most packets are 28 * 1 KB, it means we remember the last 2 MB transferred */ 29 #define HISTORY_SIZE 2048 30 31 /* How far back we go to calculate rates to be displayed in the 32 * interface */ 33 #define LONG_INTERVAL 30000 /* 30 secs */ 34 35 /* How far back we go to calculate pseudo-instantaneous transfer rates, 36 * for the actual rate control */ 37 #define SHORT_INTERVAL 1000 /* 1 sec */ 38 39 40 /*********************************************************************** 41 * Structures 42 **********************************************************************/ 43 typedef struct tr_transfer_s 44 { 45 uint64_t date; 46 int size; 47 } 48 tr_transfer_t; 49 30 50 struct tr_ratecontrol_s 31 51 { 32 tr_lock_t lock; 33 int limit; 34 tr_transfer_t * first; 35 tr_transfer_t * last; 52 tr_lock_t lock; 53 int limit; 54 55 /* Circular history: it's empty if transferStop == transferStart, 56 * full if ( transferStop + 1 ) % HISTORY_SIZE == transferStart */ 57 tr_transfer_t transfers[HISTORY_SIZE]; 58 int transferStart; 59 int transferStop; 36 60 }; 37 struct tr_transfer_s 38 { 39 uint64_t date; 40 int size; 41 tr_transfer_t * next; 42 tr_transfer_t * prev; 43 }; 44 45 /*********************************************************************** 46 * rateForInterval 47 *********************************************************************** 48 * Returns the transfer rate on the last 'interval' milliseconds 49 **********************************************************************/ 50 static inline float rateForInterval( tr_ratecontrol_t * r, int interval ) 51 { 52 tr_transfer_t * t; 53 uint64_t start = tr_date() - interval; 54 int total = 0; 55 56 for( t = r->first; t && t->date > start; t = t->next ) 57 { 58 total += t->size; 59 } 60 61 return ( 1000.0 / 1024.0 ) * total / interval; 62 } 63 64 static inline void cleanOldTransfers( tr_ratecontrol_t * r ) 65 { 66 tr_transfer_t * t, * prev; 67 uint64_t old = tr_date() - MAX_HISTORY * 1000; 68 69 for( t = r->last; t && t->date < old; ) 70 { 71 prev = t->prev; 72 if( prev ) 73 prev->next = NULL; 74 else 75 r->first = NULL; 76 free( t ); 77 t = prev; 78 r->last = prev; 79 } 80 } 61 62 63 /*********************************************************************** 64 * Local prototypes 65 **********************************************************************/ 66 static float rateForInterval( tr_ratecontrol_t * r, int interval ); 67 68 69 /*********************************************************************** 70 * Exported functions 71 **********************************************************************/ 81 72 82 73 tr_ratecontrol_t * tr_rcInit() … … 112 103 r = isUpload ? tor->upload : tor->download; 113 104 tr_lockLock( &r->lock ); 114 rate += rateForInterval( r, 1000);105 rate += rateForInterval( r, SHORT_INTERVAL ); 115 106 tr_lockUnlock( &r->lock ); 116 107 … … 136 127 137 128 tr_lockLock( &r->lock ); 138 ret = ( r->limit <= 0 ) ? ( r->limit < 0 ) : ( rateForInterval( r, 1000 ) < r->limit ); 129 ret = ( r->limit <= 0 ) ? ( r->limit < 0 ) : 130 ( rateForInterval( r, SHORT_INTERVAL ) < r->limit ); 139 131 tr_lockUnlock( &r->lock ); 140 132 … … 148 140 if( size < 100 ) 149 141 { 142 /* Don't count small messages */ 150 143 return; 151 144 } 152 145 153 146 tr_lockLock( &r->lock ); 154 t = malloc( sizeof( tr_transfer_t ) ); 155 156 if( r->first ) 157 r->first->prev = t; 158 if( !r->last ) 159 r->last = t; 160 t->next = r->first; 161 t->prev = NULL; 162 r->first = t; 163 164 t->date = tr_date(); 165 t->size = size; 166 167 cleanOldTransfers( r ); 147 148 r->transferStop = ( r->transferStop + 1 ) % HISTORY_SIZE; 149 if( r->transferStop == r->transferStart ) 150 /* History is full, forget about the first (oldest) item */ 151 r->transferStart = ( r->transferStart + 1 ) % HISTORY_SIZE; 152 153 t = &r->transfers[r->transferStop]; 154 t->date = tr_date(); 155 t->size = size; 156 168 157 tr_lockUnlock( &r->lock ); 169 158 } … … 174 163 175 164 tr_lockLock( &r->lock ); 176 ret = rateForInterval( r, MAX_HISTORY * 1000);165 ret = rateForInterval( r, LONG_INTERVAL ); 177 166 tr_lockUnlock( &r->lock ); 178 167 … … 182 171 void tr_rcReset( tr_ratecontrol_t * r ) 183 172 { 184 tr_transfer_t * t, * next; 185 186 tr_lockLock( &r->lock ); 187 for( t = r->first; t; ) 188 { 189 next = t->next; 190 free( t ); 191 t = next; 192 } 193 r->first = NULL; 194 r->last = NULL; 173 tr_lockLock( &r->lock ); 174 r->transferStart = 0; 175 r->transferStop = 0; 195 176 tr_lockUnlock( &r->lock ); 196 177 } … … 202 183 free( r ); 203 184 } 185 186 187 /*********************************************************************** 188 * Local functions 189 **********************************************************************/ 190 191 /*********************************************************************** 192 * rateForInterval 193 *********************************************************************** 194 * Returns the transfer rate in KB/s on the last 'interval' 195 * milliseconds 196 **********************************************************************/ 197 static float rateForInterval( tr_ratecontrol_t * r, int interval ) 198 { 199 tr_transfer_t * t = NULL; 200 uint64_t now, start; 201 int i, total; 202 203 now = tr_date(); 204 start = now - interval; 205 206 /* Browse the history back in time */ 207 total = 0; 208 for( i = r->transferStop; i != r->transferStart; i-- ) 209 { 210 t = &r->transfers[i]; 211 if( t->date < start ) 212 break; 213 214 total += t->size; 215 216 if( !i ) 217 i = HISTORY_SIZE; /* Loop */ 218 } 219 if( ( r->transferStop + 1 ) % HISTORY_SIZE == r->transferStart 220 && i == r->transferStart ) 221 { 222 /* High bandwidth -> the history isn't big enough to remember 223 * everything transferred since 'interval' ms ago. Correct the 224 * interval so that we return the correct rate */ 225 interval = now - t->date; 226 } 227 228 return ( 1000.0f / 1024.0f ) * total / interval; 229 } 230
Note: See TracChangeset
for help on using the changeset viewer.