forked from quic-go/quic-go
use a sync.Pool for ACK frames
This commit is contained in:
@@ -171,16 +171,16 @@ func (h *receivedPacketTracker) GetAckFrame(onlyIfQueued bool) *wire.AckFrame {
|
||||
}
|
||||
}
|
||||
|
||||
ack := &wire.AckFrame{
|
||||
AckRanges: h.packetHistory.AppendAckRanges(nil),
|
||||
// Make sure that the DelayTime is always positive.
|
||||
// This is not guaranteed on systems that don't have a monotonic clock.
|
||||
DelayTime: utils.Max(0, now.Sub(h.largestObservedReceivedTime)),
|
||||
ECT0: h.ect0,
|
||||
ECT1: h.ect1,
|
||||
ECNCE: h.ecnce,
|
||||
}
|
||||
ack := wire.GetAckFrame()
|
||||
ack.DelayTime = utils.Max(0, now.Sub(h.largestObservedReceivedTime))
|
||||
ack.ECT0 = h.ect0
|
||||
ack.ECT1 = h.ect1
|
||||
ack.ECNCE = h.ecnce
|
||||
ack.AckRanges = h.packetHistory.AppendAckRanges(ack.AckRanges)
|
||||
|
||||
if h.lastAck != nil {
|
||||
wire.PutAckFrame(h.lastAck)
|
||||
}
|
||||
h.lastAck = ack
|
||||
h.ackAlarm = time.Time{}
|
||||
h.ackQueued = false
|
||||
|
||||
@@ -11,6 +11,10 @@ import (
|
||||
// Furthermore, it removes the data slices from CRYPTO and STREAM frames.
|
||||
func ConvertFrame(frame wire.Frame) logging.Frame {
|
||||
switch f := frame.(type) {
|
||||
case *wire.AckFrame:
|
||||
// We use a pool for ACK frames.
|
||||
// Implementations of the tracer interface may hold on to frames, so we need to make a copy here.
|
||||
return ConvertAckFrame(f)
|
||||
case *wire.CryptoFrame:
|
||||
return &logging.CryptoFrame{
|
||||
Offset: f.Offset,
|
||||
@@ -31,3 +35,16 @@ func ConvertFrame(frame wire.Frame) logging.Frame {
|
||||
return logging.Frame(frame)
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertAckFrame(f *wire.AckFrame) *logging.AckFrame {
|
||||
ranges := make([]wire.AckRange, 0, len(f.AckRanges))
|
||||
ranges = append(ranges, f.AckRanges...)
|
||||
ack := &logging.AckFrame{
|
||||
AckRanges: ranges,
|
||||
DelayTime: f.DelayTime,
|
||||
ECNCE: f.ECNCE,
|
||||
ECT0: f.ECT0,
|
||||
ECT1: f.ECT1,
|
||||
}
|
||||
return ack
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ func parseAckFrame(r *bytes.Reader, ackDelayExponent uint8, _ protocol.VersionNu
|
||||
}
|
||||
ecn := typeByte&0x1 > 0
|
||||
|
||||
frame := &AckFrame{}
|
||||
frame := GetAckFrame()
|
||||
|
||||
la, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
@@ -106,7 +106,7 @@ func parseAckFrame(r *bytes.Reader, ackDelayExponent uint8, _ protocol.VersionNu
|
||||
return frame, nil
|
||||
}
|
||||
|
||||
// Write writes an ACK frame.
|
||||
// Append appends an ACK frame.
|
||||
func (f *AckFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
|
||||
hasECN := f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0
|
||||
if hasECN {
|
||||
|
||||
24
internal/wire/ack_frame_pool.go
Normal file
24
internal/wire/ack_frame_pool.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package wire
|
||||
|
||||
import "sync"
|
||||
|
||||
var ackFramePool = sync.Pool{New: func() any {
|
||||
return &AckFrame{}
|
||||
}}
|
||||
|
||||
func GetAckFrame() *AckFrame {
|
||||
f := ackFramePool.Get().(*AckFrame)
|
||||
f.AckRanges = f.AckRanges[:0]
|
||||
f.ECNCE = 0
|
||||
f.ECT0 = 0
|
||||
f.ECT1 = 0
|
||||
f.DelayTime = 0
|
||||
return f
|
||||
}
|
||||
|
||||
func PutAckFrame(f *AckFrame) {
|
||||
if cap(f.AckRanges) > 4 {
|
||||
return
|
||||
}
|
||||
ackFramePool.Put(f)
|
||||
}
|
||||
29
internal/wire/ack_frame_pool_test.go
Normal file
29
internal/wire/ack_frame_pool_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("ACK Frame (for IETF QUIC)", func() {
|
||||
It("gets an ACK frame from the pool", func() {
|
||||
for i := 0; i < 100; i++ {
|
||||
ack := GetAckFrame()
|
||||
Expect(ack.AckRanges).To(BeEmpty())
|
||||
Expect(ack.ECNCE).To(BeZero())
|
||||
Expect(ack.ECT0).To(BeZero())
|
||||
Expect(ack.ECT1).To(BeZero())
|
||||
Expect(ack.DelayTime).To(BeZero())
|
||||
|
||||
ack.AckRanges = make([]AckRange, rand.Intn(10))
|
||||
ack.ECNCE = 1
|
||||
ack.ECT0 = 2
|
||||
ack.ECT1 = 3
|
||||
ack.DelayTime = time.Hour
|
||||
PutAckFrame(ack)
|
||||
}
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user