Skip to content

Commit 323e52f

Browse files
committed
src: minor quic packet cleanups
1 parent e74d9f4 commit 323e52f

File tree

3 files changed

+35
-24
lines changed

3 files changed

+35
-24
lines changed

src/quic/bindingdata.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
#include <node.h>
1212
#include <node_mem.h>
1313
#include <v8.h>
14+
#include <list>
1415
#include <unordered_map>
15-
#include <vector>
1616
#include "defs.h"
1717

1818
namespace node::quic {
@@ -172,7 +172,7 @@ class BindingData final
172172
// Purge the packet free list to free up memory.
173173
JS_METHOD(FlushPacketFreelist);
174174

175-
std::vector<BaseObjectPtr<BaseObject>> packet_freelist;
175+
std::list<BaseObjectPtr<BaseObject>> packet_freelist;
176176

177177
std::unordered_map<Endpoint*, BaseObjectPtr<BaseObject>> listening_endpoints;
178178

src/quic/packet.cc

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ BaseObjectPtr<Packet> Packet::Create(Environment* env,
120120
}
121121

122122
BaseObjectPtr<Packet> Packet::Clone() const {
123+
// Cloning is copy-free. Our data_ is a shared_ptr so we can just
124+
// share it with the cloned packet.
123125
auto& binding = BindingData::Get(env());
124126
if (binding.packet_freelist.empty()) {
125127
JS_NEW_INSTANCE_OR_RETURN(env(), obj, {});
@@ -135,8 +137,8 @@ BaseObjectPtr<Packet> Packet::FromFreeList(Environment* env,
135137
const SocketAddress& destination) {
136138
auto& binding = BindingData::Get(env);
137139
if (binding.packet_freelist.empty()) return {};
138-
auto obj = binding.packet_freelist.back();
139-
binding.packet_freelist.pop_back();
140+
auto obj = binding.packet_freelist.front();
141+
binding.packet_freelist.pop_front();
140142
CHECK(obj);
141143
CHECK_EQ(env, obj->env());
142144
auto packet = BaseObjectPtr<Packet>(static_cast<Packet*>(obj.get()));
@@ -185,6 +187,8 @@ void Packet::Done(int status) {
185187
// big, we don't want to accumulate these things forever.
186188
auto& binding = BindingData::Get(env());
187189
if (binding.packet_freelist.size() >= kMaxFreeList) {
190+
Debug(this, "Freelist full, destroying packet");
191+
data_.reset();
188192
return;
189193
}
190194

@@ -195,14 +199,18 @@ void Packet::Done(int status) {
195199
binding.packet_freelist.push_back(std::move(self));
196200
}
197201

202+
Packet::operator bool() const {
203+
return data_ != nullptr;
204+
}
205+
198206
std::string Packet::ToString() const {
199207
if (!data_) return "Packet (<empty>)";
200208
return "Packet (" + data_->ToString() + ")";
201209
}
202210

203211
void Packet::MemoryInfo(MemoryTracker* tracker) const {
204212
tracker->TrackField("destination", destination_);
205-
tracker->TrackField("data", data_);
213+
if (data_) tracker->TrackField("data", data_);
206214
}
207215

208216
BaseObjectPtr<Packet> Packet::CreateRetryPacket(

src/quic/packet.h

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,23 @@ struct PathDescriptor final {
2828
std::string ToString() const;
2929
};
3030

31-
// A Packet encapsulates serialized outbound QUIC data.
32-
// Packets must never be larger than the path MTU. The
33-
// default QUIC packet maximum length is 1200 bytes,
34-
// which we assume by default. The packet storage will
35-
// be stack allocated up to this size.
31+
// A Packet encapsulates serialized outbound QUIC data. Packets must never be
32+
// larger than the path MTU. The default QUIC packet maximum length is 1200
33+
// bytes, which we assume by default. The packet storage will be stack allocated
34+
// up to this size.
3635
//
37-
// Packets are maintained in a freelist held by the
38-
// BindingData instance. When using Create() to create
39-
// a Packet, we'll check to see if there is a free
40-
// packet in the freelist and use it instead of starting
41-
// fresh with a new packet. The freelist can store at
42-
// most kMaxFreeList packets
36+
// Packets are maintained in a freelist held by the BindingData instance. When
37+
// using Create() to create a Packet, we'll check to see if there is a free
38+
// packet in the freelist and use it instead of starting fresh with a new
39+
// packet. The freelist can store at most kMaxFreeList packets. This is a
40+
// performance optimization to avoid excessive allocation churn when creating
41+
// lots of packets since each one is ReqWrap and has a fair amount of associated
42+
// overhead. However, we don't want to accumulate too many of these in the
43+
// freelist either, so we cap the size.
4344
//
44-
// Packets are always encrypted so their content should
45-
// be considered opaque to us. We leave it entirely up
46-
// to ngtcp2 how to encode QUIC frames into the packet.
45+
// Packets are always encrypted so their content should be considered opaque
46+
// to us. We leave it entirely up to ngtcp2 how to encode QUIC frames into
47+
// the packet.
4748
class Packet final : public ReqWrap<uv_udp_send_t> {
4849
private:
4950
struct Data;
@@ -56,11 +57,9 @@ class Packet final : public ReqWrap<uv_udp_send_t> {
5657
virtual void PacketDone(int status) = 0;
5758
};
5859

59-
// Do not use the Packet constructors directly to create
60-
// them. These are public only to support MakeBaseObject.
61-
// Use the Create, or Create variants to create or
62-
// acquire packet instances.
63-
60+
// Do not use the Packet constructors directly to create them. These are
61+
// public only to support MakeBaseObject. Use the Create, or Create variants
62+
// to create or acquire packet instances.
6463
Packet(Environment* env,
6564
Listener* listener,
6665
v8::Local<v8::Object> object,
@@ -80,13 +79,17 @@ class Packet final : public ReqWrap<uv_udp_send_t> {
8079
size_t length() const;
8180
operator uv_buf_t() const;
8281
operator ngtcp2_vec() const;
82+
operator bool() const;
8383

8484
// Modify the size of the packet after ngtcp2 has written
8585
// to it. len must be <= length(). We call this after we've
8686
// asked ngtcp2 to encode frames into the packet and ngtcp2
8787
// tells us how many of the packets bytes were used.
8888
void Truncate(size_t len);
8989

90+
// Create (or acquire from the freelist) a Packet with the given
91+
// destination and length. The diagnostic_label is used to help
92+
// identify the packet purpose in debugging output.
9093
static BaseObjectPtr<Packet> Create(
9194
Environment* env,
9295
Listener* listener,

0 commit comments

Comments
 (0)