diff options
author | simonjam@chromium.org <simonjam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-07 01:21:26 +0000 |
---|---|---|
committer | simonjam@chromium.org <simonjam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-07 01:21:26 +0000 |
commit | acc32d123e055aa4c2c11538c8405164ef9c9998 (patch) | |
tree | 544fb0d50a185acde818a24e8761d37dabc28935 /net | |
parent | 12d264b91951777c613f7ca8346cd3e3545f0ca0 (diff) | |
download | chromium_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.h | 18 | ||||
-rw-r--r-- | net/http/http_pipelined_host_capability.h | 24 | ||||
-rw-r--r-- | net/http/http_pipelined_host_impl.cc | 28 | ||||
-rw-r--r-- | net/http/http_pipelined_host_impl.h | 5 | ||||
-rw-r--r-- | net/http/http_pipelined_host_impl_unittest.cc | 22 | ||||
-rw-r--r-- | net/http/http_pipelined_host_pool.cc | 42 | ||||
-rw-r--r-- | net/http/http_pipelined_host_pool.h | 14 | ||||
-rw-r--r-- | net/http/http_pipelined_host_pool_unittest.cc | 43 | ||||
-rw-r--r-- | net/http/http_server_properties.h | 14 | ||||
-rw-r--r-- | net/http/http_server_properties_impl.cc | 63 | ||||
-rw-r--r-- | net/http/http_server_properties_impl.h | 27 | ||||
-rw-r--r-- | net/http/http_stream_factory_impl.cc | 3 | ||||
-rw-r--r-- | net/net.gyp | 1 |
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', |