Optimize QpackBlockingManager::blocking_allowed_on_stream().

Iterating through |header_blocks_| can be costly, so handle the presumably
common cases of zero and very large blocked stream limits first.  Also,
do early return as soon as |blocked_stream_count| gets too large.

gfe-relnote: n/a, change to QUIC v99-only code.  Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 271596962
Change-Id: I18ecea0ae7c631c52c8cb53badbff2ff3471b2c4
diff --git a/quic/core/qpack/qpack_blocking_manager.cc b/quic/core/qpack/qpack_blocking_manager.cc
index f121aa0..2243c90 100644
--- a/quic/core/qpack/qpack_blocking_manager.cc
+++ b/quic/core/qpack/qpack_blocking_manager.cc
@@ -74,6 +74,18 @@
 bool QpackBlockingManager::blocking_allowed_on_stream(
     QuicStreamId stream_id,
     uint64_t maximum_blocked_streams) const {
+  // This should be the most common case: the limit is larger than the number of
+  // streams that have unacknowledged header blocks (regardless of whether they
+  // are blocked or not) plus one for stream |stream_id|.
+  if (header_blocks_.size() + 1 <= maximum_blocked_streams) {
+    return true;
+  }
+
+  // This should be another common case: no blocked stream allowed.
+  if (maximum_blocked_streams == 0) {
+    return false;
+  }
+
   uint64_t blocked_stream_count = 0;
   for (const auto& header_blocks_for_stream : header_blocks_) {
     for (const IndexSet& indices : header_blocks_for_stream.second) {
@@ -84,14 +96,31 @@
           return true;
         }
         ++blocked_stream_count;
+        // If stream |stream_id| is already blocked, then it is not counted yet,
+        // therefore the number of blocked streams is at least
+        // |blocked_stream_count + 1|, which cannot be more than
+        // |maximum_blocked_streams| by API contract.
+        // If stream |stream_id| is not blocked, then blocking will increase the
+        // blocked stream count to at least |blocked_stream_count + 1|.  If that
+        // is larger than |maximum_blocked_streams|, then blocking is not
+        // allowed on stream |stream_id|.
+        if (blocked_stream_count + 1 > maximum_blocked_streams) {
+          return false;
+        }
         break;
       }
     }
   }
 
-  // Stream |stream_id| is not blocked, therefore sending blocking references on
-  // it would increase the blocked stream count by one.
-  return blocked_stream_count + 1 <= maximum_blocked_streams;
+  // Stream |stream_id| is not blocked.
+  // If there are no blocked streams, then
+  // |blocked_stream_count + 1 <= maximum_blocked_streams| because
+  // |maximum_blocked_streams| is larger than zero.
+  // If there are are blocked streams, then
+  // |blocked_stream_count + 1 <= maximum_blocked_streams| otherwise the method
+  // would have returned false when |blocked_stream_count| was incremented.
+  // Therefore blocking on |stream_id| is allowed.
+  return true;
 }
 
 uint64_t QpackBlockingManager::smallest_blocking_index() const {