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, "