Changeset b20e298


Ignore:
Timestamp:
Oct 5, 2012 1:08:05 PM (9 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
583463a
Parents:
090d59f
Message:
  • SSU:
    • More synchronization fixes
    • Reduce chance of dup acks in a single message
    • Reduce max unsent acks to 50
    • Use last ack time in ping decision too
    • Reduce ack delay
Location:
router/java/src/net/i2p/router/transport/udp
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • router/java/src/net/i2p/router/transport/udp/ACKSender.java

    r090d59f rb20e298  
    2929   
    3030    /** how frequently do we want to send ACKs to a peer? */
    31     static final int ACK_FREQUENCY = 500;
     31    static final int ACK_FREQUENCY = 350;
    3232   
    3333    public ACKSender(RouterContext ctx, UDPTransport transport) {
     
    7474    }
    7575   
    76     private long ackFrequency(long timeSinceACK, long rtt) {
     76    private static long ackFrequency(long timeSinceACK, long rtt) {
    7777        // if we are actively pumping lots of data to them, we can depend upon
    7878        // the unsentACKThreshold to figure out when to send an ACK instead of
    7979        // using the timer, so we can set the timeout/frequency higher
    8080        if (timeSinceACK < 2*1000)
    81             return Math.max(rtt/2, 500);
     81            return Math.max(rtt/2, ACK_FREQUENCY);
    8282        else
    8383            return ACK_FREQUENCY;
     
    163163               
    164164                if (!ackBitfields.isEmpty()) {
    165                     _context.statManager().addRateData("udp.sendACKCount", ackBitfields.size(), 0);
     165                    _context.statManager().addRateData("udp.sendACKCount", ackBitfields.size());
    166166                    if (remaining > 0)
    167                         _context.statManager().addRateData("udp.sendACKRemaining", remaining, 0);
     167                        _context.statManager().addRateData("udp.sendACKRemaining", remaining);
    168168                    // set above before the break
    169169                    //now = _context.clock().now();
     
    171171                        lastSend = now - 1;
    172172                    _context.statManager().addRateData("udp.ackFrequency", now-lastSend, now-wanted);
    173                     //_context.statManager().getStatLog().addData(peer.getRemoteHostId().toString(), "udp.peer.sendACKCount", ackBitfields.size(), 0);
     173                    //_context.statManager().getStatLog().addData(peer.getRemoteHostId().toString(), "udp.peer.sendACKCount", ackBitfields.size());
    174174                    UDPPacket ack = _builder.buildACK(peer, ackBitfields);
    175175                    ack.markType(1);
     
    194194                    }
    195195                } else {
    196                     _context.statManager().addRateData("udp.abortACK", 1, 0);
     196                    _context.statManager().addRateData("udp.abortACK", 1);
    197197                }
    198198            }
  • router/java/src/net/i2p/router/transport/udp/IntroductionManager.java

    r090d59f rb20e298  
    186186    public void pingIntroducers() {
    187187        // Try to keep the connection up for two hours after we made anybody an introducer
    188         long pingCutoff = _context.clock().now() - (105 * 60 * 1000);
    189         long inactivityCutoff = _context.clock().now() - UDPTransport.MIN_EXPIRE_TIMEOUT;
     188        long now = _context.clock().now();
     189        long pingCutoff = now - (105 * 60 * 1000);
     190        long inactivityCutoff = now - UDPTransport.MIN_EXPIRE_TIMEOUT;
    190191        for (PeerState cur : _inbound) {
    191192            if (cur.getIntroducerTime() > pingCutoff &&
     
    193194                if (_log.shouldLog(Log.INFO))
    194195                    _log.info("Pinging introducer: " + cur);
    195                 cur.setLastSendTime(_context.clock().now());
     196                cur.setLastSendTime(now);
    196197                _transport.send(_builder.buildPing(cur));
    197198            }
  • router/java/src/net/i2p/router/transport/udp/PeerState.java

    r090d59f rb20e298  
    407407    /** how many seconds have we sent packets without any ACKs received? */
    408408    public int getConsecutiveFailedSends() { return _consecutiveFailedSends; }
    409     /** have we received a packet with the ECN bit set in the current second? */
     409
     410    /**
     411     *  have we received a packet with the ECN bit set in the current second?
     412     *  @return false always
     413     *  @deprecated unused, ECNs are never sent, always returns false
     414     */
    410415    public boolean getCurrentSecondECNReceived() { return _currentSecondECNReceived; }
     416
    411417    /**
    412418     * have all of the packets received in the current second requested that
     
    414420     */
    415421    //public boolean getRemoteWantsPreviousACKs() { return _remoteWantsPreviousACKs; }
     422
    416423    /** how many bytes should we send to the peer in a second */
    417424    public int getSendWindowBytes() { return _sendWindowBytes; }
     
    549556
    550557    /**
    551      *  Latest of last sent and last ping
     558     *  Latest of last sent, last ACK, last ping
    552559     *  @since 0.9.3
    553560     */
    554     public long getLastSendOrPingTime() { return Math.max(_lastSendTime, _lastPingTime); }
     561    public long getLastSendOrPingTime() {
     562        return Math.max(Math.max(_lastSendTime, _lastACKSend), _lastPingTime);
     563    }
    555564
    556565    /** return the smoothed send transfer rate */
     
    755764     * either they told us to back off, or we had to resend to get
    756765     * the data through. 
    757      *
     766     *  Caller should synch on this
     767     *  @return true if window shrunk, but nobody uses the return value
    758768     */
    759769    private boolean congestionOccurred() {
     
    762772            return false; // only shrink once every few seconds
    763773        _lastCongestionOccurred = now;
    764        
    765         _context.statManager().addRateData("udp.congestionOccurred", _sendWindowBytes, _sendBps);
    766774       
    767775        int congestionAt = _sendWindowBytes;
     
    820828    }
    821829
    822     /** the ack was sent */
     830    /**
     831     * The ack was sent.
     832     * Side effect - sets _lastACKSend
     833     */
    823834    public void removeACKMessage(Long messageId) {
    824835            boolean removed = _currentACKs.remove(messageId);
     
    841852     *  The max number of acks we save to send as duplicates
    842853     */
    843     private static final int MAX_RESEND_ACKS = 16;
     854    private static final int MAX_RESEND_ACKS = 64;
    844855    /**
    845856     *  The max number of duplicate acks sent in each ack-only messge.
     
    847858     *  @since 0.7.13
    848859     */
    849     private static final int MAX_RESEND_ACKS_LARGE = MAX_RESEND_ACKS;
     860    private static final int MAX_RESEND_ACKS_LARGE = MAX_RESEND_ACKS / 3;
    850861    /** for small MTU */
    851     private static final int MAX_RESEND_ACKS_SMALL = MAX_RESEND_ACKS;
     862    private static final int MAX_RESEND_ACKS_SMALL = MAX_RESEND_ACKS / 5;
    852863   
    853864    /**
     
    868879     * So this is only for ACK-only packets, so all the size limiting is useless.
    869880     * FIXME.
     881     * Side effect - sets _lastACKSend if rv is non-empty
    870882     *
    871883     * @return non-null, possibly empty
    872884     */
    873885    public List<ACKBitfield> retrieveACKBitfields(boolean alwaysIncludeRetransmissions) {
    874         List<ACKBitfield> rv = new ArrayList(MAX_RESEND_ACKS);
    875886        int bytesRemaining = countMaxACKData();
    876887
     
    884895            else
    885896                maxResendAcks = MAX_RESEND_ACKS_LARGE;
    886             List<Long> randomResends = new ArrayList(_currentACKsResend);
    887 
     897            List<ACKBitfield> rv = new ArrayList(maxResendAcks);
     898
     899            // save to add to currentACKsResend later so we don't include twice
     900            List<Long> currentACKsRemoved = new ArrayList(_currentACKs.size());
    888901            // As explained above, we include the acks in any order
    889902            // since we are unlikely to get backed up -
     
    895908                long id = val.longValue();
    896909                rv.add(new FullACKBitfield(id));
    897                 _currentACKsResend.offer(val);
     910                currentACKsRemoved.add(val);
    898911                bytesRemaining -= 4;
    899912            }
     
    901914                _wantACKSendSince = -1;
    902915            if (alwaysIncludeRetransmissions || !rv.isEmpty()) {
     916                List<Long> randomResends = new ArrayList(_currentACKsResend);
    903917                // now repeat by putting in some old ACKs
    904918                // randomly selected from the Resend queue.
     
    921935                    //}
    922936                }
     937                for (Long val : currentACKsRemoved) {
     938                    _currentACKsResend.offer(val);
     939                }
    923940            }
    924941            // trim down the resends
     
    948965        }
    949966
    950         _lastACKSend = _context.clock().now();
     967        if (!rv.isEmpty())
     968            _lastACKSend = _context.clock().now();
    951969        //if (rv == null)
    952970        //    rv = Collections.EMPTY_LIST;
     
    10161034    }
    10171035       
    1018     /** we sent a message which was ACKed containing the given # of bytes */
    1019     public void messageACKed(int bytesACKed, long lifetime, int numSends) {
     1036    /**
     1037     *  We sent a message which was ACKed containing the given # of bytes.
     1038     *  Caller should synch on this
     1039     */
     1040    private void locked_messageACKed(int bytesACKed, long lifetime, int numSends) {
    10201041        _concurrentMessagesActive--;
    10211042        if (_concurrentMessagesActive < 0)
     
    10311052                _sendWindowBytes += bytesACKed;
    10321053            } else {
    1033                 if (false) {
    1034                     _sendWindowBytes += 16; // why 16?
    1035                 } else {
     1054                //if (false) {
     1055                //    _sendWindowBytes += 16; // why 16?
     1056                //} else {
    10361057                    float prob = ((float)bytesACKed) / ((float)(_sendWindowBytes<<1));
    10371058                    float v = _context.random().nextFloat();
     
    10391060                    if (v <= prob)
    10401061                        _sendWindowBytes += bytesACKed; //512; // bytesACKed;
    1041                 }
     1062                //}
    10421063            }
    10431064        } else {
     
    10521073        _lastSendFullyTime = _lastReceiveTime;
    10531074       
    1054         if (true) {
     1075        //if (true) {
    10551076            if (_sendWindowBytesRemaining + bytesACKed <= _sendWindowBytes)
    10561077                _sendWindowBytesRemaining += bytesACKed;
    10571078            else
    10581079                _sendWindowBytesRemaining = _sendWindowBytes;
    1059         }
     1080        //}
    10601081       
    10611082        _messagesSent++;
    10621083        if (numSends < 2) {
    1063             synchronized (this) {
     1084            // caller synchs
     1085            //synchronized (this) {
    10641086                recalculateTimeouts(lifetime);
    10651087                adjustMTU();
    1066             }
    1067         }
    1068         else if (_log.shouldLog(Log.INFO))
     1088            //}
     1089        }
     1090    }
     1091
     1092    /**
     1093     *  We sent a message which was ACKed containing the given # of bytes.
     1094     */
     1095    private void messageACKed(int bytesACKed, long lifetime, int numSends) {
     1096        synchronized(this) {
     1097            locked_messageACKed(bytesACKed, lifetime, numSends);
     1098        }
     1099        if (numSends >= 2 && _log.shouldLog(Log.INFO))
    10691100            _log.info("acked after numSends=" + numSends + " w/ lifetime=" + lifetime + " and size=" + bytesACKed);
    10701101       
     
    11451176        }
    11461177        *****/
    1147         congestionOccurred();
     1178        _context.statManager().addRateData("udp.congestionOccurred", _sendWindowBytes, _sendBps);
    11481179        _context.statManager().addRateData("udp.congestedRTO", _rto, _rttDeviation);
    11491180        synchronized (this) {
     1181            congestionOccurred();
    11501182            adjustMTU();
    11511183        }
     
    12091241   
    12101242    /**
    1211      * we received a backoff request, so cut our send window
     1243     *  We received a backoff request, so cut our send window.
     1244     *  NOTE: ECN sending is unimplemented, this is never called.
    12121245     */
    12131246    public void ECNReceived() {
    1214         congestionOccurred();
     1247        synchronized(this) {
     1248            congestionOccurred();
     1249        }
     1250        _context.statManager().addRateData("udp.congestionOccurred", _sendWindowBytes, _sendBps);
    12151251        _currentSecondECNReceived = true;
    12161252        _lastReceiveTime = _context.clock().now();
     
    12231259    /** when did we last send an ACK to the peer? */
    12241260    public long getLastACKSend() { return _lastACKSend; }
     1261
     1262    /** @deprecated unused */
    12251263    public void setLastACKSend(long when) { _lastACKSend = when; }
     1264
    12261265    public long getWantedACKSendSince() { return _wantACKSendSince; }
    12271266
     1267    /**
     1268     *  Are we out of room to send all the current unsent acks in a single packet?
     1269     *  This is a huge threshold (134 for small MTU and 255 for large MTU)
     1270     *  that is rarely if ever exceeded in practice.
     1271     *  So just use a fixed threshold of half the resend acks, so that if the
     1272     *  packet is lost the acks have a decent chance of getting retransmitted.
     1273     *  Used only by ACKSender.
     1274     */
    12281275    public boolean unsentACKThresholdReached() {
    1229         int threshold = countMaxACKData() / 4;
    1230         return _currentACKs.size() >= threshold;
    1231     }
    1232 
    1233     /** @return MTU - 83 */
     1276        //int threshold = countMaxACKData() / 4;
     1277        //return _currentACKs.size() >= threshold;
     1278        return _currentACKs.size() >= MAX_RESEND_ACKS / 2;
     1279    }
     1280
     1281    /**
     1282     *  @return how many bytes available for acks in an ack-only packet, == MTU - 83
     1283     *          Max of 1020
     1284     */
    12341285    private int countMaxACKData() {
    1235         return _mtu
     1286        return Math.min(PacketBuilder.ABSOLUTE_MAX_ACKS * 4,
     1287                _mtu
    12361288                - PacketBuilder.IP_HEADER_SIZE
    12371289                - PacketBuilder.UDP_HEADER_SIZE
     
    12421294                - 1 // data flag
    12431295                - 1 // # ACKs
    1244                 - 16; // padding safety
     1296                - 16); // padding safety
    12451297    }
    12461298
Note: See TracChangeset for help on using the changeset viewer.