Allocate new blocks in QuicStreamSequencerBuffer only if there is any new data.

This is a bit useful if the same STREAM_FRAME is received again (due to spurious retransmission) after ReleaseWholeBuffer is called.

Protected by FLAGS_quic_reloadable_flag_quic_delay_sequencer_buffer_allocation_until_new_data.

PiperOrigin-RevId: 401235944
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 29688b9..54f6fa9 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -832,6 +832,8 @@
                          ::testing::PrintToStringParamName());
 
 TEST_P(EndToEndTest, HandshakeSuccessful) {
+  SetQuicReloadableFlag(quic_delay_sequencer_buffer_allocation_until_new_data,
+                        true);
   ASSERT_TRUE(Initialize());
   EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
   ASSERT_TRUE(server_thread_);
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 6b6d3f0..4399efa 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -47,6 +47,8 @@
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_on_pto, false)
 // If true, default-enable 5RTO blachole detection.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true)
+// If true, delay block allocation in QuicStreamSequencerBuffer until there is actually new data available.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_delay_sequencer_buffer_allocation_until_new_data, false)
 // If true, disable QUIC version Q043.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q043, false)
 // If true, disable QUIC version Q046.
diff --git a/quic/core/quic_stream_sequencer_buffer.cc b/quic/core/quic_stream_sequencer_buffer.cc
index 194b149..78c55c7 100644
--- a/quic/core/quic_stream_sequencer_buffer.cc
+++ b/quic/core/quic_stream_sequencer_buffer.cc
@@ -125,7 +125,9 @@
     *error_details = "Received data beyond available range.";
     return QUIC_INTERNAL_ERROR;
   }
-  MaybeAddMoreBlocks(starting_offset + size);
+  if (!delay_allocation_until_new_data_) {
+    MaybeAddMoreBlocks(starting_offset + size);
+  }
 
   if (bytes_received_.Empty() ||
       starting_offset >= bytes_received_.rbegin()->max() ||
@@ -140,6 +142,11 @@
       *error_details = "Too many data intervals received for this stream.";
       return QUIC_TOO_MANY_STREAM_DATA_INTERVALS;
     }
+    if (delay_allocation_until_new_data_) {
+      QUIC_RELOADABLE_FLAG_COUNT_N(
+          quic_delay_sequencer_buffer_allocation_until_new_data, 1, 2);
+      MaybeAddMoreBlocks(starting_offset + size);
+    }
 
     size_t bytes_copy = 0;
     if (!CopyStreamData(starting_offset, data, &bytes_copy, error_details)) {
@@ -163,6 +170,11 @@
     *error_details = "Too many data intervals received for this stream.";
     return QUIC_TOO_MANY_STREAM_DATA_INTERVALS;
   }
+  if (delay_allocation_until_new_data_) {
+    QUIC_RELOADABLE_FLAG_COUNT_N(
+        quic_delay_sequencer_buffer_allocation_until_new_data, 2, 2);
+    MaybeAddMoreBlocks(starting_offset + size);
+  }
   for (const auto& interval : newly_received) {
     const QuicStreamOffset copy_offset = interval.min();
     const QuicByteCount copy_length = interval.max() - interval.min();
diff --git a/quic/core/quic_stream_sequencer_buffer.h b/quic/core/quic_stream_sequencer_buffer.h
index c99cc93..83ce01b 100644
--- a/quic/core/quic_stream_sequencer_buffer.h
+++ b/quic/core/quic_stream_sequencer_buffer.h
@@ -239,6 +239,9 @@
 
   // Currently received data.
   QuicIntervalSet<QuicStreamOffset> bytes_received_;
+
+  bool delay_allocation_until_new_data_ = GetQuicReloadableFlag(
+      quic_delay_sequencer_buffer_allocation_until_new_data);
 };
 
 }  // namespace quic