Skip to content

Commit ece4b0b

Browse files
committed
quic: bring in a related performance optimizations en route
1 parent 163c2db commit ece4b0b

6 files changed

Lines changed: 70 additions & 21 deletions

File tree

src/quic/application.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ class Session::Application : public MemoryRetainer {
146146
virtual void ReceiveStreamClose(Stream* stream,
147147
QuicError&& error = QuicError());
148148

149+
// Notify the Application that this stream is about to be removed
150+
virtual void StreamRemoved(stream_id id) {}
151+
149152
// Notifies the Application that the identified stream has been reset.
150153
virtual void ReceiveStreamReset(Stream* stream,
151154
uint64_t final_size,

src/quic/endpoint.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -466,14 +466,24 @@ class Endpoint::UDP::Impl final : public HandleWrap {
466466
// UV_UDP_MMSG_CHUNK is set for each packet in a recvmmsg batch.
467467
// Processing is the same as for a single-message receive — ngtcp2
468468
// copies what it needs synchronously from the buf slice.
469+
uint64_t now;
470+
if (flags & UV_UDP_MMSG_CHUNK) {
471+
if (impl->recv_batch_ts_ == 0) impl->recv_batch_ts_ = uv_hrtime();
472+
now = impl->recv_batch_ts_;
473+
} else {
474+
now = uv_hrtime();
475+
}
469476
impl->endpoint_->Receive(reinterpret_cast<const uint8_t*>(buf->base),
470477
static_cast<size_t>(nread),
471-
SocketAddress(addr));
478+
SocketAddress(addr),
479+
now);
472480
}
473481

474482
uv_udp_t handle_;
475483
Endpoint* endpoint_;
476484

485+
uint64_t recv_batch_ts_ = 0;
486+
477487
friend class UDP;
478488
};
479489

