Internal QUICHE change PiperOrigin-RevId: 301656000 Change-Id: Icf94da3805b379e988edd32dfcfddb8222318d78
diff --git a/quic/core/congestion_control/bandwidth_sampler.cc b/quic/core/congestion_control/bandwidth_sampler.cc index df6eb24..37a49a1 100644 --- a/quic/core/congestion_control/bandwidth_sampler.cc +++ b/quic/core/congestion_control/bandwidth_sampler.cc
@@ -78,7 +78,7 @@ total_bytes_sent_at_last_acked_packet_(0), last_acked_packet_sent_time_(QuicTime::Zero()), last_acked_packet_ack_time_(QuicTime::Zero()), - is_app_limited_(false), + is_app_limited_(started_as_app_limited_), connection_state_map_(), max_tracked_packets_(GetQuicFlag(FLAGS_quic_max_tracked_packet_count)), unacked_packet_map_(unacked_packet_map), @@ -289,11 +289,26 @@ recent_ack_points_.Update(ack_time, total_bytes_acked_); } - // Exit app-limited phase once a packet that was sent while the connection is - // not app-limited is acknowledged. - if (is_app_limited_ && end_of_app_limited_phase_.IsInitialized() && - packet_number > end_of_app_limited_phase_) { - is_app_limited_ = false; + if (started_as_app_limited_) { + if (is_app_limited_) { + // Exit app-limited phase in two cases: + // (1) end_of_app_limited_phase_ is not initialized, i.e., so far all + // packets are sent while there are buffered packets or pending data. + // (2) The current acked packet is after the sent packet marked as the end + // of the app limit phase. + if (!end_of_app_limited_phase_.IsInitialized() || + packet_number > end_of_app_limited_phase_) { + QUIC_RELOADABLE_FLAG_COUNT(quic_bw_sampler_app_limited_starting_value); + is_app_limited_ = false; + } + } + } else { + // Exit app-limited phase once a packet that was sent while the connection + // is not app-limited is acknowledged. + if (is_app_limited_ && end_of_app_limited_phase_.IsInitialized() && + packet_number > end_of_app_limited_phase_) { + is_app_limited_ = false; + } } // There might have been no packets acknowledged at the moment when the
diff --git a/quic/core/congestion_control/bandwidth_sampler.h b/quic/core/congestion_control/bandwidth_sampler.h index b0ad576..0a69447 100644 --- a/quic/core/congestion_control/bandwidth_sampler.h +++ b/quic/core/congestion_control/bandwidth_sampler.h
@@ -509,6 +509,10 @@ // The most recently sent packet. QuicPacketNumber last_sent_packet_; + // Indicates whether the bandwidth sampler is started in app-limited phase. + const bool started_as_app_limited_ = + GetQuicReloadableFlag(quic_bw_sampler_app_limited_starting_value); + // Indicates whether the bandwidth sampler is currently in an app-limited // phase. bool is_app_limited_;
diff --git a/quic/core/congestion_control/bandwidth_sampler_test.cc b/quic/core/congestion_control/bandwidth_sampler_test.cc index 73b812f..5dda998 100644 --- a/quic/core/congestion_control/bandwidth_sampler_test.cc +++ b/quic/core/congestion_control/bandwidth_sampler_test.cc
@@ -39,6 +39,7 @@ protected: BandwidthSamplerTest() : sampler_(nullptr, /*max_height_tracker_window_length=*/0), + sampler_app_limited_at_start_(sampler_.is_app_limited()), bytes_in_flight_(0), max_bandwidth_(QuicBandwidth::Zero()), est_bandwidth_upper_bound_(QuicBandwidth::Infinite()), @@ -53,6 +54,7 @@ MockClock clock_; BandwidthSampler sampler_; + bool sampler_app_limited_at_start_; QuicByteCount bytes_in_flight_; QuicBandwidth max_bandwidth_; // Max observed bandwidth from acks. QuicBandwidth est_bandwidth_upper_bound_; @@ -89,6 +91,7 @@ bandwidth_sample.bandwidth = sample.sample_max_bandwidth; bandwidth_sample.rtt = sample.sample_rtt; bandwidth_sample.state_at_send = sample.last_packet_send_state; + EXPECT_TRUE(bandwidth_sample.state_at_send.is_valid); return bandwidth_sample; } @@ -107,8 +110,6 @@ // Acknowledge receipt of a packet and expect it to be not app-limited. QuicBandwidth AckPacket(uint64_t packet_number) { BandwidthSample sample = AckPacketInner(packet_number); - EXPECT_TRUE(sample.state_at_send.is_valid); - EXPECT_FALSE(sample.state_at_send.is_app_limited); return sample.bandwidth; } @@ -446,14 +447,29 @@ QuicBandwidth expected_bandwidth = QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize); - Send40PacketsAndAckFirst20(time_between_packets); + // Send 20 packets at a constant inter-packet time. + for (int i = 1; i <= 20; i++) { + SendPacket(i); + clock_.AdvanceTime(time_between_packets); + } + + // Ack packets 1 to 20, while sending new packets at the same rate as + // before. + for (int i = 1; i <= 20; i++) { + BandwidthSample sample = AckPacketInner(i); + EXPECT_EQ(sample.state_at_send.is_app_limited, + sampler_app_limited_at_start_); + SendPacket(i + 20); + clock_.AdvanceTime(time_between_packets); + } // We are now app-limited. Ack 21 to 40 as usual, but do not send anything for // now. sampler_.OnAppLimited(); for (int i = 21; i <= 40; i++) { - QuicBandwidth current_sample = AckPacket(i); - EXPECT_EQ(expected_bandwidth, current_sample); + BandwidthSample sample = AckPacketInner(i); + EXPECT_FALSE(sample.state_at_send.is_app_limited); + EXPECT_EQ(expected_bandwidth, sample.bandwidth); clock_.AdvanceTime(time_between_packets); } @@ -480,8 +496,9 @@ // Run out of packets, and then ack packet 61 to 80, all of which should have // correct non-app-limited samples. for (int i = 61; i <= 80; i++) { - QuicBandwidth last_bandwidth = AckPacket(i); - EXPECT_EQ(expected_bandwidth, last_bandwidth); + BandwidthSample sample = AckPacketInner(i); + EXPECT_FALSE(sample.state_at_send.is_app_limited); + EXPECT_EQ(sample.bandwidth, expected_bandwidth); clock_.AdvanceTime(time_between_packets); } sampler_.RemoveObsoletePackets(QuicPacketNumber(81));
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc index 2e12f5b..a10f415 100644 --- a/quic/core/quic_session.cc +++ b/quic/core/quic_session.cc
@@ -1376,7 +1376,9 @@ // to the client. control_frame_manager_.WriteOrBufferHandshakeDone(); } - connection_->ResetHasNonAppLimitedSampleAfterHandshakeCompletion(); + if (!GetQuicReloadableFlag(quic_bw_sampler_app_limited_starting_value)) { + connection_->ResetHasNonAppLimitedSampleAfterHandshakeCompletion(); + } break; default: QUIC_BUG << "Unknown encryption level: "