Add a knob (QuicSentPacketManager::ReduceMemoryUsage) to reduce the memory used by unacked_packet_map and bandwidth_sampler owned by QuicSentPacketManager.

In follow-up, this knob can be used if the session is idled long enough.

PiperOrigin-RevId: 875952422
diff --git a/quiche/quic/core/congestion_control/bandwidth_sampler.h b/quiche/quic/core/congestion_control/bandwidth_sampler.h
index 4e7d95d..2b7d705 100644
--- a/quiche/quic/core/congestion_control/bandwidth_sampler.h
+++ b/quiche/quic/core/congestion_control/bandwidth_sampler.h
@@ -447,6 +447,8 @@
     return overestimate_avoidance_;
   }
 
+  void ReduceMemoryUsage() { connection_state_map_.shrink_to_fit(); }
+
  private:
   friend class test::BandwidthSamplerPeer;
 
diff --git a/quiche/quic/core/congestion_control/bbr2_misc.h b/quiche/quic/core/congestion_control/bbr2_misc.h
index 09654ad..84ba709 100644
--- a/quiche/quic/core/congestion_control/bbr2_misc.h
+++ b/quiche/quic/core/congestion_control/bbr2_misc.h
@@ -546,6 +546,8 @@
     return rounds_with_queueing_;
   }
 
+  void ReduceMemoryUsage() { bandwidth_sampler_.ReduceMemoryUsage(); }
+
  private:
   // Called when a new round trip starts.
   void OnNewRound();
diff --git a/quiche/quic/core/congestion_control/bbr2_sender.h b/quiche/quic/core/congestion_control/bbr2_sender.h
index 9338414..21ed5e8 100644
--- a/quiche/quic/core/congestion_control/bbr2_sender.h
+++ b/quiche/quic/core/congestion_control/bbr2_sender.h
@@ -100,6 +100,7 @@
 
   bool EnableECT0() override { return false; }
   bool EnableECT1() override { return false; }
+  void ReduceMemoryUsage() override { model_.ReduceMemoryUsage(); }
   // End implementation of SendAlgorithmInterface.
 
   const Bbr2Params& Params() const { return params_; }
diff --git a/quiche/quic/core/congestion_control/bbr_sender.h b/quiche/quic/core/congestion_control/bbr_sender.h
index f64978a..b9492f5 100644
--- a/quiche/quic/core/congestion_control/bbr_sender.h
+++ b/quiche/quic/core/congestion_control/bbr_sender.h
@@ -136,6 +136,7 @@
   void PopulateConnectionStats(QuicConnectionStats* stats) const override;
   bool EnableECT0() override { return false; }
   bool EnableECT1() override { return false; }
+  void ReduceMemoryUsage() override { sampler_.ReduceMemoryUsage(); }
   // End implementation of SendAlgorithmInterface.
 
   // Gets the number of RTTs BBR remains in STARTUP phase.
diff --git a/quiche/quic/core/congestion_control/send_algorithm_interface.h b/quiche/quic/core/congestion_control/send_algorithm_interface.h
index c42905d..47bf5b4 100644
--- a/quiche/quic/core/congestion_control/send_algorithm_interface.h
+++ b/quiche/quic/core/congestion_control/send_algorithm_interface.h
@@ -194,6 +194,9 @@
   // ECN mode is enabled, it is an error to call either of these methods.
   virtual bool EnableECT0() = 0;
   virtual bool EnableECT1() = 0;
+
+  // Called to reduce the memory usage of the send algorithm.
+  virtual void ReduceMemoryUsage() = 0;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h
index b62a808..c2150b4 100644
--- a/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h
+++ b/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h
@@ -78,6 +78,7 @@
   void PopulateConnectionStats(QuicConnectionStats* /*stats*/) const override {}
   bool EnableECT0() override { return false; }
   bool EnableECT1() override { return false; }
+  void ReduceMemoryUsage() override {}
   // End implementation of SendAlgorithmInterface.
 
   QuicByteCount min_congestion_window() const { return min_congestion_window_; }
diff --git a/quiche/quic/core/packet_number_indexed_queue.h b/quiche/quic/core/packet_number_indexed_queue.h
index ba50642..fc99a2f 100644
--- a/quiche/quic/core/packet_number_indexed_queue.h
+++ b/quiche/quic/core/packet_number_indexed_queue.h
@@ -96,6 +96,9 @@
   // Reserves the specified memory capacity in the underlying deque.
   void Reserve(size_t capacity) { entries_.reserve(capacity); }
 
+  // Reduces the capacity of the underlying deque.
+  void shrink_to_fit() { entries_.shrink_to_fit(); }
+
  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_sent_packet_manager.h b/quiche/quic/core/quic_sent_packet_manager.h
index e7dae0e..42d9e32 100644
--- a/quiche/quic/core/quic_sent_packet_manager.h
+++ b/quiche/quic/core/quic_sent_packet_manager.h
@@ -417,6 +417,11 @@
     return send_algorithm_.get();
   }
 
+  void ReduceMemoryUsage() {
+    unacked_packets_.ReduceMemoryUsage();
+    send_algorithm_->ReduceMemoryUsage();
+  }
+
   // Wrapper for SendAlgorithmInterface functions, since these functions are
   // not const.
   bool EnableECT0() {
diff --git a/quiche/quic/core/quic_unacked_packet_map.h b/quiche/quic/core/quic_unacked_packet_map.h
index fc6e89d..e37ac3c 100644
--- a/quiche/quic/core/quic_unacked_packet_map.h
+++ b/quiche/quic/core/quic_unacked_packet_map.h
@@ -269,6 +269,8 @@
         ", packets_in_flight: ", packets_in_flight_, "}");
   }
 
+  void ReduceMemoryUsage() { unacked_packets_.shrink_to_fit(); }
+
  private:
   friend class test::QuicUnackedPacketMapPeer;
 
diff --git a/quiche/quic/test_tools/quic_test_utils.h b/quiche/quic/test_tools/quic_test_utils.h
index 1d04449..c040b85 100644
--- a/quiche/quic/test_tools/quic_test_utils.h
+++ b/quiche/quic/test_tools/quic_test_utils.h
@@ -1255,6 +1255,7 @@
               (const, override));
   MOCK_METHOD(bool, EnableECT0, (), (override));
   MOCK_METHOD(bool, EnableECT1, (), (override));
+  MOCK_METHOD(void, ReduceMemoryUsage, (), (override));
 };
 
 class MockLossAlgorithm : public LossDetectionInterface {