Changeset 7137
- Timestamp:
- Nov 23, 2008, 4:31:28 PM (14 years ago)
- Location:
- trunk/libtransmission
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/peer-io.c
r7133 r7137 31 31 #include "net.h" 32 32 #include "peer-io.h" 33 #include "ratecontrol.h"34 33 #include "trevent.h" 35 34 #include "utils.h" … … 73 72 struct tr_bandwidth 74 73 { 75 unsigned int isUnlimited : 1; 76 size_t bytesUsed; 77 size_t bytesLeft; 74 unsigned int isUnlimited : 1; 75 size_t bytesLeft; 78 76 }; 79 77 … … 221 219 struct tr_bandwidth * b = &io->bandwidth[TR_UP]; 222 220 b->bytesLeft -= MIN( b->bytesLeft, n ); 223 b->bytesUsed += n;224 221 } 225 222 … … 257 254 struct tr_bandwidth * b = io->bandwidth + TR_DOWN; 258 255 b->bytesLeft -= MIN( b->bytesLeft, (size_t)n ); 259 b->bytesUsed += n; 260 dbgmsg( io, "%zu new input bytes. bytesUsed is %zu, bytesLeft is %zu", n, b->bytesUsed, b->bytesLeft ); 256 dbgmsg( io, "%zu new input bytes. bytesLeft is %zu", n, b->bytesLeft ); 261 257 262 258 adjustInputBuffer( io ); … … 617 613 618 614 size_t 619 tr_peerIoGetBandwidthUsed( const tr_peerIo * io,620 tr_direction direction )621 {622 assert( io );623 assert( direction == TR_UP || direction == TR_DOWN );624 return io->bandwidth[direction].bytesUsed;625 }626 627 size_t628 615 tr_peerIoGetWriteBufferSpace( const tr_peerIo * io ) 629 616 { … … 650 637 651 638 void 652 tr_peerIo SetBandwidth( tr_peerIo *io,653 tr_directiondirection,654 size_tbytesLeft )639 tr_peerIoAllocateBandwidth( tr_peerIo * io, 640 tr_direction direction, 641 size_t bytesLeft ) 655 642 { 656 643 struct tr_bandwidth * b; … … 661 648 b = io->bandwidth + direction; 662 649 b->isUnlimited = 0; 663 b->bytesUsed = 0;664 650 b->bytesLeft = bytesLeft; 665 651 … … 679 665 b = io->bandwidth + direction; 680 666 b->isUnlimited = 1; 681 b->bytesUsed = 0;682 667 b->bytesLeft = 0; 683 668 … … 883 868 return time( NULL ) - io->timeCreated; 884 869 } 885 -
trunk/libtransmission/peer-io.h
r7133 r7137 199 199 **/ 200 200 201 size_t tr_peerIoGetBandwidthUsed( const tr_peerIo * io,202 tr_direction direction );203 204 201 size_t tr_peerIoGetWriteBufferSpace( const tr_peerIo * io ); 205 202 206 void tr_peerIo SetBandwidth( tr_peerIo * io,207 tr_direction direction,208 size_t bytesLeft );203 void tr_peerIoAllocateBandwidth( tr_peerIo * io, 204 tr_direction direction, 205 size_t bytesLeft ); 209 206 210 207 void tr_peerIoSetBandwidthUnlimited( tr_peerIo * io, -
trunk/libtransmission/peer-mgr.c
r7132 r7137 68 68 /* number of unchoked peers per torrent. 69 69 * FIXME: this probably ought to be configurable */ 70 MAX_UNCHOKED_PEERS = 1 2,70 MAX_UNCHOKED_PEERS = 14, 71 71 72 72 /* number of bad pieces a peer is allowed to send before we ban them */ … … 131 131 tr_ptrArray * incomingHandshakes; /* tr_handshake */ 132 132 tr_timer * bandwidthTimer; 133 tr_ratecontrol * globalPoolRawSpeed[2];134 133 }; 135 134 … … 521 520 m->torrents = tr_ptrArrayNew( ); 522 521 m->incomingHandshakes = tr_ptrArrayNew( ); 523 m->globalPoolRawSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );524 m->globalPoolRawSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );525 522 m->bandwidthTimer = tr_timerNew( session, bandwidthPulse, m, BANDWIDTH_PERIOD_MSEC ); 526 523 return m; … … 533 530 534 531 tr_timerFree( &manager->bandwidthTimer ); 535 tr_rcClose( manager->globalPoolRawSpeed[TR_CLIENT_TO_PEER] );536 tr_rcClose( manager->globalPoolRawSpeed[TR_PEER_TO_CLIENT] );537 532 538 533 /* free the handshakes. Abort invokes handshakeDoneCB(), which removes … … 2363 2358 ****/ 2364 2359 2360 #if 0 2361 #define DEBUG_DIRECTION TR_UP 2362 #endif 2363 2365 2364 static double 2366 allocateHowMuch( double desired_average_kb_per_sec, 2367 const tr_ratecontrol * ratecontrol ) 2365 bytesPerPulse( double KiB_per_second ) 2366 { 2367 return KiB_per_second * ( 1024.0 * BANDWIDTH_PERIOD_MSEC / 1000.0 ); 2368 } 2369 2370 /* 2371 * @param currentSpeed current speed in KiB/s 2372 * @param desiredSpeed desired speed in KiB/s 2373 */ 2374 static double 2375 allocateHowMuch( tr_direction dir UNUSED, double currentSpeed, double desiredSpeed ) 2368 2376 { 2369 2377 const int pulses_per_history = TR_RATECONTROL_HISTORY_MSEC / BANDWIDTH_PERIOD_MSEC; 2370 const double seconds_per_pulse = BANDWIDTH_PERIOD_MSEC / 1000.0; 2371 const double baseline_bytes_per_pulse = desired_average_kb_per_sec * 1024.0 * seconds_per_pulse; 2372 const double min = baseline_bytes_per_pulse * 0.80; 2373 const double max = baseline_bytes_per_pulse * 1.20; 2374 const double current_bytes_per_pulse = tr_rcRate( ratecontrol ) * 1024.0 * seconds_per_pulse; 2375 const double next_pulse_bytes = baseline_bytes_per_pulse * ( pulses_per_history + 1 ) 2378 const double current_bytes_per_pulse = bytesPerPulse( currentSpeed ); 2379 const double desired_bytes_per_pulse = bytesPerPulse( desiredSpeed ); 2380 const double min = desired_bytes_per_pulse * 0.90; 2381 const double max = desired_bytes_per_pulse * 1.25; 2382 const double next_pulse_bytes = desired_bytes_per_pulse * ( pulses_per_history + 1 ) 2376 2383 - ( current_bytes_per_pulse * pulses_per_history ); 2377 2384 double clamped; … … 2382 2389 clamped = MIN( clamped, max ); 2383 2390 2384 #if 0 2385 fprintf( stderr, "desiredAvgKB is %5.2f, rate is %5.2f, allocating %5.2f (%5.2f)\n", 2386 desired_average_kb_per_sec, 2387 tr_rcRate( ratecontrol ), 2391 #ifdef DEBUG_DIRECTION 2392 if( dir == DEBUG_DIRECTION ) 2393 fprintf( stderr, "currentSpeed(%5.2f) desiredSpeed(%5.2f), allocating %5.2f (%5.2f)\n", 2394 currentSpeed, 2395 desiredSpeed, 2388 2396 clamped/1024.0, 2389 2397 next_pulse_bytes/1024.0 ); … … 2392 2400 return clamped; 2393 2401 } 2394 2395 2402 /** 2396 2403 * Distributes a fixed amount of bandwidth among a set of peers. … … 2398 2405 * @param peerArray peers whose client-to-peer bandwidth will be set 2399 2406 * @param direction whether to allocate upload or download bandwidth 2400 * @param history recent bandwidth history for thesepeers2401 * @param desired AvgKB overall bandwidth goalfor this set of peers2407 * @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 2402 2409 */ 2403 2410 static void 2404 2411 setPeerBandwidth( tr_ptrArray * peerArray, 2405 2412 const tr_direction direction, 2406 const tr_ratecontrol * ratecontrol, 2407 double desiredAvgKB ) 2408 { 2409 const int peerCount = tr_ptrArraySize( peerArray ); 2410 const double bytes = allocateHowMuch( desiredAvgKB, ratecontrol ); 2411 const double welfareBytes = MIN( 2048, bytes * 0.2 ); 2412 const double meritBytes = MAX( 0, bytes - welfareBytes ); 2413 tr_peer ** peers = (tr_peer**) tr_ptrArrayBase( peerArray ); 2413 double currentSpeed, 2414 double desiredSpeed ) 2415 { 2416 const int MINIMUM_WELFARE_BYTES = bytesPerPulse( 5 ); 2414 2417 int i; 2415 2418 double welfare; 2416 size_t bytesUsed; 2417 2418 assert( meritBytes >= 0.0 ); 2419 assert( welfareBytes >= 0.0 ); 2420 assert( direction == TR_UP || direction == TR_DOWN ); 2421 2422 for( i=bytesUsed=0; i<peerCount; ++i ) 2423 bytesUsed += tr_peerIoGetBandwidthUsed( peers[i]->io, direction ); 2424 2425 welfare = welfareBytes / peerCount; 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; 2426 2457 2427 2458 for( i=0; i<peerCount; ++i ) 2428 2459 { 2429 2460 tr_peer * peer = peers[i]; 2430 const double merit = bytesUsed 2431 ? ( meritBytes * tr_peerIoGetBandwidthUsed( peer->io, direction ) ) / bytesUsed 2432 : ( meritBytes / peerCount ); 2433 tr_peerIoSetBandwidth( peer->io, direction, merit + welfare ); 2434 } 2435 } 2436 2437 static size_t 2438 countHandshakeBandwidth( tr_ptrArray * handshakes, 2439 tr_direction direction ) 2440 { 2441 const int n = tr_ptrArraySize( handshakes ); 2442 int i; 2443 size_t total; 2444 2445 for( i = total = 0; i < n; ++i ) 2446 { 2447 tr_peerIo * io = tr_handshakeGetIO( tr_ptrArrayNth( handshakes, i ) ); 2448 total += tr_peerIoGetBandwidthUsed( io, direction ); 2449 } 2450 return total; 2451 } 2452 2453 static size_t 2454 countPeerBandwidth( tr_ptrArray * peers, 2455 tr_direction direction ) 2456 { 2457 const int n = tr_ptrArraySize( peers ); 2458 int i; 2459 size_t total; 2460 2461 for( i = total = 0; i < n; ++i ) 2462 { 2463 tr_peer * peer = tr_ptrArrayNth( peers, i ); 2464 total += tr_peerIoGetBandwidthUsed( peer->io, direction ); 2465 } 2466 return total; 2461 const size_t merit = tr_rcRate( peers[i]->pieceSpeed[direction] ) * meritMultiplier; 2462 tr_peerIoAllocateBandwidth( peer->io, direction, merit + welfare ); 2463 } 2467 2464 } 2468 2465 … … 2500 2497 static void 2501 2498 getBandwidthPeers( Torrent * t, 2502 tr_direction direction, 2503 tr_ptrArray * appendme ) 2499 tr_direction dir, 2500 tr_ptrArray * appendme, 2501 double * speed ) 2504 2502 { 2505 2503 int i, peerCount; 2506 2504 tr_peer ** peers; 2507 2505 2506 assert( t ); 2508 2507 assert( torrentIsLocked( t ) ); 2508 assert( dir == TR_UP || dir == TR_DOWN ); 2509 assert( appendme ); 2510 assert( speed ); 2509 2511 2510 2512 peers = (tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount ); 2511 2513 2512 2514 for( i=0; i<peerCount; ++i ) 2513 if( peers[i]->msgs ) 2514 if( ( ( direction == TR_PEER_TO_CLIENT ) && clientIsDownloadingFrom( peers[i] ) ) 2515 || ( ( direction == TR_CLIENT_TO_PEER ) && clientIsUploadingTo( peers[i] ) ) ) 2516 tr_ptrArrayAppend( appendme, peers[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 } 2517 2527 } 2518 2528 … … 2524 2534 * @return the amount of directional bandwidth used since the last pulse. 2525 2535 */ 2526 static double2536 static void 2527 2537 allocateBandwidth( tr_peerMgr * mgr, 2528 2538 tr_direction direction ) … … 2532 2542 Torrent ** torrents = (Torrent **) tr_ptrArrayBase( mgr->torrents ); 2533 2543 tr_ptrArray * globalPool = tr_ptrArrayNew( ); 2534 double allBytesUsed = 0; 2535 size_t poolBytesUsed = 0; 2544 double globalPoolSpeed = 0; 2536 2545 int i; 2537 2546 … … 2545 2554 { 2546 2555 Torrent * t = torrents[i]; 2547 size_t used;2548 2556 tr_speedlimit speedMode; 2549 2557 … … 2551 2559 if( tr_torrentGetActivity( t->tor ) == TR_STATUS_STOPPED ) 2552 2560 continue; 2553 2554 used = countPeerBandwidth( t->peers, direction );2555 countHandshakeBandwidth( t->outgoingHandshakes, direction );2556 2557 /* remember this torrent's bytes used */2558 tr_rcTransferred( t->tor->rawSpeed[direction], used );2559 2560 /* add this torrent's bandwidth use to allBytesUsed */2561 allBytesUsed += used;2562 2561 2563 2562 /* if piece data is disallowed, don't bother limiting bandwidth -- … … 2575 2574 break; 2576 2575 2577 case TR_SPEEDLIMIT_SINGLE: 2578 { 2576 case TR_SPEEDLIMIT_SINGLE: { 2579 2577 tr_ptrArray * peers = tr_ptrArrayNew( ); 2580 getBandwidthPeers( t, direction, peers ); 2581 setPeerBandwidth( peers, direction, 2582 t->tor->rawSpeed[direction], 2583 tr_torrentGetSpeedLimit( t->tor, direction ) ); 2578 double speed = 0; 2579 getBandwidthPeers( t, direction, peers, &speed ); 2580 setPeerBandwidth( peers, direction, speed, tr_torrentGetSpeedLimit( t->tor, direction ) ); 2584 2581 tr_ptrArrayFree( peers, NULL ); 2585 2582 break; … … 2587 2584 2588 2585 case TR_SPEEDLIMIT_GLOBAL: 2589 getBandwidthPeers( t, direction, globalPool ); 2590 poolBytesUsed += used; 2586 getBandwidthPeers( t, direction, globalPool, &globalPoolSpeed ); 2591 2587 break; 2592 2588 } 2593 2589 } 2594 2595 /* add incoming handshakes to the global pool */2596 i = countHandshakeBandwidth( mgr->incomingHandshakes, direction );2597 allBytesUsed += i;2598 poolBytesUsed += i;2599 2600 tr_rcTransferred( mgr->globalPoolRawSpeed[direction], poolBytesUsed );2601 2590 2602 2591 /* handle the global pool's connections */ … … 2604 2593 givePeersUnlimitedBandwidth( globalPool, direction ); 2605 2594 else 2606 setPeerBandwidth( globalPool, direction, 2607 mgr->globalPoolRawSpeed[direction], 2595 setPeerBandwidth( globalPool, direction, globalPoolSpeed, 2608 2596 tr_sessionGetSpeedLimit( session, direction ) ); 2609 2597 … … 2613 2601 /* cleanup */ 2614 2602 tr_ptrArrayFree( globalPool, NULL ); 2615 return allBytesUsed;2616 2603 } 2617 2604
Note: See TracChangeset
for help on using the changeset viewer.