Skip to content

Commit

Permalink
Warmth of a connection (cwnd) is estimated by the amount of data writ…
Browse files Browse the repository at this point in the history
…ten to the socket.

Choosing the warmest connection would mean faster resource load times. 

idle time is the time a socket has remained idle (no http requests being served on it). 
Probability of server resetting a connection increases with idle time duration. 

Using a cost function that takes into account bytes transferred and idle time to pick best connection to schedule http requests on.

CODEREVIEW done in http://codereview.chromium.org/6990036/

Contributed by gagansingh@google.com

Review URL: http://codereview.chromium.org/7189055

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90373 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
gagansingh@google.com committed Jun 24, 2011
1 parent 591805d commit 0ca76cb
Show file tree
Hide file tree
Showing 54 changed files with 679 additions and 11 deletions.
54 changes: 54 additions & 0 deletions chrome/browser/browser_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
#include "net/base/cookie_monster.h"
#include "net/base/net_module.h"
#include "net/base/network_change_notifier.h"
#include "net/http/http_basic_stream.h"
#include "net/http/http_network_layer.h"
#include "net/http/http_stream_factory.h"
#include "net/socket/client_socket_pool_base.h"
Expand Down Expand Up @@ -208,6 +209,18 @@
#include "views/touchui/touch_factory.h"
#endif

namespace {
void SetSocketReusePolicy(int warmest_socket_trial_group,
const int socket_policy[],
int num_groups) {
const int* result = std::find(socket_policy, socket_policy + num_groups,
warmest_socket_trial_group);
DCHECK_NE(result, socket_policy + num_groups)
<< "Not a valid socket reuse policy group";
net::SetSocketReusePolicy(result - socket_policy);
}
}

namespace net {
class NetLog;
} // namespace net
Expand Down Expand Up @@ -474,6 +487,46 @@ void BrowserMainParts::SpdyFieldTrial() {
}
}

// If --socket-reuse-policy is not specified, run an A/B test for choosing the
// warmest socket.
void BrowserMainParts::WarmConnectionFieldTrial() {
const CommandLine& command_line = parsed_command_line();
if (command_line.HasSwitch(switches::kSocketReusePolicy)) {
std::string socket_reuse_policy_str = command_line.GetSwitchValueASCII(
switches::kSocketReusePolicy);
int policy = -1;
base::StringToInt(socket_reuse_policy_str, &policy);

const int policy_list[] = { 0, 1, 2 };
VLOG(1) << "Setting socket_reuse_policy = " << policy;
SetSocketReusePolicy(policy, policy_list, arraysize(policy_list));
return;
}

const base::FieldTrial::Probability kWarmSocketDivisor = 100;
const base::FieldTrial::Probability kWarmSocketProbability = 33;

// After January 30, 2013 builds, it will always be in default group.
scoped_refptr<base::FieldTrial> warmest_socket_trial(
new base::FieldTrial(
"WarmSocketImpact", kWarmSocketDivisor, "last_accessed_socket",
2013, 1, 30));

// Default value is USE_LAST_ACCESSED_SOCKET.
const int last_accessed_socket = warmest_socket_trial->kDefaultGroupNumber;
const int warmest_socket = warmest_socket_trial->AppendGroup(
"warmest_socket", kWarmSocketProbability);
const int warm_socket = warmest_socket_trial->AppendGroup(
"warm_socket", kWarmSocketProbability);

const int warmest_socket_trial_group = warmest_socket_trial->group();

const int policy_list[] = { warmest_socket, warm_socket,
last_accessed_socket };
SetSocketReusePolicy(warmest_socket_trial_group, policy_list,
arraysize(policy_list));
}

// If neither --enable-connect-backup-jobs or --disable-connect-backup-jobs is
// specified, run an A/B test for automatically establishing backup TCP
// connections when a certain timeout value is exceeded.
Expand Down Expand Up @@ -593,6 +646,7 @@ void BrowserMainParts::SetupFieldTrials(bool metrics_recording_enabled) {
prerender::ConfigurePrefetchAndPrerender(parsed_command_line());
SpdyFieldTrial();
ConnectBackupJobsFieldTrial();
WarmConnectionFieldTrial();
}

// -----------------------------------------------------------------------------
Expand Down
7 changes: 7 additions & 0 deletions chrome/browser/browser_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#pragma once

