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 {