forked from quic-go/quic-go
refactor timer calculation in sesssion to reduce syscalls
This commit is contained in:
@@ -21,7 +21,7 @@ type SentPacketHandler interface {
|
||||
CongestionAllowsSending() bool
|
||||
CheckForError() error
|
||||
|
||||
TimeToFirstRTO() time.Duration
|
||||
TimeOfFirstRTO() time.Time
|
||||
}
|
||||
|
||||
// ReceivedPacketHandler handles ACKs needed to send for incoming packets
|
||||
|
||||
@@ -313,17 +313,15 @@ func (h *sentPacketHandler) queuePacketsRTO() {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) TimeToFirstRTO() time.Duration {
|
||||
now := time.Now()
|
||||
min := utils.InfDuration
|
||||
func (h *sentPacketHandler) TimeOfFirstRTO() time.Time {
|
||||
var min time.Time
|
||||
for _, p := range h.packetHistory {
|
||||
if p == nil || p.Retransmitted {
|
||||
continue
|
||||
}
|
||||
if now.After(p.rtoTime) {
|
||||
return 0
|
||||
if min.IsZero() || min.After(p.rtoTime) {
|
||||
min = p.rtoTime
|
||||
}
|
||||
min = utils.MinDuration(min, p.rtoTime.Sub(now))
|
||||
}
|
||||
return min
|
||||
}
|
||||
|
||||
@@ -646,27 +646,20 @@ var _ = Describe("SentPacketHandler", func() {
|
||||
|
||||
Context("RTO retransmission", func() {
|
||||
Context("calculating the time to first RTO", func() {
|
||||
It("defaults to inf", func() {
|
||||
Expect(handler.TimeToFirstRTO()).To(Equal(utils.InfDuration))
|
||||
It("defaults to zero", func() {
|
||||
Expect(handler.TimeOfFirstRTO().IsZero()).To(BeTrue())
|
||||
})
|
||||
|
||||
It("returns time to RTO", func() {
|
||||
err := handler.SentPacket(&Packet{PacketNumber: 1, Frames: []frames.Frame{}, Length: 1})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(handler.TimeToFirstRTO()).To(BeNumerically("~", protocol.DefaultRetransmissionTime, time.Millisecond))
|
||||
})
|
||||
|
||||
It("returns 0 when RTOs are required", func() {
|
||||
err := handler.SentPacket(&Packet{PacketNumber: 1, Frames: []frames.Frame{}, Length: 1})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
handler.packetHistory[1].rtoTime = time.Now().Add(-time.Second)
|
||||
Expect(handler.TimeToFirstRTO()).To(BeZero())
|
||||
Expect(handler.TimeOfFirstRTO().Sub(time.Now())).To(BeNumerically("~", protocol.DefaultRetransmissionTime, time.Millisecond))
|
||||
})
|
||||
|
||||
It("ignores nil packets", func() {
|
||||
handler.packetHistory[1] = nil
|
||||
handler.queuePacketsRTO()
|
||||
Expect(handler.TimeToFirstRTO()).To(Equal(utils.InfDuration))
|
||||
Expect(handler.TimeOfFirstRTO().IsZero()).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ func (h *mockSentPacketHandler) BytesInFlight() protocol.ByteCount
|
||||
func (h *mockSentPacketHandler) GetLargestObserved() protocol.PacketNumber { return 1 }
|
||||
func (h *mockSentPacketHandler) CongestionAllowsSending() bool { panic("not implemented") }
|
||||
func (h *mockSentPacketHandler) CheckForError() error { panic("not implemented") }
|
||||
func (h *mockSentPacketHandler) TimeToFirstRTO() time.Duration { panic("not implemented") }
|
||||
func (h *mockSentPacketHandler) TimeOfFirstRTO() time.Time { panic("not implemented") }
|
||||
|
||||
func newMockSentPacketHandler() ackhandler.SentPacketHandler {
|
||||
return &mockSentPacketHandler{}
|
||||
|
||||
56
session.go
56
session.go
@@ -78,8 +78,9 @@ type Session struct {
|
||||
|
||||
lastNetworkActivityTime time.Time
|
||||
|
||||
timer *time.Timer
|
||||
timerRead bool
|
||||
timer *time.Timer
|
||||
currentDeadline time.Time
|
||||
timerRead bool
|
||||
}
|
||||
|
||||
// newSession makes a new session
|
||||
@@ -139,29 +140,7 @@ func (s *Session) run() {
|
||||
default:
|
||||
}
|
||||
|
||||
// Calculate the minimum of all timeouts
|
||||
now := time.Now()
|
||||
firstTimeout := utils.InfDuration
|
||||
// Some timeouts are only set when we can actually send
|
||||
// Note: if a packet arrives, we go through this again afterwards.
|
||||
if s.sentPacketHandler.CongestionAllowsSending() {
|
||||
// Small packet send delay
|
||||
if !s.smallPacketDelayedOccurranceTime.IsZero() {
|
||||
firstTimeout = utils.MinDuration(firstTimeout, s.smallPacketDelayedOccurranceTime.Add(protocol.SmallPacketSendDelay).Sub(now))
|
||||
}
|
||||
// RTOs
|
||||
firstTimeout = utils.MinDuration(firstTimeout, s.sentPacketHandler.TimeToFirstRTO())
|
||||
}
|
||||
// Idle connection timeout
|
||||
firstTimeout = utils.MinDuration(firstTimeout, s.lastNetworkActivityTime.Add(s.connectionParametersManager.GetIdleConnectionStateLifetime()).Sub(now))
|
||||
|
||||
// We need to drain the timer if the value from its channel was not read yet.
|
||||
// See https://groups.google.com/forum/#!topic/golang-dev/c9UUfASVPoU
|
||||
if !s.timer.Stop() && !s.timerRead {
|
||||
<-s.timer.C
|
||||
}
|
||||
s.timer.Reset(firstTimeout)
|
||||
s.timerRead = false
|
||||
s.maybeResetTimer()
|
||||
|
||||
var err error
|
||||
select {
|
||||
@@ -208,6 +187,33 @@ func (s *Session) run() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Session) maybeResetTimer() {
|
||||
nextDeadline := s.lastNetworkActivityTime.Add(s.connectionParametersManager.GetIdleConnectionStateLifetime())
|
||||
|
||||
if !s.smallPacketDelayedOccurranceTime.IsZero() {
|
||||
// nextDeadline = utils.MinDuration(firstTimeout, s.smallPacketDelayedOccurranceTime.Add(protocol.SmallPacketSendDelay).Sub(now))
|
||||
nextDeadline = utils.MinTime(nextDeadline, s.smallPacketDelayedOccurranceTime.Add(protocol.SmallPacketSendDelay))
|
||||
}
|
||||
if rtoTime := s.sentPacketHandler.TimeOfFirstRTO(); !rtoTime.IsZero() {
|
||||
nextDeadline = utils.MinTime(nextDeadline, rtoTime)
|
||||
}
|
||||
|
||||
if nextDeadline.Equal(s.currentDeadline) {
|
||||
// No need to reset the timer
|
||||
return
|
||||
}
|
||||
|
||||
// We need to drain the timer if the value from its channel was not read yet.
|
||||
// See https://groups.google.com/forum/#!topic/golang-dev/c9UUfASVPoU
|
||||
if !s.timer.Stop() && !s.timerRead {
|
||||
<-s.timer.C
|
||||
}
|
||||
s.timer.Reset(nextDeadline.Sub(time.Now()))
|
||||
|
||||
s.timerRead = false
|
||||
s.currentDeadline = nextDeadline
|
||||
}
|
||||
|
||||
func (s *Session) handlePacketImpl(remoteAddr interface{}, hdr *publicHeader, data []byte) error {
|
||||
s.lastNetworkActivityTime = time.Now()
|
||||
r := bytes.NewReader(data)
|
||||
|
||||
@@ -98,6 +98,14 @@ func AbsDuration(d time.Duration) time.Duration {
|
||||
return -d
|
||||
}
|
||||
|
||||
// MinTime returns the earlier time
|
||||
func MinTime(a, b time.Time) time.Time {
|
||||
if a.After(b) {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// MaxPacketNumber returns the max packet number
|
||||
func MaxPacketNumber(a, b protocol.PacketNumber) protocol.PacketNumber {
|
||||
if a > b {
|
||||
|
||||
Reference in New Issue
Block a user