Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(375)

Side by Side Diff: net/spdy/spdy_session.cc

Issue 13872016: [SPDY] Add histograms for flow control stalls (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/net_log_event_type_list.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/spdy/spdy_session.h" 5 #include "net/spdy/spdy_session.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 // Find our stream. 746 // Find our stream.
747 CHECK(IsStreamActive(stream_id)); 747 CHECK(IsStreamActive(stream_id));
748 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 748 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
749 CHECK_EQ(stream->stream_id(), stream_id); 749 CHECK_EQ(stream->stream_id(), stream_id);
750 750
751 if (len < 0) { 751 if (len < 0) {
752 NOTREACHED(); 752 NOTREACHED();
753 return scoped_ptr<SpdyBuffer>(); 753 return scoped_ptr<SpdyBuffer>();
754 } 754 }
755 755
756 if (len > kMaxSpdyFrameChunkSize) { 756 int effective_len = std::min(len, kMaxSpdyFrameChunkSize);
757 len = kMaxSpdyFrameChunkSize; 757
758 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); 758 bool send_stalled_by_stream =
759 (flow_control_state_ >= FLOW_CONTROL_STREAM) &&
760 (stream->send_window_size() <= 0);
761 bool send_stalled_by_session = IsSendStalled();
762
763 // NOTE: There's an enum of the same name in histograms.xml.
764 enum SpdyFrameFlowControlState {
765 SEND_NOT_STALLED,
766 SEND_STALLED_BY_STREAM,
767 SEND_STALLED_BY_SESSION,
768 SEND_STALLED_BY_STREAM_AND_SESSION,
769 };
770
771 SpdyFrameFlowControlState frame_flow_control_state = SEND_NOT_STALLED;
772 if (send_stalled_by_stream) {
773 if (send_stalled_by_session) {
774 frame_flow_control_state = SEND_STALLED_BY_STREAM_AND_SESSION;
775 } else {
776 frame_flow_control_state = SEND_STALLED_BY_STREAM;
777 }
778 } else if (send_stalled_by_session) {
779 frame_flow_control_state = SEND_STALLED_BY_SESSION;
759 } 780 }
760 781
761 // Obey send window size of the stream (and session, if applicable) 782 if (flow_control_state_ == FLOW_CONTROL_STREAM) {
762 // if flow control is enabled. 783 UMA_HISTOGRAM_ENUMERATION(
784 "Net.SpdyFrameStreamFlowControlState",
785 frame_flow_control_state,
786 SEND_STALLED_BY_STREAM + 1);
787 } else if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) {
788 UMA_HISTOGRAM_ENUMERATION(
789 "Net.SpdyFrameStreamAndSessionFlowControlState",
790 frame_flow_control_state,
791 SEND_STALLED_BY_STREAM_AND_SESSION + 1);
792 }
793
794 // Obey send window size of the stream if stream flow control is
795 // enabled.
763 if (flow_control_state_ >= FLOW_CONTROL_STREAM) { 796 if (flow_control_state_ >= FLOW_CONTROL_STREAM) {
764 int32 effective_window_size = stream->send_window_size(); 797 if (send_stalled_by_stream) {
765 if (effective_window_size <= 0) {
766 // Because we queue frames onto the session, it is possible that
767 // a stream was not flow controlled at the time it attempted the
768 // write, but when we go to fulfill the write, it is now flow
769 // controlled. This is why we need the session to mark the stream
770 // as stalled - because only the session knows for sure when the
771 // stall occurs.
772 stream->set_send_stalled_by_flow_control(true); 798 stream->set_send_stalled_by_flow_control(true);
773 net_log().AddEvent( 799 net_log().AddEvent(
774 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_ON_STREAM_SEND_WINDOW, 800 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_BY_STREAM_SEND_WINDOW,
775 NetLog::IntegerCallback("stream_id", stream_id)); 801 NetLog::IntegerCallback("stream_id", stream_id));
776 return scoped_ptr<SpdyBuffer>(); 802 return scoped_ptr<SpdyBuffer>();
777 } 803 }
778 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { 804
779 effective_window_size = 805 effective_len = std::min(effective_len, stream->send_window_size());
780 std::min(effective_window_size, session_send_window_size_); 806 }
781 if (effective_window_size <= 0) { 807
782 DCHECK(IsSendStalled()); 808 // Obey send window size of the session if session flow control is
783 stream->set_send_stalled_by_flow_control(true); 809 // enabled.
784 QueueSendStalledStream(stream); 810 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) {
785 net_log().AddEvent( 811 if (send_stalled_by_session) {
786 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_ON_SESSION_SEND_WINDOW, 812 stream->set_send_stalled_by_flow_control(true);
787 NetLog::IntegerCallback("stream_id", stream_id)); 813 QueueSendStalledStream(stream);
788 return scoped_ptr<SpdyBuffer>(); 814 net_log().AddEvent(
789 } 815 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_BY_SESSION_SEND_WINDOW,
816 NetLog::IntegerCallback("stream_id", stream_id));
817 return scoped_ptr<SpdyBuffer>();
790 } 818 }
791 819
792 int new_len = std::min(len, effective_window_size); 820 effective_len = std::min(effective_len, session_send_window_size_);
793 if (new_len < len) {
794 len = new_len;
795 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN);
796 }
797 } 821 }
798 822
823 DCHECK_GE(effective_len, 0);
824
825 // Clear FIN flag if only some of the data will be in the data
826 // frame.
827 if (effective_len < len)
828 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN);
829
799 if (net_log().IsLoggingAllEvents()) { 830 if (net_log().IsLoggingAllEvents()) {
800 net_log().AddEvent( 831 net_log().AddEvent(
801 NetLog::TYPE_SPDY_SESSION_SEND_DATA, 832 NetLog::TYPE_SPDY_SESSION_SEND_DATA,
802 base::Bind(&NetLogSpdyDataCallback, stream_id, len, 833 base::Bind(&NetLogSpdyDataCallback, stream_id, effective_len,
803 (flags & DATA_FLAG_FIN) != 0)); 834 (flags & DATA_FLAG_FIN) != 0));
804 } 835 }
805 836
806 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. 837 // Send PrefacePing for DATA_FRAMEs with nonzero payload size.
807 if (len > 0) 838 if (effective_len > 0)
808 SendPrefacePingIfNoneInFlight(); 839 SendPrefacePingIfNoneInFlight();
809 840
810 // TODO(mbelshe): reduce memory copies here. 841 // TODO(mbelshe): reduce memory copies here.
811 DCHECK(buffered_spdy_framer_.get()); 842 DCHECK(buffered_spdy_framer_.get());
812 scoped_ptr<SpdyFrame> frame( 843 scoped_ptr<SpdyFrame> frame(
813 buffered_spdy_framer_->CreateDataFrame( 844 buffered_spdy_framer_->CreateDataFrame(
814 stream_id, data->data(), static_cast<uint32>(len), flags)); 845 stream_id, data->data(),
846 static_cast<uint32>(effective_len), flags));
815 847
816 scoped_ptr<SpdyBuffer> data_buffer(new SpdyBuffer(frame.Pass())); 848 scoped_ptr<SpdyBuffer> data_buffer(new SpdyBuffer(frame.Pass()));
817 849
818 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { 850 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) {
819 DecreaseSendWindowSize(static_cast<int32>(len)); 851 DecreaseSendWindowSize(static_cast<int32>(effective_len));
820 data_buffer->AddConsumeCallback( 852 data_buffer->AddConsumeCallback(
821 base::Bind(&SpdySession::OnWriteBufferConsumed, 853 base::Bind(&SpdySession::OnWriteBufferConsumed,
822 weak_factory_.GetWeakPtr(), 854 weak_factory_.GetWeakPtr(),
823 static_cast<size_t>(len))); 855 static_cast<size_t>(effective_len)));
824 } 856 }
825 857
826 return data_buffer.Pass(); 858 return data_buffer.Pass();
827 } 859 }
828 860
829 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) { 861 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) {
830 DCHECK_NE(0u, stream_id); 862 DCHECK_NE(0u, stream_id);
831 // TODO(mbelshe): We should send a RST_STREAM control frame here 863 // TODO(mbelshe): We should send a RST_STREAM control frame here
832 // so that the server can cancel a large send. 864 // so that the server can cancel a large send.
833 865
(...skipping 1533 matching lines...) Expand 10 before | Expand all | Expand 10 after
2367 if (!queue->empty()) { 2399 if (!queue->empty()) {
2368 SpdyStreamId stream_id = queue->front(); 2400 SpdyStreamId stream_id = queue->front();
2369 queue->pop_front(); 2401 queue->pop_front();
2370 return stream_id; 2402 return stream_id;
2371 } 2403 }
2372 } 2404 }
2373 return 0; 2405 return 0;
2374 } 2406 }
2375 2407
2376 } // namespace net 2408 } // namespace net
OLDNEW
« no previous file with comments | « net/base/net_log_event_type_list.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698