Changeset 7147


Ignore:
Timestamp:
Nov 24, 2008, 4:21:23 AM (12 years ago)
Author:
charles
Message:

(libT) #1468: another stab at getting the peer transfer speeds both fast and a little more consistent.

Location:
trunk/libtransmission
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/Makefile.am

    r7101 r7147  
    1313
    1414libtransmission_a_SOURCES = \
     15    bandwidth.c \
    1516    bencode.c \
    1617    blocklist.c \
     
    5758
    5859noinst_HEADERS = \
     60    bandwidth.c \
    5961    bencode.h \
    6062    blocklist.h \
  • trunk/libtransmission/handshake.c

    r7125 r7147  
    11801180    tr_handshake * handshake;
    11811181
    1182     tr_peerIoSetBandwidthUnlimited( io, TR_UP );
    1183     tr_peerIoSetBandwidthUnlimited( io, TR_DOWN );
    1184 
    11851182    handshake = tr_new0( tr_handshake, 1 );
    11861183    handshake->io = io;
  • trunk/libtransmission/net.c

    r7133 r7147  
    129129    {
    130130        const int sndbuf = session->so_sndbuf;
     131        const int rcvbuf = session->so_rcvbuf;
    131132        setsockopt( fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof( sndbuf ) );
     133        setsockopt( fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof( rcvbuf ) );
    132134    }
    133135}
  • trunk/libtransmission/peer-io.c

    r7137 r7147  
    2727
    2828#include "transmission.h"
     29#include "bandwidth.h"
    2930#include "crypto.h"
    3031#include "list.h"
     
    7071    } while( 0 )
    7172
    72 struct tr_bandwidth
    73 {
    74     unsigned int  isUnlimited : 1;
    75     size_t        bytesLeft;
    76 };
    77 
    7873struct tr_datatype
    7974{
     
    112107    size_t                 bufferSize[2];
    113108
    114     struct tr_bandwidth    bandwidth[2];
    115 
    116     tr_crypto *            crypto;
     109    tr_bandwidth         * bandwidth[2];
     110    tr_crypto            * crypto;
    117111};
    118112
     
    125119{
    126120    struct evbuffer * live = EVBUFFER_OUTPUT( io->bufev );
    127 
    128     if( io->bandwidth[TR_UP].isUnlimited )
    129     {
    130         bufferevent_write_buffer( io->bufev, io->output );
    131     }
    132     else if( io->bandwidth[TR_UP].bytesLeft > EVBUFFER_LENGTH( live ) )
    133     {
    134         /* there's free space in bufev's output buffer;
    135            try to fill it up */
    136         const size_t desiredLength = io->bandwidth[TR_UP].bytesLeft;
    137         const size_t under = desiredLength - EVBUFFER_LENGTH( live );
    138         const size_t n = MIN( under, EVBUFFER_LENGTH( io->output ) );
     121    size_t curLive = EVBUFFER_LENGTH( live );
     122    size_t maxLive = tr_bandwidthClamp( io->bandwidth[TR_UP], io->session->so_sndbuf );
     123
     124    if( ( curLive < maxLive ) && EVBUFFER_LENGTH( io->output ) )
     125    {
     126        size_t freeSpace = maxLive - curLive;
     127        size_t n = MIN( freeSpace, EVBUFFER_LENGTH( io->output ) );
    139128        bufferevent_write( io->bufev, EVBUFFER_DATA( io->output ), n );
    140129        evbuffer_drain( io->output, n );
    141     }
    142     else if( io->bandwidth[TR_UP].bytesLeft < EVBUFFER_LENGTH( live ) )
    143     {
    144         /* bufev's output buffer exceeds our bandwidth allocation;
    145            move the excess out of bufev so it can't be sent yet */
    146         const size_t      desiredLength = io->bandwidth[TR_UP].bytesLeft;
    147         const size_t      over = EVBUFFER_LENGTH( live ) - desiredLength;
    148         struct evbuffer * buf = evbuffer_new( );
    149         evbuffer_add( buf, EVBUFFER_DATA( live ) + desiredLength, over );
    150         evbuffer_add_buffer( buf, io->output );
    151         evbuffer_free( io->output );
    152         io->output = buf;
    153         EVBUFFER_LENGTH( live ) = desiredLength;
    154     }
    155 
    156     if( EVBUFFER_LENGTH( live ) )
    157     {
     130        curLive += n;
     131    }
     132
     133    io->bufferSize[TR_UP] = curLive;
     134
     135    if( curLive )
    158136        bufferevent_enable( io->bufev, EV_WRITE );
    159     }
    160 
    161     io->bufferSize[TR_UP] = EVBUFFER_LENGTH( live );
    162 
    163     dbgmsg( io, "after adjusting the output buffer, its size is now %zu",
    164             io->bufferSize[TR_UP] );
     137
     138    dbgmsg( io, "after adjusting the output buffer, its size is now %zu", curLive );
    165139}
    166140
     
    168142adjustInputBuffer( tr_peerIo * io )
    169143{
    170     if( io->bandwidth[TR_DOWN].isUnlimited )
    171     {
    172         dbgmsg( io, "unlimited reading..." );
    173         bufferevent_setwatermark( io->bufev, EV_READ, 0, 0 );
     144    /* FIXME: the max read size probably needs to vary depending on the
     145     * number of peers that we have connected...  1024 is going to force
     146     * us way over the limit when there are lots of peers */
     147    static const int maxBufSize = 1024;
     148    const size_t n = tr_bandwidthClamp( io->bandwidth[TR_DOWN], maxBufSize );
     149
     150    if( !n )
     151    {
     152        dbgmsg( io, "disabling reads because we've hit our limit" );
     153        bufferevent_disable( io->bufev, EV_READ );
     154    }
     155    else
     156    {
     157        dbgmsg( io, "enabling reading of %zu more bytes", n );
     158        bufferevent_setwatermark( io->bufev, EV_READ, 0, n );
    174159        bufferevent_enable( io->bufev, EV_READ );
    175160    }
    176     else
    177     {
    178         const size_t n = io->bandwidth[TR_DOWN].bytesLeft;
    179         if( n == 0 )
    180         {
    181             dbgmsg( io, "disabling reads because we've hit our limit" );
    182             bufferevent_disable( io->bufev, EV_READ );
    183         }
    184         else
    185         {
    186             dbgmsg( io, "enabling reading of %zu more bytes", n );
    187             bufferevent_setwatermark( io->bufev, EV_READ, 0, n );
    188             bufferevent_enable( io->bufev, EV_READ );
    189         }
    190     }
     161
     162    io->bufferSize[TR_DOWN] = EVBUFFER_LENGTH( EVBUFFER_INPUT( io->bufev ) );
    191163}
    192164
     
    215187            const size_t n = addPacketOverhead( chunk_length );
    216188
    217             if( next->isPieceData )
    218             {
    219                 struct tr_bandwidth * b = &io->bandwidth[TR_UP];
    220                 b->bytesLeft -= MIN( b->bytesLeft, n );
    221             }
    222 
    223189            if( io->didWrite )
    224190                io->didWrite( io, n, next->isPieceData, io->userData );
     
    243209    tr_peerIo *  io = vio;
    244210    tr_session * session = io->session;
    245     const size_t len = EVBUFFER_LENGTH( EVBUFFER_INPUT( e ) );
    246211
    247212    dbgmsg( io, "canRead" );
    248 
    249     /* if the input buffer has grown, record the bytes that were read */
    250     if( len > io->bufferSize[TR_DOWN] )
    251     {
    252         const size_t payload = len - io->bufferSize[TR_DOWN];
    253         const size_t n = addPacketOverhead( payload );
    254         struct tr_bandwidth * b = io->bandwidth + TR_DOWN;
    255         b->bytesLeft -= MIN( b->bytesLeft, (size_t)n );
    256         dbgmsg( io, "%zu new input bytes. bytesLeft is %zu", n, b->bytesLeft );
    257 
    258         adjustInputBuffer( io );
    259     }
    260213
    261214    /* try to consume the input buffer */
     
    290243
    291244    if( !err )
    292         io->bufferSize[TR_DOWN] = EVBUFFER_LENGTH( EVBUFFER_INPUT( e ) );
     245        adjustInputBuffer( io );
    293246}
    294247
     
    349302    io->timeCreated = time( NULL );
    350303    io->output = evbuffer_new( );
    351     io->bandwidth[TR_UP].isUnlimited = 1;
    352     io->bandwidth[TR_DOWN].isUnlimited = 1;
    353304    bufevNew( io );
    354305    return io;
     
    615566tr_peerIoGetWriteBufferSpace( const tr_peerIo * io )
    616567{
    617     const size_t desiredBufferLen = 4096;
     568    const size_t desiredLiveLen = tr_bandwidthClamp( io->bandwidth[TR_UP], io->session->so_rcvbuf );
    618569    const size_t currentLiveLen = EVBUFFER_LENGTH( EVBUFFER_OUTPUT( io->bufev ) );
    619 
    620     const size_t currentLbufLen = EVBUFFER_LENGTH( io->output );
    621     const size_t desiredLiveLen = io->bandwidth[TR_UP].isUnlimited
    622                                 ? INT_MAX
    623                                 : io->bandwidth[TR_UP].bytesLeft;
    624 
    625     const size_t currentLen = currentLiveLen + currentLbufLen;
    626     const size_t desiredLen = desiredBufferLen + desiredLiveLen;
    627 
    628     size_t       freeSpace = 0;
     570    const size_t desiredQueueLen = io->session->so_sndbuf;
     571    const size_t currentQueueLen = EVBUFFER_LENGTH( io->output );
     572    const size_t desiredLen = desiredLiveLen + desiredQueueLen;
     573    const size_t currentLen = currentLiveLen + currentQueueLen;
     574    size_t freeSpace = 0;
    629575
    630576    if( desiredLen > currentLen )
    631577        freeSpace = desiredLen - currentLen;
     578
     579    return freeSpace;
     580}
     581
     582void
     583tr_peerIoSetBandwidth( tr_peerIo     * io,
     584                       tr_direction    direction,
     585                       tr_bandwidth  * bandwidth )
     586{
     587    assert( io );
     588    assert( direction == TR_UP || direction == TR_DOWN );
     589
     590    io->bandwidth[direction] = bandwidth;
     591
     592    if( direction ==  TR_UP )
     593        adjustOutputBuffer( io );
    632594    else
    633         freeSpace = 0;
    634 
    635     return freeSpace;
    636 }
    637 
    638 void
    639 tr_peerIoAllocateBandwidth( tr_peerIo     * io,
    640                             tr_direction    direction,
    641                             size_t          bytesLeft )
    642 {
    643     struct tr_bandwidth * b;
    644 
    645     assert( io );
    646     assert( direction == TR_UP || direction == TR_DOWN );
    647 
    648     b = io->bandwidth + direction;
    649     b->isUnlimited = 0;
    650     b->bytesLeft = bytesLeft;
    651 
    652     adjustOutputBuffer( io );
    653     adjustInputBuffer( io );
    654 }
    655 
    656 void
    657 tr_peerIoSetBandwidthUnlimited( tr_peerIo *  io,
    658                                 tr_direction direction )
    659 {
    660     struct tr_bandwidth * b;
    661 
    662     assert( io );
    663     assert( direction == TR_UP || direction == TR_DOWN );
    664 
    665     b = io->bandwidth + direction;
    666     b->isUnlimited = 1;
    667     b->bytesLeft = 0;
    668 
    669     adjustInputBuffer( io );
    670     adjustOutputBuffer( io );
     595        adjustInputBuffer( io );
    671596}
    672597
     
    712637    dbgmsg( io, "adding %zu bytes into io->output", writemeLen );
    713638
    714     if( io->bandwidth[TR_UP].isUnlimited )
    715         bufferevent_write( io->bufev, writeme, writemeLen );
    716     else
    717         evbuffer_add( io->output, writeme, writemeLen );
     639    evbuffer_add( io->output, writeme, writemeLen );
    718640
    719641    datatype = tr_new( struct tr_datatype, 1 );
  • trunk/libtransmission/peer-io.h

    r7137 r7147  
    2121struct evbuffer;
    2222struct bufferevent;
    23 struct tr_handle;
     23struct tr_bandwidth;
    2424struct tr_crypto;
    2525typedef struct tr_peerIo tr_peerIo;
     
    201201size_t            tr_peerIoGetWriteBufferSpace( const tr_peerIo * io );
    202202
    203 void              tr_peerIoAllocateBandwidth( tr_peerIo *  io,
    204                                               tr_direction direction,
    205                                               size_t       bytesLeft );
    206 
    207 void              tr_peerIoSetBandwidthUnlimited( tr_peerIo *  io,
    208                                                   tr_direction direction );
     203void              tr_peerIoSetBandwidth( tr_peerIo            * io,
     204                                         tr_direction           direction,
     205                                         struct tr_bandwidth  * bandwidth );
    209206
    210207
  • trunk/libtransmission/peer-mgr.c

    r7137 r7147  
    2020
    2121#include "transmission.h"
     22#include "bandwidth.h"
     23#include "bencode.h"
    2224#include "blocklist.h"
    2325#include "clients.h"
     
    5759   
    5860    /* how frequently to reallocate bandwidth */
    59     BANDWIDTH_PERIOD_MSEC = 250,
     61    BANDWIDTH_PERIOD_MSEC = 333,
    6062
    6163    /* max # of peers to ask fer per torrent per reconnect pulse */
    62     MAX_RECONNECTIONS_PER_PULSE = 2,
     64    MAX_RECONNECTIONS_PER_PULSE = 4,
    6365
    6466    /* max number of peers to ask for per second overall.
    6567    * this throttle is to avoid overloading the router */
    66     MAX_CONNECTIONS_PER_SECOND = 4,
     68    MAX_CONNECTIONS_PER_SECOND = 8,
    6769
    6870    /* number of unchoked peers per torrent.
     
    7173
    7274    /* number of bad pieces a peer is allowed to send before we ban them */
    73     MAX_BAD_PIECES_PER_PEER = 3,
     75    MAX_BAD_PIECES_PER_PEER = 5,
    7476
    7577    /* use for bitwise operations w/peer_atom.myflags */
     
    10261028            if( peer )
    10271029                tr_rcTransferred ( peer->rawSpeed[dir], e->length );
    1028             tr_rcTransferred ( tor->rawSpeed[dir], e->length );
    1029             tr_rcTransferred ( tor->session->rawSpeed[dir], e->length );
    10301030
    10311031            /* maybe add it to the piece upload speed */
     
    10331033                if( peer )
    10341034                    tr_rcTransferred ( peer->pieceSpeed[dir], e->length );
    1035                 tr_rcTransferred ( tor->pieceSpeed[dir], e->length );
    1036                 tr_rcTransferred ( tor->session->pieceSpeed[dir], e->length );
    10371035            }
     1036
     1037            tr_bandwidthUsed( tor->bandwidth[dir], e->length, e->wasPieceData );
     1038            tr_bandwidthUsed( tor->session->bandwidth[dir], e->length, e->wasPieceData );
    10381039
    10391040            /* update the stats */
     
    10701071            if( peer )
    10711072                tr_rcTransferred ( peer->rawSpeed[dir], e->length );
    1072             tr_rcTransferred ( tor->rawSpeed[dir], e->length );
    1073             tr_rcTransferred ( tor->session->rawSpeed[dir], e->length );
    10741073
    10751074            /* maybe add it to the piece upload speed */
     
    10771076                if( peer )
    10781077                    tr_rcTransferred ( peer->pieceSpeed[dir], e->length );
    1079                 tr_rcTransferred ( tor->pieceSpeed[dir], e->length );
    1080                 tr_rcTransferred ( tor->session->pieceSpeed[dir], e->length );
    10811078            }
     1079
     1080            tr_bandwidthUsed( tor->bandwidth[dir], e->length, e->wasPieceData );
     1081            tr_bandwidthUsed( tor->session->bandwidth[dir], e->length, e->wasPieceData );
    10821082     
    10831083            /* update the stats */
     
    19401940            n->isInterested = peer->peerIsInterested;
    19411941            n->isChoked     = peer->peerIsChoked;
    1942             n->rate = (int)(tr_peerGetPieceSpeed( peer, TR_CLIENT_TO_PEER )
    1943                             + tr_peerGetPieceSpeed( peer, TR_PEER_TO_CLIENT ) );
     1942            n->rate         = tr_peerGetPieceSpeed( peer, TR_CLIENT_TO_PEER ) * 1024;
    19441943        }
    19451944    }
     
    23582357****/
    23592358
    2360 #if 0
    2361 #define DEBUG_DIRECTION TR_UP
     2359static void
     2360pumpAllPeers( tr_peerMgr * mgr )
     2361{
     2362    const int torrentCount = tr_ptrArraySize( mgr->torrents );
     2363    int       i, j;
     2364
     2365    for( i = 0; i < torrentCount; ++i )
     2366    {
     2367        Torrent * t = tr_ptrArrayNth( mgr->torrents, i );
     2368        for( j = 0; j < tr_ptrArraySize( t->peers ); ++j )
     2369        {
     2370            tr_peer * peer = tr_ptrArrayNth( t->peers, j );
     2371            tr_peerMsgsPulse( peer->msgs );
     2372        }
     2373    }
     2374}
     2375
     2376static void
     2377setTorrentBandwidth( Torrent * t,
     2378                     tr_direction dir,
     2379                     tr_bandwidth * bandwidth )
     2380{
     2381    int i;
     2382    int peerCount = 0;
     2383    tr_peer ** peers = getConnectedPeers( t, &peerCount );
     2384
     2385    for( i=0; i<peerCount; ++i )
     2386        tr_peerIoSetBandwidth( peers[i]->io, dir, bandwidth );
     2387
     2388    tr_free( peers );
     2389}
     2390
     2391#if 1
     2392#define DEBUG_DIRECTION TR_DOWN
    23622393#endif
    23632394
     
    23792410    const double desired_bytes_per_pulse = bytesPerPulse( desiredSpeed );
    23802411    const double min = desired_bytes_per_pulse * 0.90;
    2381     const double max = desired_bytes_per_pulse * 1.25;
     2412    const double max = desired_bytes_per_pulse * 1.50;
    23822413    const double next_pulse_bytes = desired_bytes_per_pulse * ( pulses_per_history + 1 )
    23832414                                  - ( current_bytes_per_pulse * pulses_per_history );
     
    23912422#ifdef DEBUG_DIRECTION
    23922423if( dir == DEBUG_DIRECTION )
    2393 fprintf( stderr, "currentSpeed(%5.2f) desiredSpeed(%5.2f), allocating %5.2f (%5.2f)\n",
     2424fprintf( stderr, "currentSpeed(%5.2f) desiredSpeed(%5.2f), allocating %5.2f (unclamped: %5.2f)\n",
    23942425         currentSpeed,
    23952426         desiredSpeed,
     
    24002431    return clamped;
    24012432}
    2402 /**
    2403  * Distributes a fixed amount of bandwidth among a set of peers.
    2404  *
    2405  * @param peerArray peers whose client-to-peer bandwidth will be set
    2406  * @param direction whether to allocate upload or download bandwidth
    2407  * @param currentSpeed current speed in KiB/s for this set of peers
    2408  * @param desiredSpeed desired speed in KiB/s for this set of peers
    2409  */
    2410 static void
    2411 setPeerBandwidth( tr_ptrArray          * peerArray,
    2412                   const tr_direction     direction,
    2413                   double                 currentSpeed,
    2414                   double                 desiredSpeed )
    2415 {
    2416     const int    MINIMUM_WELFARE_BYTES = bytesPerPulse( 5 );
    2417     int          i;
    2418     double       welfare;
    2419     double       meritBytes;
    2420     double       meritMultiplier;
    2421     double       welfareBytes;
    2422     const int    peerCount      = tr_ptrArraySize( peerArray );
    2423     const double bytes          = allocateHowMuch( direction, currentSpeed, desiredSpeed );
    2424     tr_peer **   peers          = (tr_peer**) tr_ptrArrayBase( peerArray );
    2425 
    2426     /* how many bytes we'll allocate based on merit.
    2427      *
    2428      * 1. When just getting started we want to give all the peers a lot
    2429      *    of `welfare' allocation because we don't know which ones will
    2430      *    turn out to be productive for us.
    2431      *
    2432      * 2. When we've reached steady state and are near our bandwidth limit,
    2433      *    the bandwidth spent on `welfare' is going to come from peers that
    2434      *    we already know are productive... which is probably a waste.
    2435      *
    2436      * 3. So we tie the merit/welfare allocations to the current speed.
    2437      *    the closer the current speed gets to the maximum speed, the less
    2438      *    welfare we allocate.
    2439      *
    2440      * 4. We always need to allocate /some/ welfare bytes, otherwise
    2441      *    the other peers will starve.
    2442      */
    2443     meritBytes = bytesPerPulse( MIN( currentSpeed * 1.2, desiredSpeed ) );
    2444     welfareBytes = bytes > meritBytes ?  bytes - meritBytes : 0;
    2445     if( welfareBytes < MINIMUM_WELFARE_BYTES )
    2446         welfareBytes = MINIMUM_WELFARE_BYTES;
    2447     meritBytes = bytes - welfareBytes;
    2448     meritMultiplier = currentSpeed > 0.01 ?  meritBytes / currentSpeed : 0.0;
    2449 
    2450 #ifdef DEBUG_DIRECTION
    2451 if( direction == DEBUG_DIRECTION )
    2452 fprintf( stderr, "currentSpeed(%5.2f) desiredSpeed(%5.2f) - k[%.1f] merit [%.1f] welfare [%.1f]\n", currentSpeed, desiredSpeed, bytes/1024.0, meritBytes/1024.0, welfareBytes/1024.0 );
    2453 #endif
    2454 
    2455     /* how much welfare each peer gets */
    2456     welfare = welfareBytes / peerCount;
    2457 
    2458     for( i=0; i<peerCount; ++i )
    2459     {
    2460         tr_peer * peer = peers[i];
    2461         const size_t merit = tr_rcRate( peers[i]->pieceSpeed[direction] ) * meritMultiplier;
    2462         tr_peerIoAllocateBandwidth( peer->io, direction, merit + welfare );
    2463     }
    2464 }
    2465 
    2466 static void
    2467 givePeersUnlimitedBandwidth( tr_ptrArray * peers,
    2468                              tr_direction  direction )
    2469 {
    2470     const int n = tr_ptrArraySize( peers );
    2471     int       i;
    2472 
    2473     for( i = 0; i < n; ++i )
    2474     {
    2475         tr_peer * peer = tr_ptrArrayNth( peers, i );
    2476         tr_peerIoSetBandwidthUnlimited( peer->io, direction );
    2477     }
    2478 }
    2479 
    2480 static void
    2481 pumpAllPeers( tr_peerMgr * mgr )
    2482 {
    2483     const int torrentCount = tr_ptrArraySize( mgr->torrents );
    2484     int       i, j;
    2485 
    2486     for( i = 0; i < torrentCount; ++i )
    2487     {
    2488         Torrent * t = tr_ptrArrayNth( mgr->torrents, i );
    2489         for( j = 0; j < tr_ptrArraySize( t->peers ); ++j )
    2490         {
    2491             tr_peer * peer = tr_ptrArrayNth( t->peers, j );
    2492             tr_peerMsgsPulse( peer->msgs );
    2493         }
    2494     }
    2495 }
    2496 
    2497 static void
    2498 getBandwidthPeers( Torrent       * t,
    2499                    tr_direction    dir,
    2500                    tr_ptrArray   * appendme,
    2501                    double        * speed )
    2502 {
    2503     int i, peerCount;
    2504     tr_peer ** peers;
    2505 
    2506     assert( t );
    2507     assert( torrentIsLocked( t ) );
    2508     assert( dir == TR_UP || dir == TR_DOWN );
    2509     assert( appendme );
    2510     assert( speed );
    2511 
    2512     peers = (tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount );
    2513 
    2514     for( i=0; i<peerCount; ++i )
    2515     {
    2516         tr_peer * p = peers[i];
    2517 
    2518         if( p->msgs )
    2519         {
    2520             if( ( ( dir == TR_DOWN ) && clientIsDownloadingFrom( p ) ) || ( ( dir == TR_UP ) && clientIsUploadingTo( p ) ) )
    2521             {
    2522                 tr_ptrArrayAppend( appendme, p );
    2523                 *speed += tr_rcRate( p->pieceSpeed[dir] );
    2524             }
    2525         }
    2526     }
    2527 }
    25282433
    25292434/**
     
    25322437 * @param mgr the peer manager
    25332438 * @param direction whether to allocate upload or download bandwidth
    2534  * @return the amount of directional bandwidth used since the last pulse.
    25352439 */
    25362440static void
     
    25382442                   tr_direction direction )
    25392443{
    2540     tr_session *  session = mgr->session;
    2541     const int     torrentCount = tr_ptrArraySize( mgr->torrents );
    2542     Torrent **    torrents = (Torrent **) tr_ptrArrayBase( mgr->torrents );
    2543     tr_ptrArray * globalPool = tr_ptrArrayNew( );
    2544     double        globalPoolSpeed = 0;
    2545     int           i;
     2444    int              i;
     2445    tr_session     * session = mgr->session;
     2446    const int        torrentCount = tr_ptrArraySize( mgr->torrents );
     2447    Torrent       ** torrents = (Torrent **) tr_ptrArrayBase( mgr->torrents );
     2448    tr_bandwidth   * global_pool = session->bandwidth[direction];
    25462449
    25472450    assert( mgr );
     
    25712474        {
    25722475            case TR_SPEEDLIMIT_UNLIMITED:
    2573                 givePeersUnlimitedBandwidth( t->peers, direction );
    2574                 break;
    2575 
    2576             case TR_SPEEDLIMIT_SINGLE: {
    2577                 tr_ptrArray * peers = tr_ptrArrayNew( );
    2578                 double speed = 0;
    2579                 getBandwidthPeers( t, direction, peers, &speed );
    2580                 setPeerBandwidth( peers, direction, speed, tr_torrentGetSpeedLimit( t->tor, direction ) );
    2581                 tr_ptrArrayFree( peers, NULL );
     2476            {
     2477                tr_bandwidth * b = t->tor->bandwidth[direction];
     2478                tr_bandwidthSetUnlimited( b );
     2479                setTorrentBandwidth( t, direction, b );
    25822480                break;
    25832481            }
    25842482
     2483            case TR_SPEEDLIMIT_SINGLE:
     2484            {
     2485                tr_bandwidth * b = t->tor->bandwidth[direction];
     2486                const double currentSpeed = tr_bandwidthGetPieceSpeed( b );
     2487                const double desiredSpeed = tr_torrentGetSpeedLimit( t->tor, direction );
     2488                const double bytesPerPulse = allocateHowMuch( direction, currentSpeed, desiredSpeed );
     2489#ifdef DEBUG_DIRECTION
     2490if( direction == DEBUG_DIRECTION )
     2491fprintf( stderr, "single: currentSpeed %.0f ... desiredSpeed %.0f ... bytesPerPulse %.0f\n", currentSpeed, desiredSpeed, bytesPerPulse );
     2492#endif
     2493                tr_bandwidthSetLimited( b, bytesPerPulse );
     2494                setTorrentBandwidth( t, direction, b );
     2495                break;
     2496            }
     2497
    25852498            case TR_SPEEDLIMIT_GLOBAL:
    2586                 getBandwidthPeers( t, direction, globalPool, &globalPoolSpeed );
     2499            {
     2500                setTorrentBandwidth( t, direction, global_pool );
    25872501                break;
     2502            }
    25882503        }
    25892504    }
     
    25912506    /* handle the global pool's connections */
    25922507    if( !tr_sessionIsSpeedLimitEnabled( session, direction ) )
    2593         givePeersUnlimitedBandwidth( globalPool, direction );
    2594     else
    2595         setPeerBandwidth( globalPool, direction, globalPoolSpeed,
    2596                           tr_sessionGetSpeedLimit( session, direction ) );
     2508        tr_bandwidthSetUnlimited( global_pool );
     2509    else {
     2510        const double currentSpeed = tr_bandwidthGetPieceSpeed( global_pool );
     2511        const double desiredSpeed = tr_sessionGetSpeedLimit( session, direction );
     2512        const double bytesPerPulse = allocateHowMuch( direction, currentSpeed, desiredSpeed );
     2513#ifdef DEBUG_DIRECTION
     2514if( direction == DEBUG_DIRECTION )
     2515fprintf( stderr, "global(%p): currentSpeed %.0f ... desiredSpeed %.0f ... bytesPerPulse %.0f\n", global_pool, currentSpeed, desiredSpeed, bytesPerPulse );
     2516#endif
     2517        tr_bandwidthSetLimited( session->bandwidth[direction], bytesPerPulse );
     2518    }
    25972519
    25982520    /* now that we've allocated bandwidth, pump all the connected peers */
    25992521    pumpAllPeers( mgr );
    2600 
    2601     /* cleanup */
    2602     tr_ptrArrayFree( globalPool, NULL );
    26032522}
    26042523
     
    26182537    return TRUE;
    26192538}
    2620 
  • trunk/libtransmission/peer-msgs.c

    r7136 r7147  
    16321632}
    16331633
     1634static int peerPulse( void * vmsgs );
     1635
    16341636static void
    16351637didWrite( tr_peerIo * io UNUSED, size_t bytesWritten, int wasPieceData, void * vmsgs )
     
    16371639    tr_peermsgs * msgs = vmsgs;
    16381640    firePeerGotData( msgs, bytesWritten, wasPieceData );
     1641    peerPulse( msgs );
    16391642}
    16401643
     
    16991702                  ( rateToClient * 30 * 1024 ) / peer->torrent->blockSize;
    17001703
    1701     peer->minActiveRequests = 4;
     1704    peer->minActiveRequests = 8;
    17021705    peer->maxActiveRequests = peer->minActiveRequests + estimatedBlocksInNext30Seconds;
    17031706    return TRUE;
  • trunk/libtransmission/session.c

    r7133 r7147  
    2222
    2323#include "transmission.h"
     24#include "bandwidth.h"
    2425#include "blocklist.h"
    2526#include "fdlimit.h"
     
    3031#include "platform.h" /* tr_lock */
    3132#include "port-forwarding.h"
    32 #include "ratecontrol.h"
    3333#include "rpc-server.h"
    3434#include "stats.h"
     
    255255    h->proxyUsername = tr_strdup( proxyUsername );
    256256    h->proxyPassword = tr_strdup( proxyPassword );
    257     h->pieceSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
    258     h->pieceSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
    259     h->rawSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
    260     h->rawSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
    261257    h->so_sndbuf = 1500 * 3; /* 3x MTU for most ethernet/wireless */
     258    h->so_rcvbuf = 8192;
    262259
    263260    if( configDir == NULL )
     
    286283    h->shared = tr_sharedInit( h, isPortForwardingEnabled, publicPort );
    287284    h->isPortSet = publicPort >= 0;
     285
     286    h->bandwidth[TR_UP] = tr_bandwidthNew( h );
     287    h->bandwidth[TR_DOWN] = tr_bandwidthNew( h );
    288288
    289289    /* first %s is the application name
     
    508508    assert( dir==TR_UP || dir==TR_DOWN );
    509509
    510     return session ? tr_rcRate( session->pieceSpeed[dir] ) : 0.0;
     510    return session ? tr_bandwidthGetPieceSpeed( session->bandwidth[dir] ) : 0.0;
    511511}
    512512
     
    516516    assert( dir==TR_UP || dir==TR_DOWN );
    517517
    518     return session ? tr_rcRate( session->rawSpeed[dir] ) : 0.0;
     518    return session ? tr_bandwidthGetPieceSpeed( session->bandwidth[dir] ) : 0.0;
    519519}
    520520
     
    630630
    631631    /* free the session memory */
    632     tr_rcClose( session->pieceSpeed[TR_PEER_TO_CLIENT] );
    633     tr_rcClose( session->pieceSpeed[TR_CLIENT_TO_PEER] );
    634     tr_rcClose( session->rawSpeed[TR_PEER_TO_CLIENT] );
    635     tr_rcClose( session->rawSpeed[TR_CLIENT_TO_PEER] );
     632    tr_bandwidthFree( session->bandwidth[TR_UP] );
     633    tr_bandwidthFree( session->bandwidth[TR_DOWN] );
    636634    tr_lockFree( session->lock );
    637635    for( i = 0; i < session->metainfoLookupCount; ++i )
  • trunk/libtransmission/session.h

    r7133 r7147  
    4949};
    5050
    51 struct tr_ratecontrol;
     51struct tr_bandwidth;
    5252
    5353struct tr_handle
     
    109109    int so_sndbuf;
    110110
    111     /* the rate at which pieces are being transferred between client and peer.
    112      * protocol overhead is NOT included; this is only the piece data */
    113     struct tr_ratecontrol     *  pieceSpeed[2];
     111    /* the size of the input buffer for peer connections */
     112    int so_rcvbuf;
    114113
    115     /* the rate at which bytes are being transferred between client and peer. */
    116     struct tr_ratecontrol     *  rawSpeed[2];
     114    /* monitors the "global pool" speeds */
     115    struct tr_bandwidth       * bandwidth[2];
    117116};
    118117
  • trunk/libtransmission/torrent.c

    r7069 r7147  
    3333
    3434#include "transmission.h"
     35#include "bandwidth.h"
    3536#include "bencode.h"
    3637#include "completion.h"
     
    497498    randomizeTiers( info );
    498499
    499     tor->rawSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
    500     tor->rawSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
    501     tor->pieceSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
    502     tor->pieceSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
     500    tor->bandwidth[TR_UP] = tr_bandwidthNew( h );
     501    tor->bandwidth[TR_DOWN] = tr_bandwidthNew( h );
    503502
    504503    tor->blockSize = getBlockSize( info->pieceSize );
     
    815814                            s->peersFrom );
    816815
    817     s->rawUploadSpeed     = tr_rcRate( tor->rawSpeed[TR_UP] );
    818     s->rawDownloadSpeed   = tr_rcRate( tor->rawSpeed[TR_DOWN] );
    819     s->pieceUploadSpeed   = tr_rcRate( tor->pieceSpeed[TR_UP] );
    820     s->pieceDownloadSpeed = tr_rcRate( tor->pieceSpeed[TR_DOWN] );
     816    s->rawUploadSpeed     = tr_bandwidthGetRawSpeed  ( tor->bandwidth[TR_UP] );
     817    s->rawDownloadSpeed   = tr_bandwidthGetRawSpeed  ( tor->bandwidth[TR_DOWN] );
     818    s->pieceUploadSpeed   = tr_bandwidthGetPieceSpeed( tor->bandwidth[TR_UP] );
     819    s->pieceDownloadSpeed = tr_bandwidthGetPieceSpeed( tor->bandwidth[TR_DOWN] );
    821820
    822821    usableSeeds += tor->info.webseedCount;
     
    11011100    h->torrentCount--;
    11021101
    1103     tr_rcClose( tor->pieceSpeed[TR_PEER_TO_CLIENT] );
    1104     tr_rcClose( tor->pieceSpeed[TR_CLIENT_TO_PEER] );
    1105     tr_rcClose( tor->rawSpeed[TR_PEER_TO_CLIENT] );
    1106     tr_rcClose( tor->rawSpeed[TR_CLIENT_TO_PEER] );
     1102    tr_bandwidthFree( tor->bandwidth[TR_DOWN] );
     1103    tr_bandwidthFree( tor->bandwidth[TR_UP] );
    11071104
    11081105    tr_metainfoFree( inf );
  • trunk/libtransmission/torrent.h

    r7069 r7147  
    2626#define TR_TORRENT_H 1
    2727
     28struct tr_bandwidth;
    2829struct tr_ratecontrol;
    2930
     
    230231    int                        uniqueId;
    231232
    232     /* the rate at which pieces are being transferred between client and
    233      * its peers.  protocol overhead is NOT included; only the piece data */
    234     struct tr_ratecontrol    * pieceSpeed[2];
    235 
    236     /* the rate at which bytes are being sent between client and peers */
    237     struct tr_ratecontrol    * rawSpeed[2];
     233    struct tr_bandwidth      * bandwidth[2];
    238234};
    239235
Note: See TracChangeset for help on using the changeset viewer.