Opened 3 weeks ago

Last modified 5 days ago

#2648 new enhancement

PeerState.java: rework send window

Reported by: jogger Owned by: zzz
Priority: major Milestone: undecided
Component: router/transport Version: 0.9.43
Keywords: Cc:
Parent Tickets: #2512 Sensitive: no

Description

Currently there is a byte based window and a message based one. Both are adjusted after message completion, in case of a fail 10 sec late. Adjustment is based on some heuristics that seem to work to some degree. Major weakness: In case of occasional UDP packet loss which is no error condition, the byte based window keeps possible transfer speeds at a minimum.

I suggest using a byte based window twice as large as what is ACKed from the other end. This would be adjusted just before each send attempt. Such a window would grow very fast, if the other end ACKs fast, and it would be run run down long before a message fails in case no ACKs come in.

Subtickets

Change History (2)

comment:1 Changed 7 days ago by zzz

Parent Tickets: 2512

This is essentially a dup of #2512 and #2576? see also #2505

comment:2 Changed 5 days ago by jogger

Not a dup. This is an enhancement, replacing the TCP like logic. I have sucessfully tested a 3 sec window with 20*1033 initial size, fitting tunnel build or torrent chunk. Upscaling factor 1.25 * bytes ACKed. Superior to current code as it runs down the window in 3 sec as opposed to a 10 sec timeout. Example code:

    void updateSendWindow(long now) {
        int duration;
        if ((duration = (int)(now - _lastSendRefill)) > 0) {
            if (duration < 10000)
                // sendrate for 10 sec interval = new traffic + portion of old traffic
                _sendBps = (_sendBytes + 5) / 10 + ((10000 - duration) * _sendBps + 5000) / 10000;
            else
                _sendBps = (_sendBytes * 1000 + duration / 2) / duration;
            _lastSendRefill = now;
            _sendBytes = 0;

            if (duration < SEND_WINDOW) {
                int oldWindowBytes = _sendWindowBytes;
                // adjust send window, remove elapsed period, add 1.25 * bytes acked
                // _sendWindowBytesRemaining honor retransmissions, _bytesAcked do not
                // so window is grown only for constantly sending, low error connections
                _sendWindowBytes = Math.max(MINIMUM_WINDOW_BYTES,
                    _sendWindowBytes - (duration * _sendWindowBytes + SEND_WINDOW / 2) / SEND_WINDOW + _bytesAcked + _bytesAcked / 4);
                // adjust for possible changes in send window (=fast run down if no ACKs)
                if (oldWindowBytes != _sendWindowBytes)
                    _sendWindowBytesRemaining = (_sendWindowBytesRemaining * _sendWindowBytes + oldWindowBytes / 2) / oldWindowBytes;
                // refill remaining
                _sendWindowBytesRemaining = Math.min(_sendWindowBytes,
                    _sendWindowBytesRemaining + (_sendWindowBytes * duration + SEND_WINDOW / 2) / SEND_WINDOW);
            } else {
                _sendWindowBytes = Math.max(MINIMUM_WINDOW_BYTES, _bytesAcked + _bytesAcked / 4);
                _sendWindowBytesRemaining = _sendWindowBytes;
            }
            _bytesAcked = 0;
            // Allow more than 2 retransmissions if this guy has been fast for quite a while
            // must have 10 KBps constantly for _retransmax = 3
            _retransmax = 1 + _sendWindowBytes / MINIMUM_WINDOW_BYTES;
        }
    }
Note: See TracTickets for help on using tickets.