summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorsimonjam@chromium.org <simonjam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-07 01:21:26 +0000
committersimonjam@chromium.org <simonjam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-07 01:21:26 +0000
commitacc32d123e055aa4c2c11538c8405164ef9c9998 (patch)
tree544fb0d50a185acde818a24e8761d37dabc28935 /net
parent12d264b91951777c613f7ca8346cd3e3545f0ca0 (diff)
downloadchromium_src-acc32d123e055aa4c2c11538c8405164ef9c9998.zip
chromium_src-acc32d123e055aa4c2c11538c8405164ef9c9998.tar.gz
chromium_src-acc32d123e055aa4c2c11538c8405164ef9c9998.tar.bz2
Save pipelining capabilities for the most used hosts between sessions.
BUG=None TEST=unit_tests Review URL: http://codereview.chromium.org/8770035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113315 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/http/http_pipelined_host.h18
-rw-r--r--net/http/http_pipelined_host_capability.h24
-rw-r--r--net/http/http_pipelined_host_impl.cc28
-rw-r--r--net/http/http_pipelined_host_impl.h5
-rw-r--r--net/http/http_pipelined_host_impl_unittest.cc22
-rw-r--r--net/http/http_pipelined_host_pool.cc42
-rw-r--r--net/http/http_pipelined_host_pool.h14
-rw-r--r--net/http/http_pipelined_host_pool_unittest.cc43
-rw-r--r--net/http/http_server_properties.h14
-rw-r--r--net/http/http_server_properties_impl.cc63
-rw-r--r--net/http/http_server_properties_impl.h27
-rw-r--r--net/http/http_stream_factory_impl.cc3
-rw-r--r--net/net.gyp1
13 files changed, 211 insertions, 93 deletions
diff --git a/net/http/http_pipelined_host.h b/net/http/http_pipelined_host.h
index c368313..711b98d 100644
--- a/net/http/http_pipelined_host.h
+++ b/net/http/http_pipelined_host.h
@@ -6,14 +6,15 @@
#define NET_HTTP_HTTP_PIPELINED_HOST_H_
#pragma once
-#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
#include "net/http/http_pipelined_connection.h"
+#include "net/http/http_pipelined_host_capability.h"
namespace net {
class BoundNetLog;
class ClientSocketHandle;
+class HostPortPair;
class HttpPipelinedStream;
class ProxyInfo;
struct SSLConfig;
@@ -23,14 +24,6 @@ struct SSLConfig;
// assigns requests to the least loaded pipelined connection.
class NET_EXPORT_PRIVATE HttpPipelinedHost {
public:
- enum Capability {
- UNKNOWN,
- INCAPABLE,
- CAPABLE,
- PROBABLY_CAPABLE, // We are using pipelining, but haven't processed enough
- // requests to record this host as known to be capable.
- };
-
class Delegate {
public:
// Called when a pipelined host has no outstanding requests on any of its
@@ -42,8 +35,9 @@ class NET_EXPORT_PRIVATE HttpPipelinedHost {
virtual void OnHostHasAdditionalCapacity(HttpPipelinedHost* host) = 0;
// Called when a host determines if pipelining can be used.
- virtual void OnHostDeterminedCapability(HttpPipelinedHost* host,
- Capability capability) = 0;
+ virtual void OnHostDeterminedCapability(
+ HttpPipelinedHost* host,
+ HttpPipelinedHostCapability capability) = 0;
};
class Factory {
@@ -54,7 +48,7 @@ class NET_EXPORT_PRIVATE HttpPipelinedHost {
virtual HttpPipelinedHost* CreateNewHost(
Delegate* delegate, const HostPortPair& origin,
HttpPipelinedConnection::Factory* factory,
- Capability capability) = 0;
+ HttpPipelinedHostCapability capability) = 0;
};
virtual ~HttpPipelinedHost() {}
diff --git a/net/http/http_pipelined_host_capability.h b/net/http/http_pipelined_host_capability.h
new file mode 100644
index 0000000..2c44cd3
--- /dev/null
+++ b/net/http/http_pipelined_host_capability.h
@@ -0,0 +1,24 @@
+// 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.
+
+#ifndef NET_HTTP_HTTP_PIPELINED_HOST_CAPABILITY_H_
+#define NET_HTTP_HTTP_PIPELINED_HOST_CAPABILITY_H_
+#pragma once
+
+namespace net {
+
+// These values are serialized in Preferences. Do not change these values and
+// only add new ones at the end.
+enum HttpPipelinedHostCapability {
+ PIPELINE_UNKNOWN = 0,
+ PIPELINE_INCAPABLE = 1,
+ PIPELINE_CAPABLE = 2,
+ PIPELINE_PROBABLY_CAPABLE = 3, // We are using pipelining, but haven't
+ // processed enough requests to record this
+ // host as known to be capable.
+};
+
+} // namespace net
+
+#endif // NET_HTTP_HTTP_PIPELINED_HOST_CAPABILITY_H_
diff --git a/net/http/http_pipelined_host_impl.cc b/net/http/http_pipelined_host_impl.cc
index d554fe1..6ca759e 100644
--- a/net/http/http_pipelined_host_impl.cc
+++ b/net/http/http_pipelined_host_impl.cc
@@ -34,7 +34,7 @@ HttpPipelinedHostImpl::HttpPipelinedHostImpl(
HttpPipelinedHost::Delegate* delegate,
const HostPortPair& origin,
HttpPipelinedConnection::Factory* factory,
- Capability capability)
+ HttpPipelinedHostCapability capability)
: delegate_(delegate),
origin_(origin),
factory_(factory),
@@ -54,7 +54,7 @@ HttpPipelinedStream* HttpPipelinedHostImpl::CreateStreamOnNewPipeline(
const ProxyInfo& used_proxy_info,
const BoundNetLog& net_log,
bool was_npn_negotiated) {
- if (capability_ == INCAPABLE) {
+ if (capability_ == PIPELINE_INCAPABLE) {
return NULL;
}
HttpPipelinedConnection* pipeline = factory_->CreateNewPipeline(
@@ -124,21 +124,21 @@ void HttpPipelinedHostImpl::OnPipelineFeedback(
switch (feedback) {
case HttpPipelinedConnection::OK:
++pipelines_[pipeline].num_successes;
- if (capability_ == UNKNOWN) {
- capability_ = PROBABLY_CAPABLE;
+ if (capability_ == PIPELINE_UNKNOWN) {
+ capability_ = PIPELINE_PROBABLY_CAPABLE;
NotifyAllPipelinesHaveCapacity();
- } else if (capability_ == PROBABLY_CAPABLE &&
+ } else if (capability_ == PIPELINE_PROBABLY_CAPABLE &&
pipelines_[pipeline].num_successes >=
kNumKnownSuccessesThreshold) {
- capability_ = CAPABLE;
- delegate_->OnHostDeterminedCapability(this, CAPABLE);
+ capability_ = PIPELINE_CAPABLE;
+ delegate_->OnHostDeterminedCapability(this, PIPELINE_CAPABLE);
}
break;
case HttpPipelinedConnection::PIPELINE_SOCKET_ERROR:
case HttpPipelinedConnection::OLD_HTTP_VERSION:
- capability_ = INCAPABLE;
- delegate_->OnHostDeterminedCapability(this, INCAPABLE);
+ capability_ = PIPELINE_INCAPABLE;
+ delegate_->OnHostDeterminedCapability(this, PIPELINE_INCAPABLE);
break;
case HttpPipelinedConnection::MUST_CLOSE_CONNECTION:
@@ -149,15 +149,15 @@ void HttpPipelinedHostImpl::OnPipelineFeedback(
int HttpPipelinedHostImpl::GetPipelineCapacity() const {
int capacity = 0;
switch (capability_) {
- case CAPABLE:
- case PROBABLY_CAPABLE:
+ case PIPELINE_CAPABLE:
+ case PIPELINE_PROBABLY_CAPABLE:
capacity = max_pipeline_depth();
break;
- case INCAPABLE:
+ case PIPELINE_INCAPABLE:
CHECK(false);
- case UNKNOWN:
+ case PIPELINE_UNKNOWN:
capacity = 1;
break;
@@ -169,7 +169,7 @@ int HttpPipelinedHostImpl::GetPipelineCapacity() const {
bool HttpPipelinedHostImpl::CanPipelineAcceptRequests(
HttpPipelinedConnection* pipeline) const {
- return capability_ != INCAPABLE &&
+ return capability_ != PIPELINE_INCAPABLE &&
pipeline->usable() &&
pipeline->active() &&
pipeline->depth() < GetPipelineCapacity();
diff --git a/net/http/http_pipelined_host_impl.h b/net/http/http_pipelined_host_impl.h
index c1d745c..1286d69 100644
--- a/net/http/http_pipelined_host_impl.h
+++ b/net/http/http_pipelined_host_impl.h
@@ -15,6 +15,7 @@
#include "net/base/net_export.h"
#include "net/http/http_pipelined_connection.h"
#include "net/http/http_pipelined_host.h"
+#include "net/http/http_pipelined_host_capability.h"
namespace net {
@@ -34,7 +35,7 @@ class NET_EXPORT_PRIVATE HttpPipelinedHostImpl
HttpPipelinedHostImpl(HttpPipelinedHost::Delegate* delegate,
const HostPortPair& origin,
HttpPipelinedConnection::Factory* factory,
- Capability capability);
+ HttpPipelinedHostCapability capability);
virtual ~HttpPipelinedHostImpl();
// HttpPipelinedHost interface
@@ -98,7 +99,7 @@ class NET_EXPORT_PRIVATE HttpPipelinedHostImpl
const HostPortPair origin_;
PipelineInfoMap pipelines_;
scoped_ptr<HttpPipelinedConnection::Factory> factory_;
- Capability capability_;
+ HttpPipelinedHostCapability capability_;
DISALLOW_COPY_AND_ASSIGN(HttpPipelinedHostImpl);
};
diff --git a/net/http/http_pipelined_host_impl_unittest.cc b/net/http/http_pipelined_host_impl_unittest.cc
index ed7d722..3eace82 100644
--- a/net/http/http_pipelined_host_impl_unittest.cc
+++ b/net/http/http_pipelined_host_impl_unittest.cc
@@ -32,7 +32,7 @@ class MockHostDelegate : public HttpPipelinedHost::Delegate {
MOCK_METHOD1(OnHostHasAdditionalCapacity, void(HttpPipelinedHost* host));
MOCK_METHOD2(OnHostDeterminedCapability,
void(HttpPipelinedHost* host,
- HttpPipelinedHost::Capability capability));
+ HttpPipelinedHostCapability capability));
};
class MockPipelineFactory : public HttpPipelinedConnection::Factory {
@@ -83,10 +83,10 @@ class HttpPipelinedHostImplTest : public testing::Test {
: origin_("host", 123),
factory_(new MockPipelineFactory), // Owned by host_.
host_(new HttpPipelinedHostImpl(&delegate_, origin_, factory_,
- HttpPipelinedHost::CAPABLE)) {
+ PIPELINE_CAPABLE)) {
}
- void SetCapability(HttpPipelinedHost::Capability capability) {
+ void SetCapability(HttpPipelinedHostCapability capability) {
factory_ = new MockPipelineFactory;
host_.reset(new HttpPipelinedHostImpl(
&delegate_, origin_, factory_, capability));
@@ -200,7 +200,7 @@ TEST_F(HttpPipelinedHostImplTest, PicksLeastLoadedPipeline) {
}
TEST_F(HttpPipelinedHostImplTest, OpensUpOnPipelineSuccess) {
- SetCapability(HttpPipelinedHost::UNKNOWN);
+ SetCapability(PIPELINE_UNKNOWN);
MockPipeline* pipeline = AddTestPipeline(1, true, true);
EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
@@ -219,7 +219,7 @@ TEST_F(HttpPipelinedHostImplTest, OpensUpOnPipelineSuccess) {
}
TEST_F(HttpPipelinedHostImplTest, OpensAllPipelinesOnPipelineSuccess) {
- SetCapability(HttpPipelinedHost::UNKNOWN);
+ SetCapability(PIPELINE_UNKNOWN);
MockPipeline* pipeline1 = AddTestPipeline(1, false, true);
MockPipeline* pipeline2 = AddTestPipeline(1, true, true);
@@ -240,15 +240,14 @@ TEST_F(HttpPipelinedHostImplTest, OpensAllPipelinesOnPipelineSuccess) {
}
TEST_F(HttpPipelinedHostImplTest, ShutsDownOnOldVersion) {
- SetCapability(HttpPipelinedHost::UNKNOWN);
+ SetCapability(PIPELINE_UNKNOWN);
MockPipeline* pipeline = AddTestPipeline(1, true, true);
EXPECT_EQ(NULL, host_->CreateStreamOnExistingPipeline());
EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
.Times(0);
EXPECT_CALL(delegate_,
- OnHostDeterminedCapability(host_.get(),
- HttpPipelinedHost::INCAPABLE))
+ OnHostDeterminedCapability(host_.get(), PIPELINE_INCAPABLE))
.Times(1);
host_->OnPipelineFeedback(pipeline,
HttpPipelinedConnection::OLD_HTTP_VERSION);
@@ -259,7 +258,7 @@ TEST_F(HttpPipelinedHostImplTest, ShutsDownOnOldVersion) {
}
TEST_F(HttpPipelinedHostImplTest, ConnectionCloseHasNoEffect) {
- SetCapability(HttpPipelinedHost::UNKNOWN);
+ SetCapability(PIPELINE_UNKNOWN);
MockPipeline* pipeline = AddTestPipeline(1, true, true);
EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
@@ -276,14 +275,13 @@ TEST_F(HttpPipelinedHostImplTest, ConnectionCloseHasNoEffect) {
}
TEST_F(HttpPipelinedHostImplTest, SuccessesLeadToCapable) {
- SetCapability(HttpPipelinedHost::UNKNOWN);
+ SetCapability(PIPELINE_UNKNOWN);
MockPipeline* pipeline = AddTestPipeline(1, true, true);
EXPECT_CALL(delegate_, OnHostHasAdditionalCapacity(host_.get()))
.Times(1);
EXPECT_CALL(delegate_,
- OnHostDeterminedCapability(host_.get(),
- HttpPipelinedHost::CAPABLE))
+ OnHostDeterminedCapability(host_.get(), PIPELINE_CAPABLE))
.Times(1);
host_->OnPipelineFeedback(pipeline, HttpPipelinedConnection::OK);
diff --git a/net/http/http_pipelined_host_pool.cc b/net/http/http_pipelined_host_pool.cc
index fa705a0..71eb0ae 100644
--- a/net/http/http_pipelined_host_pool.cc
+++ b/net/http/http_pipelined_host_pool.cc
@@ -6,31 +6,29 @@
#include "base/logging.h"
#include "base/stl_util.h"
+#include "net/http/http_pipelined_host_capability.h"
#include "net/http/http_pipelined_host_impl.h"
+#include "net/http/http_server_properties.h"
namespace net {
-// TODO(simonjam): Run experiments with different values of this to see what
-// value is good at avoiding evictions without eating too much memory. Until
-// then, this is just a bad guess.
-static const int kNumHostsToRemember = 200;
-
class HttpPipelinedHostImplFactory : public HttpPipelinedHost::Factory {
public:
virtual HttpPipelinedHost* CreateNewHost(
HttpPipelinedHost::Delegate* delegate, const HostPortPair& origin,
HttpPipelinedConnection::Factory* factory,
- HttpPipelinedHost::Capability capability) OVERRIDE {
+ HttpPipelinedHostCapability capability) OVERRIDE {
return new HttpPipelinedHostImpl(delegate, origin, factory, capability);
}
};
HttpPipelinedHostPool::HttpPipelinedHostPool(
Delegate* delegate,
- HttpPipelinedHost::Factory* factory)
+ HttpPipelinedHost::Factory* factory,
+ HttpServerProperties* http_server_properties)
: delegate_(delegate),
factory_(factory),
- known_capability_map_(kNumHostsToRemember) {
+ http_server_properties_(http_server_properties) {
if (!factory) {
factory_.reset(new HttpPipelinedHostImplFactory);
}
@@ -42,8 +40,9 @@ HttpPipelinedHostPool::~HttpPipelinedHostPool() {
bool HttpPipelinedHostPool::IsHostEligibleForPipelining(
const HostPortPair& origin) {
- HttpPipelinedHost::Capability capability = GetHostCapability(origin);
- return capability != HttpPipelinedHost::INCAPABLE;
+ HttpPipelinedHostCapability capability =
+ http_server_properties_->GetPipelineCapability(origin);
+ return capability != PIPELINE_INCAPABLE;
}
HttpPipelinedStream* HttpPipelinedHostPool::CreateStreamOnNewPipeline(
@@ -90,8 +89,9 @@ HttpPipelinedHost* HttpPipelinedHostPool::GetPipelinedHost(
return NULL;
}
- HttpPipelinedHost::Capability capability = GetHostCapability(origin);
- if (capability == HttpPipelinedHost::INCAPABLE) {
+ HttpPipelinedHostCapability capability =
+ http_server_properties_->GetPipelineCapability(origin);
+ if (capability == PIPELINE_INCAPABLE) {
return NULL;
}
@@ -115,22 +115,8 @@ void HttpPipelinedHostPool::OnHostHasAdditionalCapacity(
void HttpPipelinedHostPool::OnHostDeterminedCapability(
HttpPipelinedHost* host,
- HttpPipelinedHost::Capability capability) {
- CapabilityMap::iterator known_it = known_capability_map_.Get(host->origin());
- if (known_it == known_capability_map_.end() ||
- known_it->second != HttpPipelinedHost::INCAPABLE) {
- known_capability_map_.Put(host->origin(), capability);
- }
-}
-
-HttpPipelinedHost::Capability HttpPipelinedHostPool::GetHostCapability(
- const HostPortPair& origin) {
- HttpPipelinedHost::Capability capability = HttpPipelinedHost::UNKNOWN;
- CapabilityMap::const_iterator it = known_capability_map_.Get(origin);
- if (it != known_capability_map_.end()) {
- capability = it->second;
- }
- return capability;
+ HttpPipelinedHostCapability capability) {
+ http_server_properties_->SetPipelineCapability(host->origin(), capability);
}
} // namespace net
diff --git a/net/http/http_pipelined_host_pool.h b/net/http/http_pipelined_host_pool.h
index 3be0cb5..67a0b013 100644
--- a/net/http/http_pipelined_host_pool.h
+++ b/net/http/http_pipelined_host_pool.h
@@ -10,14 +10,15 @@
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
-#include "base/memory/mru_cache.h"
#include "base/memory/scoped_ptr.h"
#include "net/http/http_pipelined_host.h"
+#include "net/http/http_pipelined_host_capability.h"
namespace net {
class HostPortPair;
class HttpPipelinedStream;
+class HttpServerProperties;
// Manages all of the pipelining state for specific host with active pipelined
// HTTP requests. Manages connection jobs, constructs pipelined streams, and
@@ -34,7 +35,8 @@ class NET_EXPORT_PRIVATE HttpPipelinedHostPool
};
HttpPipelinedHostPool(Delegate* delegate,
- HttpPipelinedHost::Factory* factory);
+ HttpPipelinedHost::Factory* factory,
+ HttpServerProperties* http_server_properties_);
virtual ~HttpPipelinedHostPool();
// Returns true if pipelining might work for |origin|. Generally, this returns
@@ -67,22 +69,18 @@ class NET_EXPORT_PRIVATE HttpPipelinedHostPool
virtual void OnHostDeterminedCapability(
HttpPipelinedHost* host,
- HttpPipelinedHost::Capability capability) OVERRIDE;
+ HttpPipelinedHostCapability capability) OVERRIDE;
private:
- typedef base::MRUCache<HostPortPair,
- HttpPipelinedHost::Capability> CapabilityMap;
typedef std::map<const HostPortPair, HttpPipelinedHost*> HostMap;
HttpPipelinedHost* GetPipelinedHost(const HostPortPair& origin,
bool create_if_not_found);
- HttpPipelinedHost::Capability GetHostCapability(const HostPortPair& origin);
-
Delegate* delegate_;
scoped_ptr<HttpPipelinedHost::Factory> factory_;
HostMap host_map_;
- CapabilityMap known_capability_map_;
+ HttpServerProperties* http_server_properties_;
DISALLOW_COPY_AND_ASSIGN(HttpPipelinedHostPool);
};
diff --git a/net/http/http_pipelined_host_pool_unittest.cc b/net/http/http_pipelined_host_pool_unittest.cc
index 928e4e9..457f101 100644
--- a/net/http/http_pipelined_host_pool_unittest.cc
+++ b/net/http/http_pipelined_host_pool_unittest.cc
@@ -7,6 +7,8 @@
#include "base/memory/scoped_ptr.h"
#include "net/base/ssl_config_service.h"
#include "net/http/http_pipelined_host.h"
+#include "net/http/http_pipelined_host_capability.h"
+#include "net/http/http_server_properties_impl.h"
#include "net/proxy/proxy_info.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,7 +38,7 @@ class MockHostFactory : public HttpPipelinedHost::Factory {
MOCK_METHOD4(CreateNewHost, HttpPipelinedHost*(
HttpPipelinedHost::Delegate* delegate, const HostPortPair& origin,
HttpPipelinedConnection::Factory* factory,
- HttpPipelinedHost::Capability capability));
+ HttpPipelinedHostCapability capability));
};
class MockHost : public HttpPipelinedHost {
@@ -66,7 +68,9 @@ class HttpPipelinedHostPoolTest : public testing::Test {
: origin_("host", 123),
factory_(new MockHostFactory), // Owned by pool_.
host_(new MockHost(origin_)), // Owned by pool_.
- pool_(new HttpPipelinedHostPool(&delegate_, factory_)),
+ http_server_properties_(new HttpServerPropertiesImpl),
+ pool_(new HttpPipelinedHostPool(&delegate_, factory_,
+ http_server_properties_.get())),
was_npn_negotiated_(false) {
}
@@ -88,6 +92,7 @@ class HttpPipelinedHostPoolTest : public testing::Test {
MockPoolDelegate delegate_;
MockHostFactory* factory_;
MockHost* host_;
+ scoped_ptr<HttpServerPropertiesImpl> http_server_properties_;
scoped_ptr<HttpPipelinedHostPool> pool_;
const SSLConfig ssl_config_;
@@ -99,7 +104,7 @@ class HttpPipelinedHostPoolTest : public testing::Test {
TEST_F(HttpPipelinedHostPoolTest, DefaultUnknown) {
EXPECT_TRUE(pool_->IsHostEligibleForPipelining(origin_));
EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(origin_), _,
- HttpPipelinedHost::UNKNOWN))
+ PIPELINE_UNKNOWN))
.Times(1)
.WillOnce(Return(host_));
@@ -109,16 +114,16 @@ TEST_F(HttpPipelinedHostPoolTest, DefaultUnknown) {
TEST_F(HttpPipelinedHostPoolTest, RemembersIncapable) {
EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(origin_), _,
- HttpPipelinedHost::UNKNOWN))
+ PIPELINE_UNKNOWN))
.Times(1)
.WillOnce(Return(host_));
CreateDummyStream();
- pool_->OnHostDeterminedCapability(host_, HttpPipelinedHost::INCAPABLE);
+ pool_->OnHostDeterminedCapability(host_, PIPELINE_INCAPABLE);
pool_->OnHostIdle(host_);
EXPECT_FALSE(pool_->IsHostEligibleForPipelining(origin_));
EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(origin_), _,
- HttpPipelinedHost::INCAPABLE))
+ PIPELINE_INCAPABLE))
.Times(0);
EXPECT_EQ(NULL,
pool_->CreateStreamOnNewPipeline(origin_, kDummyConnection,
@@ -128,18 +133,18 @@ TEST_F(HttpPipelinedHostPoolTest, RemembersIncapable) {
TEST_F(HttpPipelinedHostPoolTest, RemembersCapable) {
EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(origin_), _,
- HttpPipelinedHost::UNKNOWN))
+ PIPELINE_UNKNOWN))
.Times(1)
.WillOnce(Return(host_));
CreateDummyStream();
- pool_->OnHostDeterminedCapability(host_, HttpPipelinedHost::CAPABLE);
+ pool_->OnHostDeterminedCapability(host_, PIPELINE_CAPABLE);
pool_->OnHostIdle(host_);
EXPECT_TRUE(pool_->IsHostEligibleForPipelining(origin_));
host_ = new MockHost(origin_);
EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(origin_), _,
- HttpPipelinedHost::CAPABLE))
+ PIPELINE_CAPABLE))
.Times(1)
.WillOnce(Return(host_));
CreateDummyStream();
@@ -148,21 +153,21 @@ TEST_F(HttpPipelinedHostPoolTest, RemembersCapable) {
TEST_F(HttpPipelinedHostPoolTest, IncapableIsSticky) {
EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(origin_), _,
- HttpPipelinedHost::UNKNOWN))
+ PIPELINE_UNKNOWN))
.Times(1)
.WillOnce(Return(host_));
CreateDummyStream();
- pool_->OnHostDeterminedCapability(host_, HttpPipelinedHost::CAPABLE);
- pool_->OnHostDeterminedCapability(host_, HttpPipelinedHost::INCAPABLE);
- pool_->OnHostDeterminedCapability(host_, HttpPipelinedHost::CAPABLE);
+ pool_->OnHostDeterminedCapability(host_, PIPELINE_CAPABLE);
+ pool_->OnHostDeterminedCapability(host_, PIPELINE_INCAPABLE);
+ pool_->OnHostDeterminedCapability(host_, PIPELINE_CAPABLE);
pool_->OnHostIdle(host_);
EXPECT_FALSE(pool_->IsHostEligibleForPipelining(origin_));
}
TEST_F(HttpPipelinedHostPoolTest, RemainsUnknownWithoutFeedback) {
EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(origin_), _,
- HttpPipelinedHost::UNKNOWN))
+ PIPELINE_UNKNOWN))
.Times(1)
.WillOnce(Return(host_));
@@ -172,7 +177,7 @@ TEST_F(HttpPipelinedHostPoolTest, RemainsUnknownWithoutFeedback) {
host_ = new MockHost(origin_);
EXPECT_CALL(*factory_, CreateNewHost(pool_.get(), Ref(origin_), _,
- HttpPipelinedHost::UNKNOWN))
+ PIPELINE_UNKNOWN))
.Times(1)
.WillOnce(Return(host_));
@@ -180,6 +185,14 @@ TEST_F(HttpPipelinedHostPoolTest, RemainsUnknownWithoutFeedback) {
pool_->OnHostIdle(host_);
}
+TEST_F(HttpPipelinedHostPoolTest, PopulatesServerProperties) {
+ EXPECT_EQ(PIPELINE_UNKNOWN,
+ http_server_properties_->GetPipelineCapability(host_->origin()));
+ pool_->OnHostDeterminedCapability(host_, PIPELINE_CAPABLE);
+ EXPECT_EQ(PIPELINE_CAPABLE,
+ http_server_properties_->GetPipelineCapability(host_->origin()));
+}
+
} // anonymous namespace
} // namespace net
diff --git a/net/http/http_server_properties.h b/net/http/http_server_properties.h
index 51171c2..cd4ae4b 100644
--- a/net/http/http_server_properties.h
+++ b/net/http/http_server_properties.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
+#include "net/http/http_pipelined_host_capability.h"
#include "net/spdy/spdy_framer.h" // TODO(willchan): Reconsider this.
namespace net {
@@ -35,6 +36,8 @@ struct NET_EXPORT PortAlternateProtocolPair {
typedef std::map<HostPortPair, PortAlternateProtocolPair> AlternateProtocolMap;
typedef std::map<HostPortPair, spdy::SpdySettings> SpdySettingsMap;
+typedef std::map<HostPortPair,
+ HttpPipelinedHostCapability> PipelineCapabilityMap;
extern const char kAlternateProtocolHeader[];
extern const char* const kAlternateProtocolStrings[NUM_ALTERNATE_PROTOCOLS];
@@ -95,6 +98,17 @@ class NET_EXPORT HttpServerProperties {
// Returns all persistent SpdySettings.
virtual const SpdySettingsMap& spdy_settings_map() const = 0;
+ virtual HttpPipelinedHostCapability GetPipelineCapability(
+ const HostPortPair& origin) = 0;
+
+ virtual void SetPipelineCapability(
+ const HostPortPair& origin,
+ HttpPipelinedHostCapability capability) = 0;
+
+ virtual void ClearPipelineCapabilities() = 0;
+
+ virtual PipelineCapabilityMap GetPipelineCapabilityMap() const = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(HttpServerProperties);
};
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc
index d4e1303..b8a7ed1 100644
--- a/net/http/http_server_properties_impl.cc
+++ b/net/http/http_server_properties_impl.cc
@@ -8,10 +8,18 @@
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/stringprintf.h"
+#include "net/http/http_pipelined_host_capability.h"
namespace net {
-HttpServerPropertiesImpl::HttpServerPropertiesImpl() {
+// TODO(simonjam): Run experiments with different values of this to see what
+// value is good at avoiding evictions without eating too much memory. Until
+// then, this is just a bad guess.
+static const int kDefaultNumHostsToRemember = 200;
+
+HttpServerPropertiesImpl::HttpServerPropertiesImpl()
+ : pipeline_capability_map_(
+ new CachedPipelineCapabilityMap(kDefaultNumHostsToRemember)) {
}
HttpServerPropertiesImpl::~HttpServerPropertiesImpl() {
@@ -48,6 +56,21 @@ void HttpServerPropertiesImpl::InitializeSpdySettingsServers(
spdy_settings_map_.swap(*spdy_settings_map);
}
+void HttpServerPropertiesImpl::InitializePipelineCapabilities(
+ const PipelineCapabilityMap* pipeline_capability_map) {
+ PipelineCapabilityMap::const_iterator it;
+ pipeline_capability_map_->Clear();
+ for (it = pipeline_capability_map->begin();
+ it != pipeline_capability_map->end(); ++it) {
+ pipeline_capability_map_->Put(it->first, it->second);
+ }
+}
+
+void HttpServerPropertiesImpl::SetNumPipelinedHostsToRemember(int max_size) {
+ DCHECK(pipeline_capability_map_->empty());
+ pipeline_capability_map_.reset(new CachedPipelineCapabilityMap(max_size));
+}
+
void HttpServerPropertiesImpl::GetSpdyServerList(
base::ListValue* spdy_server_list) const {
DCHECK(CalledOnValidThread());
@@ -94,6 +117,7 @@ void HttpServerPropertiesImpl::Clear() {
spdy_servers_table_.clear();
alternate_protocol_map_.clear();
spdy_settings_map_.clear();
+ pipeline_capability_map_->Clear();
}
bool HttpServerPropertiesImpl::SupportsSpdy(
@@ -239,4 +263,41 @@ HttpServerPropertiesImpl::spdy_settings_map() const {
return spdy_settings_map_;
}
+HttpPipelinedHostCapability HttpServerPropertiesImpl::GetPipelineCapability(
+ const HostPortPair& origin) {
+ HttpPipelinedHostCapability capability = PIPELINE_UNKNOWN;
+ CachedPipelineCapabilityMap::const_iterator it =
+ pipeline_capability_map_->Get(origin);
+ if (it != pipeline_capability_map_->end()) {
+ capability = it->second;
+ }
+ return capability;
+}
+
+void HttpServerPropertiesImpl::SetPipelineCapability(
+ const HostPortPair& origin,
+ HttpPipelinedHostCapability capability) {
+ CachedPipelineCapabilityMap::iterator it =
+ pipeline_capability_map_->Peek(origin);
+ if (it == pipeline_capability_map_->end() ||
+ it->second != PIPELINE_INCAPABLE) {
+ pipeline_capability_map_->Put(origin, capability);
+ }
+}
+
+void HttpServerPropertiesImpl::ClearPipelineCapabilities() {
+ pipeline_capability_map_->Clear();
+}
+
+PipelineCapabilityMap
+HttpServerPropertiesImpl::GetPipelineCapabilityMap() const {
+ PipelineCapabilityMap result;
+ CachedPipelineCapabilityMap::const_iterator it;
+ for (it = pipeline_capability_map_->begin();
+ it != pipeline_capability_map_->end(); ++it) {
+ result[it->first] = it->second;
+ }
+ return result;
+}
+
} // namespace net
diff --git a/net/http/http_server_properties_impl.h b/net/http/http_server_properties_impl.h
index f697848..487e0fd 100644
--- a/net/http/http_server_properties_impl.h
+++ b/net/http/http_server_properties_impl.h
@@ -12,10 +12,12 @@
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/hash_tables.h"
+#include "base/memory/mru_cache.h"
#include "base/threading/non_thread_safe.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
+#include "net/http/http_pipelined_host_capability.h"
#include "net/http/http_server_properties.h"
namespace base {
@@ -42,6 +44,11 @@ class NET_EXPORT HttpServerPropertiesImpl
void InitializeSpdySettingsServers(SpdySettingsMap* spdy_settings_map);
+ // Initializes |pipeline_capability_map_| with the servers (host/port) from
+ // |pipeline_capability_map| that either support HTTP pipelining or not.
+ void InitializePipelineCapabilities(
+ const PipelineCapabilityMap* pipeline_capability_map);
+
// Get the list of servers (host/port) that support SPDY.
void GetSpdyServerList(base::ListValue* spdy_server_list) const;
@@ -56,6 +63,12 @@ class NET_EXPORT HttpServerPropertiesImpl
static void ForceAlternateProtocol(const PortAlternateProtocolPair& pair);
static void DisableForcedAlternateProtocol();
+ // Changes the number of host/port pairs we remember pipelining capability
+ // for. A larger number means we're more likely to be able to pipeline
+ // immediately if a host is known good, but uses more memory. This function
+ // can only be called if |pipeline_capability_map_| is empty.
+ void SetNumPipelinedHostsToRemember(int max_size);
+
// -----------------------------
// HttpServerProperties methods:
// -----------------------------
@@ -106,7 +119,20 @@ class NET_EXPORT HttpServerPropertiesImpl
// Returns all persistent SpdySettings.
virtual const SpdySettingsMap& spdy_settings_map() const OVERRIDE;
+ virtual HttpPipelinedHostCapability GetPipelineCapability(
+ const HostPortPair& origin) OVERRIDE;
+
+ virtual void SetPipelineCapability(
+ const HostPortPair& origin,
+ HttpPipelinedHostCapability capability) OVERRIDE;
+
+ virtual void ClearPipelineCapabilities() OVERRIDE;
+
+ virtual PipelineCapabilityMap GetPipelineCapabilityMap() const OVERRIDE;
+
private:
+ typedef base::MRUCache<
+ HostPortPair, HttpPipelinedHostCapability> CachedPipelineCapabilityMap;
// |spdy_servers_table_| has flattened representation of servers (host/port
// pair) that either support or not support SPDY protocol.
typedef base::hash_map<std::string, bool> SpdyServerHostPortTable;
@@ -114,6 +140,7 @@ class NET_EXPORT HttpServerPropertiesImpl
AlternateProtocolMap alternate_protocol_map_;
SpdySettingsMap spdy_settings_map_;
+ scoped_ptr<CachedPipelineCapabilityMap> pipeline_capability_map_;
DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesImpl);
};
diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc
index dd7776f..735532d 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -37,7 +37,8 @@ GURL UpgradeUrlToHttps(const GURL& original_url, int port) {
HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session)
: session_(session),
- http_pipelined_host_pool_(this, NULL) {}
+ http_pipelined_host_pool_(this, NULL,
+ session_->http_server_properties()) {}
HttpStreamFactoryImpl::~HttpStreamFactoryImpl() {
DCHECK(request_map_.empty());
diff --git a/net/net.gyp b/net/net.gyp
index ee63fd2..446c628 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -436,6 +436,7 @@
'http/http_pipelined_connection_impl.cc',
'http/http_pipelined_connection_impl.h',
'http/http_pipelined_host.h',
+ 'http/http_pipelined_host_capability.h',
'http/http_pipelined_host_impl.cc',
'http/http_pipelined_host_impl.h',
'http/http_pipelined_host_pool.cc',