use a sync.Pool to reduce allocation of linked list elements

Especially the sentPacketHistory linked list shows up in allocation
profiles, since a new list element is allocated for every single packet
we send.
Using a pool for the receiving path, as well as for the frame sorter, is
less critical, since we're tracking ranges there instead of individual
packets / frames, but it doesn't hurt either.
The other occurrences where we use a linked list (connection ID tracking
and the token store) are used so rarely (a few times over the lifetime
of the connection) that using a pool doesn't make any sense there.
This commit is contained in:
Marten Seemann
2022-12-30 18:02:19 +13:00
parent dd30a02627
commit d9665c632e
5 changed files with 56 additions and 7 deletions

View File

@@ -1,6 +1,8 @@
package ackhandler
import (
"sync"
"github.com/lucas-clemente/quic-go/internal/protocol"
list "github.com/lucas-clemente/quic-go/internal/utils/linkedlist"
"github.com/lucas-clemente/quic-go/internal/wire"
@@ -12,6 +14,12 @@ type interval struct {
End protocol.PacketNumber
}
var intervalElementPool sync.Pool
func init() {
intervalElementPool = *list.NewPool[interval]()
}
// The receivedPacketHistory stores if a packet number has already been received.
// It generates ACK ranges which can be used to assemble an ACK frame.
// It does not store packet contents.
@@ -23,7 +31,7 @@ type receivedPacketHistory struct {
func newReceivedPacketHistory() *receivedPacketHistory {
return &receivedPacketHistory{
ranges: list.New[interval](),
ranges: list.NewWithPool[interval](&intervalElementPool),
}
}

View File

@@ -2,6 +2,7 @@ package ackhandler
import (
"fmt"
"sync"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
@@ -17,11 +18,17 @@ type sentPacketHistory struct {
highestSent protocol.PacketNumber
}
var packetElementPool sync.Pool
func init() {
packetElementPool = *list.NewPool[*Packet]()
}
func newSentPacketHistory(rttStats *utils.RTTStats) *sentPacketHistory {
return &sentPacketHistory{
rttStats: rttStats,
outstandingPacketList: list.New[*Packet](),
etcPacketList: list.New[*Packet](),
outstandingPacketList: list.NewWithPool[*Packet](&packetElementPool),
etcPacketList: list.NewWithPool[*Packet](&packetElementPool),
packetMap: make(map[protocol.PacketNumber]*list.Element[*Packet]),
highestSent: protocol.InvalidPacketNumber,
}