55#include < ngtcp2/ngtcp2.h>
66#include < node_sockaddr.h>
77#include < uv.h>
8- #include < v8.h>
98#include < string>
109#include " arena.h"
1110#include " cid.h"
@@ -39,6 +38,10 @@ struct PathDescriptor final {
3938//
4039// Packets are always encrypted; their content is opaque. We leave it
4140// entirely up to ngtcp2 how to encode QUIC frames into the packet.
41+ //
42+ // Member layout is ordered so that fields touched on the hot path
43+ // (data_, capacity_, length_, listener_) share the first cache line.
44+ // The uv_udp_send_t (320 bytes, only touched by libuv) is placed last.
4245class Packet final {
4346 public:
4447 using Ptr = ArenaPool<Packet>::Ptr;
@@ -58,49 +61,61 @@ class Packet final {
5861
5962 DISALLOW_COPY_AND_MOVE (Packet)
6063
61- const SocketAddress& destination () const ;
62- Listener* listener () const ;
63- size_t length () const ;
64- size_t capacity () const ;
65- uint8_t * data ();
66- const uint8_t * data () const ;
67- operator uv_buf_t () const ;
68- operator ngtcp2_vec () const ;
64+ // --- Inline accessors (hot path) ---
65+
66+ uint8_t * data () { return data_; }
67+ const uint8_t * data () const { return data_; }
68+ size_t length () const { return length_; }
69+ size_t capacity () const { return capacity_; }
70+ const SocketAddress& destination () const { return destination_; }
71+ Listener* listener () const { return listener_; }
72+ uv_udp_send_t * req () { return &req_; }
73+
74+ operator uv_buf_t () const {
75+ return uv_buf_init (reinterpret_cast <char *>(data_), length_);
76+ }
77+ operator ngtcp2_vec () const { return ngtcp2_vec{data_, length_}; }
6978
7079 // Modify the logical size of the packet after ngtcp2 has written
7180 // to it. len must be <= capacity().
72- void Truncate (size_t len);
73-
74- uv_udp_send_t * req ();
81+ void Truncate (size_t len) {
82+ DCHECK_LE (len, capacity_);
83+ length_ = len;
84+ }
7585
7686 // Recover Packet* from a uv_udp_send_t* in the libuv send callback.
77- static Packet* FromReq (uv_udp_send_t * req);
87+ static Packet* FromReq (uv_udp_send_t * req) {
88+ return ContainerOf (&Packet::req_, req);
89+ }
7890
7991 // --- Static factory methods ---
8092 // These create fully-formed packets for specific QUIC operations.
8193 // They acquire from the endpoint's packet pool and return Ptr.
8294 // An empty Ptr indicates failure.
8395
84- static Ptr CreateRetryPacket (Endpoint& endpoint,
85- const PathDescriptor& path_descriptor,
86- const TokenSecret& token_secret);
96+ [[nodiscard]] static Ptr CreateRetryPacket (
97+ Endpoint& endpoint,
98+ const PathDescriptor& path_descriptor,
99+ const TokenSecret& token_secret);
87100
88- static Ptr CreateConnectionClosePacket (Endpoint& endpoint,
89- const SocketAddress& destination,
90- ngtcp2_conn* conn,
91- const QuicError& error);
101+ [[nodiscard]] static Ptr CreateConnectionClosePacket (
102+ Endpoint& endpoint,
103+ const SocketAddress& destination,
104+ ngtcp2_conn* conn,
105+ const QuicError& error);
92106
93- static Ptr CreateImmediateConnectionClosePacket (
107+ [[nodiscard]] static Ptr CreateImmediateConnectionClosePacket (
94108 Endpoint& endpoint,
95109 const PathDescriptor& path_descriptor,
96110 const QuicError& reason);
97111
98- static Ptr CreateStatelessResetPacket (Endpoint& endpoint,
99- const PathDescriptor& path_descriptor,
100- const TokenSecret& token_secret,
101- size_t source_len);
112+ [[nodiscard]] static Ptr CreateStatelessResetPacket (
113+ Endpoint& endpoint,
114+ const PathDescriptor& path_descriptor,
115+ const TokenSecret& token_secret,
116+ size_t source_len);
102117
103- static Ptr CreateVersionNegotiationPacket (
118+ [[nodiscard]] static Ptr CreateVersionNegotiationPacket (
104119 Endpoint& endpoint, const PathDescriptor& path_descriptor);
105120
106121 // --- Diagnostic label: zero cost in release builds ---
@@ -113,12 +128,17 @@ class Packet final {
113128 std::string ToString () const ;
114129
115130 private:
116- uv_udp_send_t req_;
117- Listener* listener_;
118- SocketAddress destination_;
131+ // Hot fields first — all on cache line 0 during the fill loop.
119132 uint8_t * data_;
120133 size_t capacity_;
121134 size_t length_;
135+ Listener* listener_;
136+
137+ // Touched at send time.
138+ SocketAddress destination_;
139+
140+ // Only touched by libuv during uv_udp_send and in the send callback.
141+ uv_udp_send_t req_;
122142
123143#ifdef DEBUG
124144 const char * diagnostic_label_ = nullptr ;
0 commit comments