For quic loss detection tuning, add a new reward function using average http latency and run it side by side with the existing reward function. protected by --gfe2_reloadable_flag_quic_enable_loss_detection_experiment_at_gfe. PiperOrigin-RevId: 319825747 Change-Id: Ic990510ce43f71990edb1ecc7180b8459e706173
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc index 0888a0e..e3dab64 100644 --- a/quic/core/http/end_to_end_test.cc +++ b/quic/core/http/end_to_end_test.cc
@@ -2631,9 +2631,11 @@ public: TestAckListener() {} - void OnPacketAcked(int acked_bytes, - QuicTime::Delta /*delta_largest_observed*/) override { + QuicTime::Delta OnPacketAcked( + int acked_bytes, + QuicTime::Delta /*delta_largest_observed*/) override { total_bytes_acked_ += acked_bytes; + return QuicTime::Delta::Zero(); } void OnPacketRetransmitted(int /*retransmitted_bytes*/) override {}
diff --git a/quic/core/http/quic_headers_stream.cc b/quic/core/http/quic_headers_stream.cc index 8157dae..7fc10dc 100644 --- a/quic/core/http/quic_headers_stream.cc +++ b/quic/core/http/quic_headers_stream.cc
@@ -91,7 +91,11 @@ return false; } if (header.ack_listener != nullptr && header_length > 0) { - header.ack_listener->OnPacketAcked(header_length, ack_delay_time); + QuicTime::Delta response_time = + header.ack_listener->OnPacketAcked(header_length, ack_delay_time); + if (!response_time.IsZero()) { + spdy_session_->RecordServerResponseTime(response_time); + } } header.unacked_length -= header_length; acked_offset += header_length;
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc index d6b5a0e..f470322 100644 --- a/quic/core/http/quic_spdy_session.cc +++ b/quic/core/http/quic_spdy_session.cc
@@ -1368,6 +1368,14 @@ quiche::QuicheStrCat(type, " stream is received twice.")); } +void QuicSpdySession::RecordServerResponseTime(QuicTime::Delta response_time) { + DCHECK_EQ(perspective(), Perspective::IS_SERVER); + QuicConnectionStats& stats = connection()->mutable_stats(); + + ++stats.num_responses; + stats.total_response_time = stats.total_response_time + response_time; +} + // static void QuicSpdySession::LogHeaderCompressionRatioHistogram( bool using_qpack,
diff --git a/quic/core/http/quic_spdy_session.h b/quic/core/http/quic_spdy_session.h index 4d6ee63..3773b88 100644 --- a/quic/core/http/quic_spdy_session.h +++ b/quic/core/http/quic_spdy_session.h
@@ -22,6 +22,7 @@ #include "net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.h" #include "net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h" #include "net/third_party/quiche/src/quic/core/quic_session.h" +#include "net/third_party/quiche/src/quic/core/quic_time.h" #include "net/third_party/quiche/src/quic/core/quic_versions.h" #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" #include "net/third_party/quiche/src/common/platform/api/quiche_optional.h" @@ -384,6 +385,9 @@ // Decode SETTINGS from |cached_state| and apply it to the session. bool ResumeApplicationState(ApplicationState* cached_state) override; + // (Server only) Records the response time of a completed request. + void RecordServerResponseTime(QuicTime::Delta response_time); + protected: // Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and // CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc index 4c979c1..c80ecc9 100644 --- a/quic/core/http/quic_spdy_stream.cc +++ b/quic/core/http/quic_spdy_stream.cc
@@ -919,8 +919,11 @@ DCHECK_LE(newly_acked_header_length, *newly_acked_length); unacked_frame_headers_offsets_.Difference(offset, offset + data_length); if (ack_listener_ != nullptr && new_data_acked) { - ack_listener_->OnPacketAcked( + QuicTime::Delta response_time = ack_listener_->OnPacketAcked( *newly_acked_length - newly_acked_header_length, ack_delay_time); + if (!response_time.IsZero()) { + spdy_session_->RecordServerResponseTime(response_time); + } } return new_data_acked; }
diff --git a/quic/core/quic_ack_listener_interface.h b/quic/core/quic_ack_listener_interface.h index 0a9c694..873015a 100644 --- a/quic/core/quic_ack_listener_interface.h +++ b/quic/core/quic_ack_listener_interface.h
@@ -20,8 +20,10 @@ // Called when a packet is acked. Called once per packet. // |acked_bytes| is the number of data bytes acked. - virtual void OnPacketAcked(int acked_bytes, - QuicTime::Delta ack_delay_time) = 0; + // Return the http response time if this is the last ack of a server stream. + // Otherwise return QuicTime::Delta::Zero(). + virtual QuicTime::Delta OnPacketAcked(int acked_bytes, + QuicTime::Delta ack_delay_time) = 0; // Called when a packet is retransmitted. Called once per packet. // |retransmitted_bytes| is the number of data bytes retransmitted.
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index 4cb08c5..69f00e4 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -3449,8 +3449,11 @@ FlushPackets(); connected_ = false; DCHECK(visitor_ != nullptr); - sent_packet_manager_.OnConnectionClosed(); visitor_->OnConnectionClosed(frame, source); + // LossDetectionTunerInterface::Finish() may be called from + // sent_packet_manager_.OnConnectionClosed. Which may require the session to + // finish its business first. + sent_packet_manager_.OnConnectionClosed(); if (debug_visitor_ != nullptr) { debug_visitor_->OnConnectionClosed(frame, source); }
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h index dc2a00f..b4f6445 100644 --- a/quic/core/quic_connection.h +++ b/quic/core/quic_connection.h
@@ -466,6 +466,8 @@ const std::string& details, ConnectionCloseBehavior connection_close_behavior); + QuicConnectionStats& mutable_stats() { return stats_; } + // Returns statistics tracked for this connection. const QuicConnectionStats& GetStats(); @@ -850,6 +852,7 @@ bool ack_frame_updated() const; QuicConnectionHelperInterface* helper() { return helper_; } + const QuicConnectionHelperInterface* helper() const { return helper_; } QuicAlarmFactory* alarm_factory() { return alarm_factory_; } quiche::QuicheStringPiece GetCurrentPacket();
diff --git a/quic/core/quic_connection_stats.h b/quic/core/quic_connection_stats.h index 3579be0..529a4ef 100644 --- a/quic/core/quic_connection_stats.h +++ b/quic/core/quic_connection_stats.h
@@ -162,6 +162,15 @@ // Number of sent packets that were encapsulated using Legacy Version // Encapsulation. QuicPacketCount sent_legacy_version_encapsulated_packets = 0; + + // HTTP server metrics. + // Number of success streams. i.e. streams in which all data are acked and + // have no stream error. + uint64_t num_responses = 0; + // Sum of response times for all success streams. A stream's response time is + // the time between stream creation to the time its last ack is received, + // minus the peer ack delay in the last ack. + QuicTime::Delta total_response_time = QuicTime::Delta::Zero(); }; } // namespace quic
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h index c936767..706eb64 100644 --- a/quic/core/quic_session.h +++ b/quic/core/quic_session.h
@@ -481,6 +481,10 @@ connection()->OnUserAgentIdKnown(); } + const QuicClock* GetClock() const { + return connection()->helper()->GetClock(); + } + protected: using StreamMap = QuicSmallMap<QuicStreamId, std::unique_ptr<QuicStream>, 10>;
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc index 0dba17b..32a8450 100644 --- a/quic/test_tools/quic_test_utils.cc +++ b/quic/test_tools/quic_test_utils.cc
@@ -835,7 +835,10 @@ MockLossAlgorithm::~MockLossAlgorithm() {} -MockAckListener::MockAckListener() {} +MockAckListener::MockAckListener() { + ON_CALL(*this, OnPacketAcked(_, _)) + .WillByDefault(testing::Return(QuicTime::Delta::Zero())); +} MockAckListener::~MockAckListener() {}
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h index 650213e..7be7edf 100644 --- a/quic/test_tools/quic_test_utils.h +++ b/quic/test_tools/quic_test_utils.h
@@ -1320,7 +1320,7 @@ MockAckListener(const MockAckListener&) = delete; MockAckListener& operator=(const MockAckListener&) = delete; - MOCK_METHOD(void, + MOCK_METHOD(QuicTime::Delta, OnPacketAcked, (int acked_bytes, QuicTime::Delta ack_delay_time), (override));