#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/tracked_objects.h"
Expand Down Expand Up @@ -129,6 +130,9 @@ class BrowserMainParts {
// specified timeout value is reached.
void ConnectBackupJobsFieldTrial();

// A/B test for warmest socket vs. most recently used socket.
void WarmConnectionFieldTrial();

// Used to initialize NSPR where appropriate.
virtual void InitializeSSL() = 0;

Expand Down Expand Up @@ -171,6 +175,9 @@ class BrowserMainParts {
// Initialized in SetupMetricsAndFieldTrials.
scoped_refptr<FieldTrialSynchronizer> field_trial_synchronizer_;

FRIEND_TEST(BrowserMainTest, WarmConnectionFieldTrial_WarmestSocket);
FRIEND_TEST(BrowserMainTest, WarmConnectionFieldTrial_Random);
FRIEND_TEST(BrowserMainTest, WarmConnectionFieldTrial_Invalid);
DISALLOW_COPY_AND_ASSIGN(BrowserMainParts);
};

Expand Down
68 changes: 68 additions & 0 deletions chrome/browser/browser_main_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/browser_main.h"

#include <string>
#include <vector>
#include "base/command_line.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/testing_pref_service.h"
#include "content/common/main_function_params.h"
#include "content/common/sandbox_init_wrapper.h"
#include "net/socket/client_socket_pool_base.h"
#include "testing/gtest/include/gtest/gtest.h"

class BrowserMainTest : public testing::Test {
public:
BrowserMainTest() : command_line_(CommandLine::NO_PROGRAM) {}
protected:
virtual void SetUp() {
sandbox_init_wrapper_.reset(new SandboxInitWrapper());
}

scoped_ptr<SandboxInitWrapper> sandbox_init_wrapper_;
TestingPrefService pref_service_;
CommandLine command_line_;
};

TEST_F(BrowserMainTest, WarmConnectionFieldTrial_WarmestSocket) {
command_line_.AppendSwitchASCII(switches::kSocketReusePolicy, "0");

scoped_ptr<MainFunctionParams> params(
new MainFunctionParams(command_line_, *sandbox_init_wrapper_, NULL));
scoped_ptr<BrowserMainParts> bw(BrowserMainParts::CreateBrowserMainParts(
*params));

bw->WarmConnectionFieldTrial();

EXPECT_EQ(0, net::GetSocketReusePolicy());
}

TEST_F(BrowserMainTest, WarmConnectionFieldTrial_Random) {
scoped_ptr<MainFunctionParams> params(
new MainFunctionParams(command_line_, *sandbox_init_wrapper_, NULL));
scoped_ptr<BrowserMainParts> bw(BrowserMainParts::CreateBrowserMainParts(
*params));

const int kNumRuns = 1000;
for (int i = 0; i < kNumRuns; i++) {
bw->WarmConnectionFieldTrial();
int val = net::GetSocketReusePolicy();
EXPECT_LE(val, 2);
EXPECT_GE(val, 0);
}
}

TEST_F(BrowserMainTest, WarmConnectionFieldTrial_Invalid) {
command_line_.AppendSwitchASCII(switches::kSocketReusePolicy, "100");

scoped_ptr<MainFunctionParams> params(
new MainFunctionParams(command_line_, *sandbox_init_wrapper_, NULL));
scoped_ptr<BrowserMainParts> bw(BrowserMainParts::CreateBrowserMainParts(
*params));

EXPECT_DEBUG_DEATH(bw->WarmConnectionFieldTrial(),
"Not a valid socket reuse policy group");
}
1 change: 1 addition & 0 deletions chrome/chrome_tests.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,7 @@
'browser/bookmarks/bookmark_utils_unittest.cc',
'browser/browser_about_handler_unittest.cc',
'browser/browser_commands_unittest.cc',
'browser/browser_main_unittest.cc',
'browser/browser_url_handler_unittest.cc',
'browser/browsing_data_appcache_helper_unittest.cc',
'browser/browsing_data_database_helper_unittest.cc',
Expand Down
4 changes: 4 additions & 0 deletions chrome/common/chrome_switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,10 @@ const char kSilentDumpOnDCHECK[] = "silent-dump-on-dcheck";
// Replaces the buffered data source for <audio> and <video> with a simplified
// resource loader that downloads the entire resource into memory.

// Choose the socket reuse policy specified. The value should be of type
// enum ClientSocketReusePolicy.
const char kSocketReusePolicy[] = "socket-reuse-policy";

// Start the browser maximized, regardless of any previous settings.
const char kStartMaximized[] = "start-maximized";

Expand Down
1 change: 1 addition & 0 deletions chrome/common/chrome_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ extern const char kShowCompositedLayerTree[];
extern const char kShowFPSCounter[];
extern const char kShowIcons[];
extern const char kSilentDumpOnDCHECK[];
extern const char kSocketReusePolicy[];
extern const char kStartMaximized[];
extern const char kSyncAllowInsecureXmppConnection[];
extern const char kSyncInvalidateXmppLogin[];
Expand Down
10 changes: 10 additions & 0 deletions content/browser/renderer_host/p2p/socket_host_test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class FakeSocket : public net::StreamSocket {
virtual void SetOmniboxSpeculation() OVERRIDE;
virtual bool WasEverUsed() const OVERRIDE;
virtual bool UsingTCPFastOpen() const OVERRIDE;
virtual int64 NumBytesRead() const OVERRIDE;
virtual base::TimeDelta GetConnectTimeMicros() const OVERRIDE;

private:
bool read_pending_;
Expand Down Expand Up @@ -209,6 +211,14 @@ bool FakeSocket::UsingTCPFastOpen() const {
return false;
}

int64 FakeSocket::NumBytesRead() const {
return -1;
}

base::TimeDelta FakeSocket::GetConnectTimeMicros() const {
return base::TimeDelta::FromMicroseconds(-1);
}

void CreateRandomPacket(std::vector<char>* packet) {
size_t size = kStunHeaderSize + rand() % 1000;
packet->resize(size);
Expand Down
10 changes: 10 additions & 0 deletions jingle/glue/pseudotcp_adapter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -463,4 +463,14 @@ bool PseudoTcpAdapter::UsingTCPFastOpen() const {
return false;
}

int64 PseudoTcpAdapter::NumBytesRead() const {
DCHECK(CalledOnValidThread());
return -1;
}

base::TimeDelta PseudoTcpAdapter::GetConnectTimeMicros() const {
DCHECK(CalledOnValidThread());
return base::TimeDelta::FromMicroseconds(-1);
}

} // namespace jingle_glue
2 changes: 2 additions & 0 deletions jingle/glue/pseudotcp_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class PseudoTcpAdapter : public net::StreamSocket, base::NonThreadSafe {
virtual void SetOmniboxSpeculation() OVERRIDE;
virtual bool WasEverUsed() const OVERRIDE;
virtual bool UsingTCPFastOpen() const OVERRIDE;
virtual int64 NumBytesRead() const OVERRIDE;
virtual base::TimeDelta GetConnectTimeMicros() const OVERRIDE;

private:
class Core;
Expand Down
10 changes: 9 additions & 1 deletion jingle/notifier/base/fake_ssl_client_socket.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Expand Down Expand Up @@ -336,4 +336,12 @@ bool FakeSSLClientSocket::UsingTCPFastOpen() const {
return transport_socket_->UsingTCPFastOpen();
}

int64 FakeSSLClientSocket::NumBytesRead() const {
return transport_socket_->NumBytesRead();
}

base::TimeDelta FakeSSLClientSocket::GetConnectTimeMicros() const {
return transport_socket_->GetConnectTimeMicros();
}

} // namespace notifier
2 changes: 2 additions & 0 deletions jingle/notifier/base/fake_ssl_client_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class FakeSSLClientSocket : public net::StreamSocket {
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
virtual bool UsingTCPFastOpen() const;
virtual int64 NumBytesRead() const;
virtual base::TimeDelta GetConnectTimeMicros() const;

private:
enum HandshakeState {
Expand Down
2 changes: 2 additions & 0 deletions jingle/notifier/base/fake_ssl_client_socket_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class MockClientSocket : public net::StreamSocket {
MOCK_METHOD0(SetOmniboxSpeculation, void());
MOCK_CONST_METHOD0(WasEverUsed, bool());
MOCK_CONST_METHOD0(UsingTCPFastOpen, bool());
MOCK_CONST_METHOD0(NumBytesRead, int64());
MOCK_CONST_METHOD0(GetConnectTimeMicros, base::TimeDelta());
};

// Break up |data| into a bunch of chunked MockReads/Writes and push
Expand Down
14 changes: 14 additions & 0 deletions jingle/notifier/base/proxy_resolving_client_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,20 @@ bool ProxyResolvingClientSocket::UsingTCPFastOpen() const {
return false;
}

int64 ProxyResolvingClientSocket::NumBytesRead() const {
if (transport_.get() && transport_->socket())
return transport_->socket()->NumBytesRead();
NOTREACHED();
return -1;
}

base::TimeDelta ProxyResolvingClientSocket::GetConnectTimeMicros() const {
if (transport_.get() && transport_->socket())
return transport_->socket()->GetConnectTimeMicros();
NOTREACHED();
return base::TimeDelta::FromMicroseconds(-1);
}

void ProxyResolvingClientSocket::CloseTransportSocket() {
if (transport_.get() && transport_->socket())
transport_->socket()->Disconnect();
Expand Down
2 changes: 2 additions & 0 deletions jingle/notifier/base/proxy_resolving_client_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class ProxyResolvingClientSocket : public net::StreamSocket {
virtual void SetOmniboxSpeculation() OVERRIDE;
virtual bool WasEverUsed() const OVERRIDE;
virtual bool UsingTCPFastOpen() const OVERRIDE;
virtual int64 NumBytesRead() const OVERRIDE;
virtual base::TimeDelta GetConnectTimeMicros() const OVERRIDE;

private:
// Proxy resolution and connection functions.
Expand Down
8 changes: 8 additions & 0 deletions net/curvecp/curvecp_client_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ bool CurveCPClientSocket::UsingTCPFastOpen() const {
return false;
}

int64 CurveCPClientSocket::NumBytesRead() const {
return -1;
}

base::TimeDelta CurveCPClientSocket::GetConnectTimeMicros() const {
return base::TimeDelta::FromMicroseconds(-1);
}

int CurveCPClientSocket::Read(IOBuffer* buf,
int buf_len,
CompletionCallback* callback) {
Expand Down
2 changes: 2 additions & 0 deletions net/curvecp/curvecp_client_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class CurveCPClientSocket : public StreamSocket {
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
virtual bool UsingTCPFastOpen() const;
virtual int64 NumBytesRead() const;
virtual base::TimeDelta GetConnectTimeMicros() const;

// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
Expand Down
Loading

0 comments on commit 0ca76cb

Please sign in to comment.