Ignore:
Timestamp:
Dec 20, 2008, 10:19:34 PM (12 years ago)
Author:
charles
Message:

try to rework the bandwidth code yet again s.t. it satisfies all three: (1) fairly distributes bandwidth across all peers, (2) scales well in high-bandwidth situations, (3) is good at hitting and staying at bandwidth limits/goals

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/bandwidth.c

    r7433 r7441  
    295295                      int             period_msec )
    296296{
    297     int n;
     297    int i, n, peerCount;
    298298    tr_ptrArray * tmp;
    299299    struct tr_peerIo ** peers;
    300300
     301    /* allocateBandwidth() is a helper function with two purposes:
     302     * 1. allocate bandwidth to b and its subtree
     303     * 2. accumulate an array of all the peerIos from b and its subtree. */
    301304    tmp = tr_ptrArrayNew( );
    302305    allocateBandwidth( b, dir, period_msec, tmp );
    303     peers = (struct tr_peerIo**) tr_ptrArrayPeek( tmp, &n );
    304 
    305     /* loop through all the peers, reading and writing in small chunks,
    306      * until we run out of bandwidth or peers. we do it this way to
    307      * prevent one peer from using up all the bandwidth */
    308 #if 0
    309 fprintf( stderr, "%s - %d peers\n", (dir==TR_UP)?"up":"down", n );
    310 #endif
    311     while( n > 0 )
    312     {
    313         int i;
    314         for( i=0; i<n; )
    315         {
    316             const int increment = n==1 ? 4096 : 1024;
    317             const int byteCount = tr_peerIoFlush( peers[i], dir, increment);
    318 
    319 #if 0
    320             if( byteCount )
    321                 fprintf( stderr, "peer %p: %d bytes\n", peers[i], byteCount );
    322 #endif
    323 
    324             if( byteCount == increment )
    325                 ++i;
    326             else
    327                 peers[i] = peers[--n];
     306    peers = (struct tr_peerIo**) tr_ptrArrayPeek( tmp, &peerCount );
     307
     308    /* Stop all peers from listening for the socket to be ready for IO.
     309     * See "Second phase of IO" lower in this function for more info. */
     310    for( i=0; i<peerCount; ++i )
     311        tr_peerIoSetEnabled( peers[i], dir, FALSE );
     312
     313    /* First phase of IO.  Tries to distribute bandwidth in a fair/even manner
     314     * to avoid "greedy peers" from starving out the other peers: loop through
     315     * peers in a round-robin fashion, giving each one of them them small chunks
     316     * of bandwidth to use.  (It's small to conserve some of the bandwidth
     317     * until the end of the loop).  Keep looping until we run out of bandwidth
     318     * or peers that are ready to use it. */
     319    n = peerCount;
     320    i = n ? tr_cryptoWeakRandInt( n ) : 0; /* pick a random starting point */
     321    for( ; n>0; )
     322    {
     323        const int increment = n==1 ? 4096 : 1024;
     324        const int byteCount = tr_peerIoFlush( peers[i], dir, increment);
     325
     326        if( byteCount == increment )
     327            ++i;
     328        else {
     329            /* peer is done writing for now; move it to the end of the list */
     330            tr_peerIo * tmp = peers[i];
     331            peers[i] = peers[n-1];
     332            peers[n-1] = tmp;
     333            --n;
    328334        }
    329     }
     335
     336        assert( i <= n );
     337        if( i == n )
     338            i = 0;
     339    }
     340
     341    /* Second phase of IO.  To help us scale well in high bandiwdth situations
     342     * such as LANs, enable on-demand IO for peers with bandwidth left to burn.
     343     * This on-demand IO for a peer is enabled until either (1) the peer runs
     344     * out of bandwidth, or (2) the next tr_bandwidthAllocate() call, when we
     345     * start all over again. */
     346    for( i=0; i<peerCount; ++i )
     347        if( tr_peerIoHasBandwidthLeft( peers[i], dir ) )
     348            tr_peerIoSetEnabled( peers[i], dir, TRUE );
    330349
    331350    /* cleanup */
Note: See TracChangeset for help on using the changeset viewer.