Index: net/socket/tcp_client_socket_win.cc |
=================================================================== |
--- net/socket/tcp_client_socket_win.cc (revision 24072) |
+++ net/socket/tcp_client_socket_win.cc (working copy) |
@@ -6,6 +6,7 @@ |
#include "base/basictypes.h" |
#include "base/compiler_specific.h" |
+#include "base/field_trial.h" // for SlowStart trial |
#include "base/memory_debug.h" |
#include "base/string_util.h" |
#include "base/sys_info.h" |
@@ -118,6 +119,19 @@ |
scoped_refptr<IOBuffer> read_iobuffer_; |
scoped_refptr<IOBuffer> write_iobuffer_; |
+ // Throttle the read size based on our current slow start state. |
+ // Returns the throttled read size. |
+ int ThrottleReadSize(int size) { |
wtc
2009/08/25 23:58:16
This method and the related data members should be
|
+ if (!use_slow_start_throttle_) |
+ return size; |
+ |
+ if (slow_start_throttle_ < kMaxSlowStartThrottle) { |
+ size = std::min(size, slow_start_throttle_); |
+ slow_start_throttle_ *= 2; |
+ } |
+ return size; |
+ } |
+ |
private: |
class ReadDelegate : public base::ObjectWatcher::Delegate { |
public: |
@@ -156,16 +170,41 @@ |
// |write_watcher_| watches for events from Write(); |
base::ObjectWatcher write_watcher_; |
+ // When doing reads from the socket, we try to mirror TCP's slow start. |
+ // We do this because otherwise the async IO subsystem artifically delays |
+ // returning data to the application. |
+ static const int kInitialSlowStartThrottle = 1 * 1024; |
+ static const int kMaxSlowStartThrottle = 32 * kInitialSlowStartThrottle; |
+ int slow_start_throttle_; |
+ |
+ static bool use_slow_start_throttle_; |
+ static bool trial_initialized_; |
+ |
DISALLOW_COPY_AND_ASSIGN(Core); |
}; |
+bool TCPClientSocketWin::Core::use_slow_start_throttle_ = true; |
+bool TCPClientSocketWin::Core::trial_initialized_ = false; |
+ |
TCPClientSocketWin::Core::Core( |
TCPClientSocketWin* socket) |
: socket_(socket), |
ALLOW_THIS_IN_INITIALIZER_LIST(reader_(this)), |
- ALLOW_THIS_IN_INITIALIZER_LIST(writer_(this)) { |
+ ALLOW_THIS_IN_INITIALIZER_LIST(writer_(this)), |
+ slow_start_throttle_(kInitialSlowStartThrottle) { |
memset(&read_overlapped_, 0, sizeof(read_overlapped_)); |
memset(&write_overlapped_, 0, sizeof(write_overlapped_)); |
+ |
+ // Initialize the AsyncSlowStart FieldTrial. |
+ if (!trial_initialized_) { |
+ trial_initialized_ = true; |
+ scoped_refptr<FieldTrial> trial = new FieldTrial("AsyncSlowStart", 100); |
+ int my_group = trial->AppendGroup("_AsyncSlowStart", 50); |
+ trial->AppendGroup("_AsyncSlowStart_off", 50); |
+ |
+ // Only use the throttling if the FieldTrial is enabled. |
+ use_slow_start_throttle_ = trial->group() == my_group; |
+ } |
} |
TCPClientSocketWin::Core::~Core() { |
@@ -366,6 +405,8 @@ |
DCHECK(!read_callback_); |
DCHECK(!core_->read_iobuffer_); |
+ buf_len = core_->ThrottleReadSize(buf_len); |
+ |
core_->read_buffer_.len = buf_len; |
core_->read_buffer_.buf = buf->data(); |