Add a flag to preallocate memory for unacked packets in both QuicUnackedPacketMap and BandwidthSampler via a command-line flag. Protected by FLAGS_quic_preallocate_unacked_packets. PiperOrigin-RevId: 764817335
diff --git a/quiche/common/quiche_protocol_flags_list.h b/quiche/common/quiche_protocol_flags_list.h index b19aa72..de2a763 100644 --- a/quiche/common/quiche_protocol_flags_list.h +++ b/quiche/common/quiche_protocol_flags_list.h
@@ -280,4 +280,10 @@ uint64_t, quic_multiplexer_alarm_granularity_us, 1000, "Alarm update granularity used by the QUICHE multiplexer alarm") +QUICHE_PROTOCOL_FLAG( + size_t, quic_preallocate_unacked_packets, 0, + "Preallocate the specified number of entries in the unacked packet map. " + "If QuicConnection::GetUnackedMapInitialCapacity() already specifies a " + "number, the larger of two applies.") + #endif
diff --git a/quiche/quic/core/congestion_control/bandwidth_sampler.cc b/quiche/quic/core/congestion_control/bandwidth_sampler.cc index f41c80e..1493c08 100644 --- a/quiche/quic/core/congestion_control/bandwidth_sampler.cc +++ b/quiche/quic/core/congestion_control/bandwidth_sampler.cc
@@ -5,6 +5,7 @@ #include "quiche/quic/core/congestion_control/bandwidth_sampler.h" #include <algorithm> +#include <cstddef> #include <ostream> #include "quiche/quic/core/quic_types.h" @@ -148,7 +149,13 @@ max_ack_height_tracker_(max_height_tracker_window_length), total_bytes_acked_after_last_ack_event_(0), overestimate_avoidance_(false), - limit_max_ack_height_tracker_by_send_rate_(false) {} + limit_max_ack_height_tracker_by_send_rate_(false) { + const size_t preallocate_count = + GetQuicFlag(quic_preallocate_unacked_packets); + if (preallocate_count > 0) { + connection_state_map_.Reserve(preallocate_count); + } +} BandwidthSampler::BandwidthSampler(const BandwidthSampler& other) : total_bytes_sent_(other.total_bytes_sent_),
diff --git a/quiche/quic/core/packet_number_indexed_queue.h b/quiche/quic/core/packet_number_indexed_queue.h index e896f87..ba50642 100644 --- a/quiche/quic/core/packet_number_indexed_queue.h +++ b/quiche/quic/core/packet_number_indexed_queue.h
@@ -5,6 +5,8 @@ #ifndef QUICHE_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_ #define QUICHE_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_ +#include <cstddef> + #include "quiche/quic/core/quic_constants.h" #include "quiche/quic/core/quic_packet_number.h" #include "quiche/quic/core/quic_types.h" @@ -91,6 +93,9 @@ return first_packet_ + entries_.size() - 1; } + // Reserves the specified memory capacity in the underlying deque. + void Reserve(size_t capacity) { entries_.reserve(capacity); } + private: // Wrapper around T used to mark whether the entry is actually in the map. struct QUICHE_NO_EXPORT EntryWrapper : T {
diff --git a/quiche/quic/core/quic_unacked_packet_map.cc b/quiche/quic/core/quic_unacked_packet_map.cc index c9d3541..419982b 100644 --- a/quiche/quic/core/quic_unacked_packet_map.cc +++ b/quiche/quic/core/quic_unacked_packet_map.cc
@@ -4,6 +4,7 @@ #include "quiche/quic/core/quic_unacked_packet_map.h" +#include <algorithm> #include <cstddef> #include <limits> #include <type_traits> @@ -18,6 +19,7 @@ #include "quiche/quic/core/quic_utils.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/quic/platform/api/quic_flag_utils.h" +#include "quiche/quic/platform/api/quic_flags.h" #include "quiche/common/simple_buffer_allocator.h" namespace quic { @@ -730,4 +732,9 @@ return content; } +void QuicUnackedPacketMap::ReserveInitialCapacity(size_t initial_capacity) { + const size_t flag_capacity = GetQuicFlag(quic_preallocate_unacked_packets); + unacked_packets_.reserve(std::max(initial_capacity, flag_capacity)); +} + } // namespace quic
diff --git a/quiche/quic/core/quic_unacked_packet_map.h b/quiche/quic/core/quic_unacked_packet_map.h index 30e3394..fc6e89d 100644 --- a/quiche/quic/core/quic_unacked_packet_map.h +++ b/quiche/quic/core/quic_unacked_packet_map.h
@@ -257,9 +257,7 @@ return supports_multiple_packet_number_spaces_; } - void ReserveInitialCapacity(size_t initial_capacity) { - unacked_packets_.reserve(initial_capacity); - } + void ReserveInitialCapacity(size_t initial_capacity); std::string DebugString() const { return absl::StrCat(
diff --git a/quiche/quic/core/quic_unacked_packet_map_test.cc b/quiche/quic/core/quic_unacked_packet_map_test.cc index b859bc7..3bfcc37 100644 --- a/quiche/quic/core/quic_unacked_packet_map_test.cc +++ b/quiche/quic/core/quic_unacked_packet_map_test.cc
@@ -760,7 +760,7 @@ EXPECT_FALSE(unacked_packets_.GetLastPacketContent() & (1 << ACK_FRAME)); } -TEST_P(QuicUnackedPacketMapTest, ReserveInitialCapacityTest) { +TEST_P(QuicUnackedPacketMapTest, ReserveInitialCapacity) { QuicUnackedPacketMap unacked_packets(GetParam()); ASSERT_EQ(QuicUnackedPacketMapPeer::GetCapacity(unacked_packets), 0u); unacked_packets.ReserveInitialCapacity(16); @@ -771,6 +771,18 @@ ASSERT_EQ(QuicUnackedPacketMapPeer::GetCapacity(unacked_packets), 16u); } +TEST_P(QuicUnackedPacketMapTest, ReserveInitialCapacityViaFlag) { + SetQuicFlag(quic_preallocate_unacked_packets, 1024); + QuicUnackedPacketMap unacked_packets(GetParam()); + ASSERT_EQ(QuicUnackedPacketMapPeer::GetCapacity(unacked_packets), 0u); + unacked_packets.ReserveInitialCapacity(16); + QuicStreamId stream_id(1); + SerializedPacket packet(CreateRetransmittablePacketForStream(1, stream_id)); + unacked_packets.AddSentPacket(&packet, TransmissionType::NOT_RETRANSMISSION, + now_, true, true, ECN_NOT_ECT); + ASSERT_EQ(QuicUnackedPacketMapPeer::GetCapacity(unacked_packets), 1024u); +} + TEST_P(QuicUnackedPacketMapTest, DebugString) { EXPECT_EQ(unacked_packets_.DebugString(), "{size: 0, least_unacked: 1, largest_sent_packet: uninitialized, "