Changeset d2569fa


Ignore:
Timestamp:
Oct 25, 2016 10:30:55 PM (3 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
3063e37
Parents:
8a84522
Message:

i2psnark: Don't count unchoked but uninterested peers as uploaders
when calculating global uploader limit, to allow more upload slots,
especially when some torrents are stalled.
Convert some shared fields to atomics for concurrency.

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java

    r8a84522 rd2569fa  
    6666
    6767        int uploaders = 0;
     68        int interestedUploaders = 0;
    6869        int removedCount = 0;
    6970
     
    7778        boolean overBWLimit = coordinator.overUpBWLimit();
    7879        if (_log.shouldLog(Log.DEBUG))
    79             _log.debug("peers: " + peerList.size() + " limit: " + uploadLimit + " overBW? " + overBWLimit);
     80            _log.debug("START peers: " + peerList.size() + " uploaders: " + coordinator.getUploaders() +
     81                       " interested: " + coordinator.getInterestedUploaders() +
     82                       " limit: " + uploadLimit + " overBW? " + overBWLimit);
    8083        DHT dht = _util.getDHT();
    8184        for (Peer peer : peerList) {
     
    99102            }
    100103
    101             if (!peer.isChoking())
     104            // we only count choking AND interested, so as not to steal a slot
     105            // from some other torrent
     106            if (peer.isInterested() && !peer.isChoking())
    102107              uploaders++;
    103108
     
    129134            // interested peers try to make some room.
    130135            // (Note use of coordinator.uploaders)
    131             if (((coordinator.uploaders == uploadLimit
    132                 && coordinator.interestedAndChoking > 0)
    133                 || coordinator.uploaders > uploadLimit
    134                 || overBWLimitChoke)
     136            int cup = coordinator.getUploaders();
     137            if (((cup == uploadLimit
     138                  && coordinator.getInterestedAndChoking() > 0)
     139                 || cup > uploadLimit
     140                 || overBWLimitChoke)
    135141                && !peer.isChoking())
    136142              {
     
    138144                if (!peer.isInterested())
    139145                  {
     146                    // Note that we only choke if we are over our limits,
     147                    // so a peer may remain unchoked even if uninterested.
    140148                    if (_log.shouldLog(Log.DEBUG))
    141149                        _log.debug("Choke uninterested peer: " + peer);
    142150                    peer.setChoking(true);
    143151                    uploaders--;
    144                     coordinator.uploaders--;
     152                    coordinator.decrementUploaders(false);
    145153                   
    146154                    // Put it at the back of the list
     
    153161                    peer.setChoking(true);
    154162                    uploaders--;
    155                     coordinator.uploaders--;
     163                    interestedUploaders--;
     164                    coordinator.decrementUploaders(true);
    156165                    removedCount++;
    157166
     
    166175                    peer.setChoking(true);
    167176                    uploaders--;
    168                     coordinator.uploaders--;
     177                    interestedUploaders--;
     178                    coordinator.decrementUploaders(true);
    169179                    removedCount++;
    170180                   
     
    179189                    peer.setChoking(true);
    180190                    uploaders--;
    181                     coordinator.uploaders--;
     191                    interestedUploaders--;
     192                    coordinator.decrementUploaders(true);
    182193                    removedCount++;
    183194                   
     
    194205                    peer.setChoking(true);
    195206                    uploaders--;
    196                     coordinator.uploaders--;
     207                    interestedUploaders--;
     208                    coordinator.decrementUploaders(true);
    197209                    removedCount++;
    198210                   
     
    231243        // Resync actual uploaders value
    232244        // (can shift a bit by disconnecting peers)
    233         coordinator.uploaders = uploaders;
     245        coordinator.setUploaders(uploaders, interestedUploaders);
    234246
    235247        // Remove the worst downloader if needed. (uploader if seeding)
    236248        if (((uploaders == uploadLimit
    237             && coordinator.interestedAndChoking > 0)
     249            && coordinator.getInterestedAndChoking() > 0)
    238250            || uploaders > uploadLimit)
    239251            && worstDownloader != null)
     
    243255
    244256            worstDownloader.setChoking(true);
    245             coordinator.uploaders--;
     257            coordinator.decrementUploaders(worstDownloader.isInterested());
    246258            removedCount++;
    247259
     
    250262          }
    251263       
    252         // Optimistically unchoke a peer
    253         if ((!overBWLimit) && !coordinator.overUpBWLimit(uploaded))
    254             coordinator.unchokePeer();
    255 
    256         // Put peers back at the end of the list that we removed earlier.
     264        boolean coordOver = coordinator.overUpBWLimit(uploaded);
    257265        synchronized (coordinator.peers) {
     266            if ((!overBWLimit) && !coordOver) {
     267                // Optimistically unchoke a peer
     268                // must be called inside synch
     269                coordinator.unchokePeer();
     270            }
     271            // Put peers back at the end of the list that we removed earlier.
    258272            for(Peer peer : removed) {
    259273                if (coordinator.peers.remove(peer))
     
    261275            }
    262276        }
    263         coordinator.interestedAndChoking += removedCount;
     277
     278        coordinator.addInterestedAndChoking(removedCount);
    264279
    265280        // store the rates
    266281        coordinator.setRateHistory(uploaded, downloaded);
     282        if (_log.shouldLog(Log.DEBUG))
     283            _log.debug("END peers: " + peerList.size() + " uploaders: " + uploaders +
     284                       " interested: " + interestedUploaders);
    267285
    268286        // close out unused files, but we don't need to do it every time
  • apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java

    r8a84522 rd2569fa  
    3434import java.util.Set;
    3535import java.util.concurrent.LinkedBlockingDeque;
     36import java.util.concurrent.atomic.AtomicInteger;
    3637import java.util.concurrent.atomic.AtomicLong;
    3738
     
    7576
    7677  /**
    77    * Approximation of the number of current uploaders.
     78   * Approximation of the number of current uploaders (unchoked peers),
     79   * whether interested or not.
    7880   * Resynced by PeerChecker once in a while.
     81   */
     82  private final AtomicInteger uploaders = new AtomicInteger();
     83
     84  /**
     85   * Approximation of the number of current uploaders (unchoked peers),
     86   * that are interested.
     87   * Resynced by PeerChecker once in a while.
     88   */
     89  private final AtomicInteger interestedUploaders = new AtomicInteger();
     90
     91  /**
    7992   * External use by PeerCheckerTask only.
    8093   */
    81   int uploaders;
    82 
    83   /**
    84    * External use by PeerCheckerTask only.
    85    */
    86   int interestedAndChoking;
     94  private final AtomicInteger interestedAndChoking = new AtomicInteger();
    8795
    8896  // final static int MAX_DOWNLOADERS = MAX_CONNECTIONS;
     
    628636  }
    629637
    630 
    631   // (Optimistically) unchoke. Should be called with peers synchronized
     638  /**
     639   * (Optimistically) unchoke. Must be called with peers synchronized
     640   */
    632641  void unchokePeer()
    633642  {
     
    646655              {
    647656                count++;
    648                 if (uploaders < maxUploaders)
     657                if (uploaders.get() < maxUploaders)
    649658                  {
    650659                    if (peer.isInteresting() && !peer.isChoked())
     
    656665          }
    657666
    658         while (uploaders < maxUploaders && !interested.isEmpty())
     667        int up = uploaders.get();
     668        while (up < maxUploaders && !interested.isEmpty())
    659669          {
    660670            Peer peer = interested.remove(0);
     
    662672              _log.debug("Unchoke: " + peer);
    663673            peer.setChoking(false);
    664             uploaders++;
     674            up = uploaders.incrementAndGet();
     675            interestedUploaders.incrementAndGet();
    665676            count--;
    666677            // Put peer back at the end of the list.
     
    669680            peerCount = peers.size();
    670681          }
    671         interestedAndChoking = count;
     682        interestedAndChoking.set(count);
    672683  }
    673684
     
    10991110    if (interest)
    11001111      {
    1101             if (uploaders < allowedUploaders())
     1112            if (uploaders.get() < allowedUploaders())
    11021113              {
    11031114                if(peer.isChoking())
    11041115                  {
    1105                     uploaders++;
     1116                    uploaders.incrementAndGet();
     1117                    interestedUploaders.incrementAndGet();
    11061118                    peer.setChoking(false);
    11071119                    if (_log.shouldLog(Log.INFO))
     
    14881500  public int allowedUploaders()
    14891501  {
    1490     if (listener != null && listener.overUploadLimit(uploaders)) {
     1502    int up = uploaders.get();
     1503    if (listener != null && listener.overUploadLimit(interestedUploaders.get())) {
    14911504           if (_log.shouldLog(Log.DEBUG))
    1492              _log.debug("Over limit, uploaders was: " + uploaders);
    1493         return uploaders - 1;
    1494     } else if (uploaders < MAX_UPLOADERS)
    1495         return uploaders + 1;
    1496     else
     1505             _log.debug("Over limit, uploaders was: " + up);
     1506        return up - 1;
     1507    } else if (up < MAX_UPLOADERS) {
     1508        return up + 1;
     1509    } else {
    14971510        return MAX_UPLOADERS;
    1498   }
    1499 
    1500   /**
     1511    }
     1512  }
     1513
     1514  /**
     1515   *  Uploaders whether interested or not
     1516   *  Use this for per-torrent limits.
     1517   *
    15011518   *  @return current
    15021519   *  @since 0.8.4
    15031520   */
    15041521  public int getUploaders() {
    1505       return uploaders;
     1522      int rv = uploaders.get();
     1523      if (rv > 0) {
     1524          int max = getPeers();
     1525          if (rv > max)
     1526              rv = max;
     1527      }
     1528      return rv;
     1529  }
     1530
     1531  /**
     1532   *  Uploaders, interested only.
     1533   *  Use this to calculate the global total, so that
     1534   *  unchoked but uninterested peers don't count against the global limit.
     1535   *
     1536   *  @return current
     1537   *  @since 0.9.28
     1538   */
     1539  public int getInterestedUploaders() {
     1540      int rv = interestedUploaders.get();
     1541      if (rv > 0) {
     1542          int max = getPeers();
     1543          if (rv > max)
     1544              rv = max;
     1545      }
     1546      return rv;
     1547  }
     1548
     1549  /**
     1550   *  Set the uploaders and interestedUploaders counts
     1551   *
     1552   *  @since 0.9.28
     1553   *  @param upl whether interested or not
     1554   *  @param inter interested only
     1555   */
     1556  public void setUploaders(int upl, int inter) {
     1557      if (upl < 0)
     1558          upl = 0;
     1559      else if (upl > MAX_UPLOADERS)
     1560          upl = MAX_UPLOADERS;
     1561      uploaders.set(upl);
     1562      if (inter < 0)
     1563          inter = 0;
     1564      else if (inter > MAX_UPLOADERS)
     1565          inter = MAX_UPLOADERS;
     1566      interestedUploaders.set(inter);
     1567  }
     1568
     1569  /**
     1570   *  Decrement the uploaders and (if set) the interestedUploaders counts
     1571   *
     1572   *  @since 0.9.28
     1573   */
     1574  public void decrementUploaders(boolean isInterested) {
     1575      int up = uploaders.decrementAndGet();
     1576      if (up < 0)
     1577          uploaders.set(0);
     1578      if (isInterested) {
     1579          up = interestedUploaders.decrementAndGet();
     1580          if (up < 0)
     1581              interestedUploaders.set(0);
     1582      }
     1583  }
     1584
     1585  /**
     1586   *  @return current
     1587   *  @since 0.9.28
     1588   */
     1589  public int getInterestedAndChoking() {
     1590      return interestedAndChoking.get();
     1591  }
     1592
     1593  /**
     1594   *  @since 0.9.28
     1595   */
     1596  public void addInterestedAndChoking(int toAdd) {
     1597      interestedAndChoking.addAndGet(toAdd);
    15061598  }
    15071599
  • apps/i2psnark/java/src/org/klomp/snark/Snark.java

    r8a84522 rd2569fa  
    13381338    for (PeerCoordinator c : _peerCoordinatorSet) {
    13391339      if (!c.halted())
    1340         totalUploaders += c.uploaders;
     1340        totalUploaders += c.getInterestedUploaders();
    13411341    }
    13421342    int limit = _util.getMaxUploaders();
  • history.txt

    r8a84522 rd2569fa  
     12016-10-25 zzz
     2 * i2psnark: Better calculation of total upload limit
     3 * SSU: Increase max IPv6 MTU (proposal #127)
     4 * Zxing 3.3.0
     5
    162016-10-23 zzz
    27 * Crypto: Create keystore directory when making SSL keys (ticket #1866)
  • router/java/src/net/i2p/router/RouterVersion.java

    r8a84522 rd2569fa  
    1919    public final static String ID = "Monotone";
    2020    public final static String VERSION = CoreVersion.VERSION;
    21     public final static long BUILD = 3;
     21    public final static long BUILD = 4;
    2222
    2323    /** for example "-test" */
Note: See TracChangeset for help on using the changeset viewer.