forked from quic-go/quic-go
send multiple packets at once, if the pacing delay is very small
This is an optimization to avoid waking of the run loop every couple of microseconds.
This commit is contained in:
@@ -14,8 +14,21 @@ type SentPacketHandler interface {
|
||||
ReceivedAck(ackFrame *wire.AckFrame, withPacketNumber protocol.PacketNumber, encLevel protocol.EncryptionLevel, recvTime time.Time) error
|
||||
SetHandshakeComplete()
|
||||
|
||||
// SendingAllowed says if a packet can be sent.
|
||||
// Sending packets might not be possible because:
|
||||
// * we're congestion limited
|
||||
// * we're tracking the maximum number of sent packets
|
||||
SendingAllowed() bool
|
||||
// TimeUntilSend is the time when the next packet should be sent.
|
||||
// It is used for pacing packets.
|
||||
TimeUntilSend() time.Time
|
||||
// ShouldSendNumPackets returns the number of packets that should be sent immediately.
|
||||
// It always returns a number greater or equal than 1.
|
||||
// A number greater than 1 is returned when the pacing delay is smaller than the minimum pacing delay.
|
||||
// Note that the number of packets is only calculated based on the pacing algorithm.
|
||||
// Before sending any packet, SendingAllowed() must be called to learn if we can actually send it.
|
||||
ShouldSendNumPackets() int
|
||||
|
||||
GetStopWaitingFrame(force bool) *wire.StopWaitingFrame
|
||||
GetLowestPacketNotConfirmedAcked() protocol.PacketNumber
|
||||
ShouldSendRetransmittablePacket() bool
|
||||
|
||||
@@ -3,6 +3,7 @@ package ackhandler
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/congestion"
|
||||
@@ -34,7 +35,7 @@ var ErrDuplicateOrOutOfOrderAck = errors.New("SentPacketHandler: Duplicate or ou
|
||||
|
||||
type sentPacketHandler struct {
|
||||
lastSentPacketNumber protocol.PacketNumber
|
||||
lastPacketSentTime time.Time
|
||||
nextPacketSendTime time.Time
|
||||
skippedPackets []protocol.PacketNumber
|
||||
|
||||
numNonRetransmittablePackets int // number of non-retransmittable packets since the last retransmittable packet
|
||||
@@ -125,7 +126,6 @@ func (h *sentPacketHandler) SentPacket(packet *Packet) error {
|
||||
|
||||
now := time.Now()
|
||||
h.lastSentPacketNumber = packet.PacketNumber
|
||||
h.lastPacketSentTime = now
|
||||
|
||||
var largestAcked protocol.PacketNumber
|
||||
if len(packet.Frames) > 0 {
|
||||
@@ -155,6 +155,8 @@ func (h *sentPacketHandler) SentPacket(packet *Packet) error {
|
||||
isRetransmittable,
|
||||
)
|
||||
|
||||
h.nextPacketSendTime = utils.MaxTime(h.nextPacketSendTime, now).Add(h.congestion.TimeUntilSend(h.bytesInFlight))
|
||||
|
||||
h.updateLossDetectionAlarm(now)
|
||||
return nil
|
||||
}
|
||||
@@ -389,7 +391,15 @@ func (h *sentPacketHandler) SendingAllowed() bool {
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) TimeUntilSend() time.Time {
|
||||
return h.lastPacketSentTime.Add(h.congestion.TimeUntilSend(h.bytesInFlight))
|
||||
return h.nextPacketSendTime
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) ShouldSendNumPackets() int {
|
||||
delay := h.congestion.TimeUntilSend(h.bytesInFlight)
|
||||
if delay == 0 || delay > protocol.MinPacingDelay {
|
||||
return 1
|
||||
}
|
||||
return int(math.Ceil(float64(protocol.MinPacingDelay) / float64(delay)))
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) retransmitOldestTwoPackets() {
|
||||
|
||||
@@ -680,9 +680,7 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
})
|
||||
|
||||
Context("congestion", func() {
|
||||
var (
|
||||
cong *mocks.MockSendAlgorithm
|
||||
)
|
||||
var cong *mocks.MockSendAlgorithm
|
||||
|
||||
BeforeEach(func() {
|
||||
cong = mocks.NewMockSendAlgorithm(mockCtrl)
|
||||
@@ -698,6 +696,7 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
protocol.ByteCount(42),
|
||||
true,
|
||||
)
|
||||
cong.EXPECT().TimeUntilSend(gomock.Any())
|
||||
p := &Packet{
|
||||
PacketNumber: 1,
|
||||
Length: 42,
|
||||
@@ -709,6 +708,7 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
|
||||
It("should call MaybeExitSlowStart and OnPacketAcked", func() {
|
||||
cong.EXPECT().OnPacketSent(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(2)
|
||||
cong.EXPECT().TimeUntilSend(gomock.Any()).Times(2)
|
||||
cong.EXPECT().MaybeExitSlowStart()
|
||||
cong.EXPECT().OnPacketAcked(
|
||||
protocol.PacketNumber(1),
|
||||
@@ -723,6 +723,7 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
|
||||
It("should call MaybeExitSlowStart and OnPacketLost", func() {
|
||||
cong.EXPECT().OnPacketSent(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(3)
|
||||
cong.EXPECT().TimeUntilSend(gomock.Any()).Times(3)
|
||||
cong.EXPECT().OnRetransmissionTimeout(true).Times(2)
|
||||
cong.EXPECT().OnPacketLost(
|
||||
protocol.PacketNumber(1),
|
||||
@@ -765,12 +766,29 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
})
|
||||
|
||||
It("gets the pacing delay", func() {
|
||||
handler.bytesInFlight = 100
|
||||
cong.EXPECT().OnPacketSent(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
|
||||
cong.EXPECT().TimeUntilSend(protocol.ByteCount(100)).Return(time.Hour)
|
||||
handler.SentPacket(&Packet{PacketNumber: 1})
|
||||
handler.bytesInFlight = protocol.ByteCount(100)
|
||||
cong.EXPECT().TimeUntilSend(handler.bytesInFlight).Return(time.Hour)
|
||||
Expect(handler.TimeUntilSend()).To(BeTemporally("~", time.Now().Add(time.Hour), time.Second))
|
||||
})
|
||||
|
||||
It("allows sending of one packet, if it should be sent immediately", func() {
|
||||
cong.EXPECT().TimeUntilSend(gomock.Any()).Return(time.Duration(0))
|
||||
Expect(handler.ShouldSendNumPackets()).To(Equal(1))
|
||||
})
|
||||
|
||||
It("allows sending of multiple packets, if the pacing delay is smaller than the minimum", func() {
|
||||
pacingDelay := protocol.MinPacingDelay / 10
|
||||
cong.EXPECT().TimeUntilSend(gomock.Any()).Return(pacingDelay)
|
||||
Expect(handler.ShouldSendNumPackets()).To(Equal(10))
|
||||
})
|
||||
|
||||
It("allows sending of multiple packets, if the pacing delay is smaller than the minimum, and not a fraction", func() {
|
||||
pacingDelay := protocol.MinPacingDelay * 2 / 5
|
||||
cong.EXPECT().TimeUntilSend(gomock.Any()).Return(pacingDelay)
|
||||
Expect(handler.ShouldSendNumPackets()).To(Equal(3))
|
||||
})
|
||||
})
|
||||
|
||||
Context("calculating RTO", func() {
|
||||
|
||||
Reference in New Issue
Block a user