OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/quic_headers_stream.h" | 5 #include "net/quic/quic_headers_stream.h" |
6 | 6 |
| 7 #include "base/metrics/histogram_macros.h" |
7 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 9 #include "net/quic/quic_flags.h" |
| 10 #include "net/quic/quic_headers_stream.h" |
8 #include "net/quic/quic_spdy_session.h" | 11 #include "net/quic/quic_spdy_session.h" |
| 12 #include "net/quic/quic_time.h" |
9 | 13 |
10 using base::StringPiece; | 14 using base::StringPiece; |
| 15 using net::HTTP2; |
| 16 using net::SpdyFrameType; |
11 using std::string; | 17 using std::string; |
12 | 18 |
13 namespace net { | 19 namespace net { |
14 | 20 |
15 namespace { | 21 namespace { |
16 | 22 |
17 const QuicStreamId kInvalidStreamId = 0; | 23 const QuicStreamId kInvalidStreamId = 0; |
18 | 24 |
19 } // namespace | 25 } // namespace |
20 | 26 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 | 173 |
168 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor); | 174 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor); |
169 }; | 175 }; |
170 | 176 |
171 QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session) | 177 QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session) |
172 : ReliableQuicStream(kHeadersStreamId, session), | 178 : ReliableQuicStream(kHeadersStreamId, session), |
173 spdy_session_(session), | 179 spdy_session_(session), |
174 stream_id_(kInvalidStreamId), | 180 stream_id_(kInvalidStreamId), |
175 fin_(false), | 181 fin_(false), |
176 frame_len_(0), | 182 frame_len_(0), |
| 183 measure_headers_hol_blocking_time_( |
| 184 FLAGS_quic_measure_headers_hol_blocking_time), |
| 185 cur_max_timestamp_(QuicTime::Zero()), |
| 186 prev_max_timestamp_(QuicTime::Zero()), |
177 spdy_framer_(HTTP2), | 187 spdy_framer_(HTTP2), |
178 spdy_framer_visitor_(new SpdyFramerVisitor(this)) { | 188 spdy_framer_visitor_(new SpdyFramerVisitor(this)) { |
179 spdy_framer_.set_visitor(spdy_framer_visitor_.get()); | 189 spdy_framer_.set_visitor(spdy_framer_visitor_.get()); |
180 spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get()); | 190 spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get()); |
181 // The headers stream is exempt from connection level flow control. | 191 // The headers stream is exempt from connection level flow control. |
182 DisableConnectionFlowControlForThisStream(); | 192 DisableConnectionFlowControlForThisStream(); |
183 } | 193 } |
184 | 194 |
185 QuicHeadersStream::~QuicHeadersStream() {} | 195 QuicHeadersStream::~QuicHeadersStream() {} |
186 | 196 |
(...skipping 13 matching lines...) Expand all Loading... |
200 scoped_ptr<SpdySerializedFrame> frame( | 210 scoped_ptr<SpdySerializedFrame> frame( |
201 spdy_framer_.SerializeFrame(headers_frame)); | 211 spdy_framer_.SerializeFrame(headers_frame)); |
202 WriteOrBufferData(StringPiece(frame->data(), frame->size()), false, | 212 WriteOrBufferData(StringPiece(frame->data(), frame->size()), false, |
203 ack_notifier_delegate); | 213 ack_notifier_delegate); |
204 return frame->size(); | 214 return frame->size(); |
205 } | 215 } |
206 | 216 |
207 void QuicHeadersStream::OnDataAvailable() { | 217 void QuicHeadersStream::OnDataAvailable() { |
208 char buffer[1024]; | 218 char buffer[1024]; |
209 struct iovec iov; | 219 struct iovec iov; |
| 220 QuicTime timestamp(QuicTime::Zero()); |
210 while (true) { | 221 while (true) { |
211 iov.iov_base = buffer; | 222 iov.iov_base = buffer; |
212 iov.iov_len = arraysize(buffer); | 223 iov.iov_len = arraysize(buffer); |
213 if (sequencer()->GetReadableRegions(&iov, 1) != 1) { | 224 if (measure_headers_hol_blocking_time_) { |
214 // No more data to read. | 225 if (!sequencer()->GetReadableRegion(&iov, ×tamp)) { |
215 break; | 226 // No more data to read. |
| 227 break; |
| 228 } |
| 229 DCHECK(timestamp.IsInitialized()); |
| 230 cur_max_timestamp_ = QuicTime::Max(timestamp, cur_max_timestamp_); |
| 231 } else { |
| 232 if (sequencer()->GetReadableRegions(&iov, 1) != 1) { |
| 233 // No more data to read. |
| 234 break; |
| 235 } |
216 } | 236 } |
217 if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base), | 237 if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base), |
218 iov.iov_len) != iov.iov_len) { | 238 iov.iov_len) != iov.iov_len) { |
219 // Error processing data. | 239 // Error processing data. |
220 return; | 240 return; |
221 } | 241 } |
222 sequencer()->MarkConsumed(iov.iov_len); | 242 sequencer()->MarkConsumed(iov.iov_len); |
223 } | 243 } |
224 } | 244 } |
225 | 245 |
(...skipping 26 matching lines...) Expand all Loading... |
252 fin_ = fin; | 272 fin_ = fin; |
253 } | 273 } |
254 | 274 |
255 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id, | 275 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id, |
256 const char* header_data, | 276 const char* header_data, |
257 size_t len) { | 277 size_t len) { |
258 DCHECK_EQ(stream_id_, stream_id); | 278 DCHECK_EQ(stream_id_, stream_id); |
259 if (len == 0) { | 279 if (len == 0) { |
260 DCHECK_NE(0u, stream_id_); | 280 DCHECK_NE(0u, stream_id_); |
261 DCHECK_NE(0u, frame_len_); | 281 DCHECK_NE(0u, frame_len_); |
| 282 if (measure_headers_hol_blocking_time_) { |
| 283 if (prev_max_timestamp_ > cur_max_timestamp_) { |
| 284 // prev_max_timestamp_ > cur_max_timestamp_ implies that |
| 285 // headers from lower numbered streams actually came off the |
| 286 // wire after headers for the current stream, hence there was |
| 287 // HOL blocking. |
| 288 QuicTime::Delta delta(prev_max_timestamp_.Subtract(cur_max_timestamp_)); |
| 289 DVLOG(1) << "stream " << stream_id |
| 290 << ": Net.QuicSession.HeadersHOLBlockedTime " |
| 291 << delta.ToMilliseconds(); |
| 292 UMA_HISTOGRAM_TIMES( |
| 293 "Net.QuicSession.HeadersHOLBlockedTime", |
| 294 base::TimeDelta::FromMicroseconds(delta.ToMicroseconds())); |
| 295 } |
| 296 prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_); |
| 297 cur_max_timestamp_ = QuicTime::Zero(); |
| 298 } |
262 spdy_session_->OnStreamHeadersComplete(stream_id_, fin_, frame_len_); | 299 spdy_session_->OnStreamHeadersComplete(stream_id_, fin_, frame_len_); |
263 // Reset state for the next frame. | 300 // Reset state for the next frame. |
264 stream_id_ = kInvalidStreamId; | 301 stream_id_ = kInvalidStreamId; |
265 fin_ = false; | 302 fin_ = false; |
266 frame_len_ = 0; | 303 frame_len_ = 0; |
267 } else { | 304 } else { |
268 spdy_session_->OnStreamHeaders(stream_id_, StringPiece(header_data, len)); | 305 spdy_session_->OnStreamHeaders(stream_id_, StringPiece(header_data, len)); |
269 } | 306 } |
270 } | 307 } |
271 | 308 |
272 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) { | 309 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) { |
273 frame_len_ += frame_len; | 310 frame_len_ += frame_len; |
274 } | 311 } |
275 | 312 |
276 bool QuicHeadersStream::IsConnected() { | 313 bool QuicHeadersStream::IsConnected() { |
277 return session()->connection()->connected(); | 314 return session()->connection()->connected(); |
278 } | 315 } |
279 | 316 |
280 } // namespace net | 317 } // namespace net |
OLD | NEW |