@@ -1353,9 +1363,8 @@ void Endpoint::CloseGracefully() {
13531363

13541364
void Endpoint::Receive(const uint8_t* data,
13551365
size_t len,
1356-
const SocketAddress& remote_address) {
1357-
const uint64_t now = uv_hrtime();
1358-
1366+
const SocketAddress& remote_address,
1367+
uint64_t now) {
13591368
// Block list filtering — applied before any packet processing to
13601369
// minimize resource expenditure on blocked sources.
13611370
if (options_.block_list) {

src/quic/endpoint.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,10 @@ class Endpoint final : public AsyncWrap, public Packet::Listener {
435435
// Ref() causes a listening Endpoint to keep the event loop active.
436436
JS_METHOD(Ref);
437437

438-
void Receive(const uint8_t* data, size_t len, const SocketAddress& from);
438+
void Receive(const uint8_t* data,
439+
size_t len,
440+
const SocketAddress& from,
441+
uint64_t now);
439442

440443
AliasedStruct<Stats> stats_;
441444
AliasedStruct<State> state_;

src/quic/http3.cc

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,12 @@ class Http3ApplicationImpl final : public Session::Application {
514514
flags.fin,
515515
flags.early);
516516

517+
uint64_t ts = session().rx_packet_ts();
518+
if (ts == 0) [[unlikely]] {
519+
ts = uv_hrtime();
520+
}
517521
auto nread = nghttp3_conn_read_stream2(
518-
*this, id, data, datalen, flags.fin ? 1 : 0, uv_hrtime());
522+
*this, id, data, datalen, flags.fin ? 1 : 0, ts);
519523

520524
if (nread < 0) {
521525
Debug(&session(),
@@ -665,6 +669,11 @@ class Http3ApplicationImpl final : public Session::Application {
665669
session().Close();
666670
}
667671

672+
void StreamRemoved(stream_id id) override {
673+
if (conn_) nghttp3_conn_set_stream_user_data(*this, id, nullptr);
674+
header_state_.erase(id);
675+
}
676+
668677
bool SendHeaders(const Stream& stream,
669678
HeadersKind kind,
670679
const Local<Array>& headers,
@@ -944,7 +953,7 @@ class Http3ApplicationImpl final : public Session::Application {
944953
}
945954

946955
void OnBeginHeaders(stream_id id) {
947-
auto stream = FindOrCreateStream(conn_.get(), &session(), id);
956+
auto stream = FindOrCreateStream(id);
948957
if (!stream) [[unlikely]]
949958
return;
950959
Debug(&session(),
@@ -997,7 +1006,7 @@ class Http3ApplicationImpl final : public Session::Application {
9971006
}
9981007

9991008
void OnBeginTrailers(stream_id id) {
1000-
auto stream = FindOrCreateStream(conn_.get(), &session(), id);
1009+
auto stream = FindOrCreateStream(id);
10011010
if (!stream) [[unlikely]]
10021011
return;
10031012
Debug(&session(),
@@ -1208,13 +1217,19 @@ class Http3ApplicationImpl final : public Session::Application {
12081217
return app;
12091218
}
12101219

1211-
static BaseObjectWeakPtr<Stream> FindOrCreateStream(nghttp3_conn* conn,
1212-
Session* session,
1213-
stream_id id) {
1214-
if (auto stream = session->FindStream(id)) {
1220+
// Persist the Stream* in the stream user data, so we can look it
1221+
// up directly without a FindStream map lookup every time.
1222+
void BindStreamUserData(stream_id id, Stream* stream) {
1223+
if (conn_) nghttp3_conn_set_stream_user_data(*this, id, stream);
1224+
}
1225+
1226+
BaseObjectWeakPtr<Stream> FindOrCreateStream(stream_id id) {
1227+
if (auto stream = session().FindStream(id)) {
1228+
BindStreamUserData(id, stream.get());
12151229
return stream;
12161230
}
1217-
if (auto stream = session->CreateStream(id)) {
1231+
if (auto stream = session().CreateStream(id)) {
1232+
BindStreamUserData(id, stream.get());
12181233
return stream;
12191234
}
12201235
return {};
@@ -1238,8 +1253,11 @@ class Http3ApplicationImpl final : public Session::Application {
12381253
auto& app = *ptr;
12391254
NgHttp3CallbackScope scope(&app.session());
12401255

1241-
auto stream = app.session().FindStream(id);
1242-
if (!stream) return NGHTTP3_ERR_CALLBACK_FAILURE;
1256+
BaseObjectPtr<Stream> stream(static_cast<Stream*>(stream_user_data));
1257+
if (!stream) [[unlikely]] {
1258+
stream = app.session().FindStream(id);
1259+
if (!stream) return NGHTTP3_ERR_CALLBACK_FAILURE;
1260+
}
12431261

12441262
if (stream->is_eos()) {
12451263
*pflags |= NGHTTP3_DATA_FLAG_EOF;
@@ -1320,7 +1338,11 @@ class Http3ApplicationImpl final : public Session::Application {
13201338
auto ptr = From(conn, conn_user_data);
13211339
CHECK_NOT_NULL(ptr);
13221340
auto& app = *ptr;
1323-
if (auto stream = app.session().FindStream(id)) {
1341+
BaseObjectPtr<Stream> stream(static_cast<Stream*>(stream_user_data));
1342+
if (!stream) [[unlikely]] {
1343+
stream = app.session().FindStream(id);
1344+
}
1345+
if (stream) {
13241346
stream->Acknowledge(static_cast<size_t>(datalen));
13251347
}
13261348
return NGTCP2_SUCCESS;
@@ -1351,12 +1373,16 @@ class Http3ApplicationImpl final : public Session::Application {
13511373
if (app.is_control_stream(id)) [[unlikely]] {
13521374
return NGHTTP3_ERR_CALLBACK_FAILURE;
13531375
}
1354-
auto& session = app.session();
1355-
if (auto stream = FindOrCreateStream(conn, &session, id)) [[likely]] {
1356-
stream->ReceiveData(data, datalen, Stream::ReceiveDataFlags{});
1357-
return NGTCP2_SUCCESS;
1376+
BaseObjectPtr<Stream> stream(static_cast<Stream*>(stream_user_data));
1377+
if (!stream) [[unlikely]] {
1378+
if (auto created = app.FindOrCreateStream(id)) {
1379+
created->ReceiveData(data, datalen, Stream::ReceiveDataFlags{});
1380+
return NGTCP2_SUCCESS;
1381+
}
1382+
return NGHTTP3_ERR_CALLBACK_FAILURE;
13581383
}
1359-
return NGHTTP3_ERR_CALLBACK_FAILURE;
1384+
stream->ReceiveData(data, datalen, Stream::ReceiveDataFlags{});
1385+
return NGTCP2_SUCCESS;
13601386
}
13611387

13621388
static int on_deferred_consume(nghttp3_conn* conn,

src/quic/session.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,7 +3041,9 @@ bool Session::ReadPacket(const uint8_t* data,
30413041
// receive path caches a timestamp and passes it to all ReadPacket()
30423042
// calls in the same I/O burst.
30433043
if (ts == 0) ts = uv_hrtime();
3044+
rx_packet_ts_ = ts;
30443045
err = ngtcp2_conn_read_pkt(*this, &path, pkt_info, data, len, ts);
3046+
rx_packet_ts_ = 0;
30453047
}
30463048
if (is_destroyed()) return false;
30473049

@@ -3538,6 +3540,8 @@ void Session::RemoveStream(stream_id id) {
35383540

35393541
ngtcp2_conn_set_stream_user_data(*this, id, nullptr);
35403542

3543+
if (impl_->application_) application().StreamRemoved(id);
3544+
35413545
// Note that removing the stream from the streams map likely releases
35423546
// the last BaseObjectPtr holding onto the Stream instance, at which
35433547
// point it will be freed. If there are other BaseObjectPtr instances

src/quic/session.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,8 @@ class Session final : public AsyncWrap, private SessionTicket::AppData::Source {
407407
const PacketInfo& pkt_info = PacketInfo(),
408408
uint64_t ts = 0);
409409

410+
uint64_t rx_packet_ts() const { return rx_packet_ts_; }
411+
410412
// Called by BindingData's flush callback to trigger SendPendingData
411413
// on this session. Encapsulates the application() access so that
412414
// bindingdata.cc doesn't need the full Application type definition.
@@ -736,6 +738,8 @@ class Session final : public AsyncWrap, private SessionTicket::AppData::Source {
736738
};
737739
Flags flags_;
738740

741+
uint64_t rx_packet_ts_ = 0;
742+
739743
bool hello_processed_ = false;
740744

741745
bool active_ = false;

0 commit comments

Comments
 (0)