| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 46a0868 commit a2b6a81
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -302,7 +302,10 @@ class Endpoint::UDP::Impl final : public HandleWrap { | |||
| 302 | 302 | reinterpret_cast<uv_handle_t*>(&handle_), | |
| 303 | 303 | PROVIDER_QUIC_UDP), | |
| 304 | 304 | endpoint_(endpoint) { | |
| 305 | - CHECK_EQ(uv_udp_init(endpoint->env()->event_loop(), &handle_), 0); | ||
| 305 | + CHECK_EQ(uv_udp_init_ex(endpoint->env()->event_loop(), | ||
| 306 | + &handle_, | ||
| 307 | + AF_UNSPEC | UV_UDP_RECVMMSG), | ||
| 308 | + 0); | ||
| 306 | 309 | handle_.data = this; | |
| 307 | 310 | } | |
| 308 | 311 | ||
@@ -311,18 +314,26 @@ class Endpoint::UDP::Impl final : public HandleWrap { | |||
| 311 | 314 | SET_SELF_SIZE(Impl) | |
| 312 | 315 | ||
| 313 | 316 | private: | |
| 314 | - // Pre-allocated receive buffer. Reused across all datagrams because | ||
| 315 | - // ngtcp2_conn_read_pkt is synchronous — it copies what it needs and | ||
| 316 | - // does not retain a reference to the buffer after returning. This | ||
| 317 | - // eliminates a malloc(64KB)/free(64KB) cycle per received datagram. | ||
| 318 | - static constexpr size_t kRecvBufferSize = 65536; // UV__UDP_DGRAM_MAXSIZE | ||
| 319 | - char recv_buf_[kRecvBufferSize]; | ||
| 317 | + // Pre-allocated receive buffer sized for recvmmsg batching. libuv's | ||
| 318 | + // recvmmsg path partitions the alloc buffer into 64KB chunks (one per | ||
| 319 | + // datagram). With kRecvBatchSize chunks we can receive up to that many | ||
| 320 | + // packets in a single recvmmsg syscall. ngtcp2_conn_read_pkt is | ||
| 321 | + // synchronous — it copies what it needs — so the buffer is safely | ||
| 322 | + // reused across batches. | ||
| 323 | + // libuv's recvmmsg partitions the buffer into UV__UDP_DGRAM_MAXSIZE (64KB) | ||
| 324 | + // chunks regardless of actual packet size. QUIC packets are ~1200 bytes, | ||
| 325 | + // so most of each 64KB chunk is wasted. We use a modest batch size to | ||
| 326 | + // balance syscall reduction against memory usage. | ||
| 327 | + static constexpr size_t kDgramMaxSize = 65536; // UV__UDP_DGRAM_MAXSIZE | ||
| 328 | + static constexpr size_t kRecvBatchSize = 5; | ||
| 329 | + static constexpr size_t kRecvBufferSize = kDgramMaxSize * kRecvBatchSize; | ||
| 330 | + std::array<char, kRecvBufferSize> recv_buf_ = {}; | ||
| 320 | 331 | ||
| 321 | 332 | static void OnAlloc(uv_handle_t* handle, | |
| 322 | 333 | size_t suggested_size, | |
| 323 | 334 | uv_buf_t* buf) { | |
| 324 | 335 | auto* impl = From(handle); | |
| 325 | - *buf = uv_buf_init(impl->recv_buf_, kRecvBufferSize); | ||
| 336 | + *buf = uv_buf_init(impl->recv_buf_.data(), kRecvBufferSize); | ||
| 326 | 337 | } | |
| 327 | 338 | ||
| 328 | 339 | static void OnReceive(uv_udp_t* handle, | |
@@ -334,6 +345,13 @@ class Endpoint::UDP::Impl final : public HandleWrap { | |||
| 334 | 345 | DCHECK_NOT_NULL(impl); | |
| 335 | 346 | DCHECK_NOT_NULL(impl->endpoint_); | |
| 336 | 347 | ||
| 348 | + // UV_UDP_MMSG_FREE signals the end of a recvmmsg batch — the | ||
| 349 | + // buffer can be reused. Since our buffer is pre-allocated and | ||
| 350 | + // persistent, there is nothing to free. | ||
| 351 | + if (flags & UV_UDP_MMSG_FREE) { | ||
| 352 | + return; | ||
| 353 | + } | ||
| 354 | + | ||
| 337 | 355 | // Nothing to do in these cases. Specifically, if the nread | |
| 338 | 356 | // is zero or we have received a partial packet, we are just | |
| 339 | 357 | // going to ignore it. No buffer release needed — recv_buf_ | |
@@ -348,6 +366,9 @@ class Endpoint::UDP::Impl final : public HandleWrap { | |||
| 348 | 366 | return; | |
| 349 | 367 | } | |
| 350 | 368 | ||
| 369 | + // UV_UDP_MMSG_CHUNK is set for each packet in a recvmmsg batch. | ||
| 370 | + // Processing is the same as for a single-message receive — ngtcp2 | ||
| 371 | + // copies what it needs synchronously from the buf slice. | ||
| 351 | 372 | impl->endpoint_->Receive(reinterpret_cast<const uint8_t*>(buf->base), | |
| 352 | 373 | static_cast<size_t>(nread), | |
| 353 | 374 | SocketAddress(addr)); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments