Index: net/quic/quic_headers_stream.cc |
diff --git a/net/quic/quic_headers_stream.cc b/net/quic/quic_headers_stream.cc |
index f78dffbfc26aa23a0d4f0dad8ad4fc4a536b1559..d8560693e98c0245c449a65de75901523c36a670 100644 |
--- a/net/quic/quic_headers_stream.cc |
+++ b/net/quic/quic_headers_stream.cc |
@@ -4,10 +4,16 @@ |
#include "net/quic/quic_headers_stream.h" |
+#include "base/metrics/histogram_macros.h" |
#include "base/strings/stringprintf.h" |
+#include "net/quic/quic_flags.h" |
+#include "net/quic/quic_headers_stream.h" |
#include "net/quic/quic_spdy_session.h" |
+#include "net/quic/quic_time.h" |
using base::StringPiece; |
+using net::HTTP2; |
+using net::SpdyFrameType; |
using std::string; |
namespace net { |
@@ -174,6 +180,10 @@ QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session) |
stream_id_(kInvalidStreamId), |
fin_(false), |
frame_len_(0), |
+ measure_headers_hol_blocking_time_( |
+ FLAGS_quic_measure_headers_hol_blocking_time), |
+ cur_max_timestamp_(QuicTime::Zero()), |
+ prev_max_timestamp_(QuicTime::Zero()), |
spdy_framer_(HTTP2), |
spdy_framer_visitor_(new SpdyFramerVisitor(this)) { |
spdy_framer_.set_visitor(spdy_framer_visitor_.get()); |
@@ -207,12 +217,22 @@ size_t QuicHeadersStream::WriteHeaders( |
void QuicHeadersStream::OnDataAvailable() { |
char buffer[1024]; |
struct iovec iov; |
+ QuicTime timestamp(QuicTime::Zero()); |
while (true) { |
iov.iov_base = buffer; |
iov.iov_len = arraysize(buffer); |
- if (sequencer()->GetReadableRegions(&iov, 1) != 1) { |
- // No more data to read. |
- break; |
+ if (measure_headers_hol_blocking_time_) { |
+ if (!sequencer()->GetReadableRegion(&iov, ×tamp)) { |
+ // No more data to read. |
+ break; |
+ } |
+ DCHECK(timestamp.IsInitialized()); |
+ cur_max_timestamp_ = QuicTime::Max(timestamp, cur_max_timestamp_); |
+ } else { |
+ if (sequencer()->GetReadableRegions(&iov, 1) != 1) { |
+ // No more data to read. |
+ break; |
+ } |
} |
if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base), |
iov.iov_len) != iov.iov_len) { |
@@ -259,6 +279,23 @@ void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id, |
if (len == 0) { |
DCHECK_NE(0u, stream_id_); |
DCHECK_NE(0u, frame_len_); |
+ if (measure_headers_hol_blocking_time_) { |
+ if (prev_max_timestamp_ > cur_max_timestamp_) { |
+ // prev_max_timestamp_ > cur_max_timestamp_ implies that |
+ // headers from lower numbered streams actually came off the |
+ // wire after headers for the current stream, hence there was |
+ // HOL blocking. |
+ QuicTime::Delta delta(prev_max_timestamp_.Subtract(cur_max_timestamp_)); |
+ DVLOG(1) << "stream " << stream_id |
+ << ": Net.QuicSession.HeadersHOLBlockedTime " |
+ << delta.ToMilliseconds(); |
+ UMA_HISTOGRAM_TIMES( |
+ "Net.QuicSession.HeadersHOLBlockedTime", |
+ base::TimeDelta::FromMicroseconds(delta.ToMicroseconds())); |
+ } |
+ prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_); |
+ cur_max_timestamp_ = QuicTime::Zero(); |
+ } |
spdy_session_->OnStreamHeadersComplete(stream_id_, fin_, frame_len_); |
// Reset state for the next frame. |
stream_id_ = kInvalidStreamId; |