diff options
author | gavinp@chromium.org <gavinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-27 16:56:45 +0000 |
---|---|---|
committer | gavinp@chromium.org <gavinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-27 16:56:45 +0000 |
commit | 47f17f7dd6c6718e98ab9c6f1e970cd6d526b18d (patch) | |
tree | 7e2136f085b79f9289cd7454de45fca2b8224655 | |
parent | 70ebea88dc660be8bd16c3fff01c8147197ae81e (diff) | |
download | chromium_src-47f17f7dd6c6718e98ab9c6f1e970cd6d526b18d.zip chromium_src-47f17f7dd6c6718e98ab9c6f1e970cd6d526b18d.tar.gz chromium_src-47f17f7dd6c6718e98ab9c6f1e970cd6d526b18d.tar.bz2 |
Make three simultanious prerenders the default maximum in Canary and Dev only.
Very basic support for three simultanious prerenders, as a basis for continued updates on the API.
R=dominich@chromium.org
BUG=None
Review URL: https://chromiumcodereview.appspot.com/10802024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148761 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/prerender/prerender_browsertest.cc | 16 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_config.cc | 2 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_config.h | 5 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_field_trial.cc | 25 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_histograms.cc | 13 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_histograms.h | 4 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.cc | 17 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.h | 5 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_unittest.cc | 104 |
9 files changed, 116 insertions, 75 deletions
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index cdc8a99..52b77cc 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc @@ -235,8 +235,8 @@ class TestPrerenderContents : public PrerenderContents { virtual void AddPendingPrerender( base::WeakPtr<PrerenderHandle> weak_prerender_handle, const GURL& url, - const content::Referrer& referrer, - const gfx::Size& size) OVERRIDE { + const content::Referrer& referrer, + const gfx::Size& size) OVERRIDE { PrerenderContents::AddPendingPrerender( weak_prerender_handle, url, referrer, size); if (expected_pending_prerenders_ > 0 && @@ -1524,12 +1524,13 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderInfiniteLoopMultiple) { const char* const kHtmlFileC = "files/prerender/prerender_infinite_c_multiple.html"; - // We need to set the final status to expect here before starting any - // prerenders. We set them on a queue so whichever we see first is expected to - // be evicted, and the second should stick around until we exit. + // This test is conceptually simplest if concurrency is at two, since we + // don't have to worry about which of kHtmlFileB or kHtmlFileC gets evicted. + GetPrerenderManager()->mutable_config().max_concurrency = 2; + std::deque<FinalStatus> expected_final_status_queue; expected_final_status_queue.push_back(FINAL_STATUS_USED); - expected_final_status_queue.push_back(FINAL_STATUS_EVICTED); + expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING); expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING); PrerenderTestURL(kHtmlFileA, expected_final_status_queue, 1); @@ -1549,8 +1550,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderInfiniteLoopMultiple) { // active entry. bool url_b_is_active_prerender = UrlIsInPrerenderManager(kHtmlFileB); bool url_c_is_active_prerender = UrlIsInPrerenderManager(kHtmlFileC); - EXPECT_TRUE((url_b_is_active_prerender || url_c_is_active_prerender) && - !(url_b_is_active_prerender && url_c_is_active_prerender)); + EXPECT_TRUE(url_b_is_active_prerender && url_c_is_active_prerender); EXPECT_FALSE(UrlIsPending(kHtmlFileB)); EXPECT_FALSE(UrlIsPending(kHtmlFileC)); } diff --git a/chrome/browser/prerender/prerender_config.cc b/chrome/browser/prerender/prerender_config.cc index f409918..43f34d9 100644 --- a/chrome/browser/prerender/prerender_config.cc +++ b/chrome/browser/prerender/prerender_config.cc @@ -7,7 +7,7 @@ namespace prerender { Config::Config() : max_bytes(100 * 1024 * 1024), - max_elements(1), + max_concurrency(1), rate_limit_enabled(true), max_age(base::TimeDelta::FromSeconds(30)), https_allowed(true), diff --git a/chrome/browser/prerender/prerender_config.h b/chrome/browser/prerender/prerender_config.h index 04f244b..70f609a 100644 --- a/chrome/browser/prerender/prerender_config.h +++ b/chrome/browser/prerender/prerender_config.h @@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_PRERENDER_PRERENDER_CONFIG_H_ #define CHROME_BROWSER_PRERENDER_PRERENDER_CONFIG_H_ +#include <string> + #include "base/time.h" #include "ui/gfx/rect.h" @@ -17,7 +19,7 @@ struct Config { size_t max_bytes; // Number of simultaneous prendered pages allowed. - unsigned int max_elements; + size_t max_concurrency; // Is rate limiting enabled? bool rate_limit_enabled; @@ -42,3 +44,4 @@ struct Config { } // namespace prerender #endif // CHROME_BROWSER_PRERENDER_PRERENDER_CONFIG_H_ + diff --git a/chrome/browser/prerender/prerender_field_trial.cc b/chrome/browser/prerender/prerender_field_trial.cc index 1d48b47..60ce6a3 100644 --- a/chrome/browser/prerender/prerender_field_trial.cc +++ b/chrome/browser/prerender/prerender_field_trial.cc @@ -52,6 +52,7 @@ void SetupPrerenderFieldTrial() { const FieldTrial::Probability divisor = 1000; FieldTrial::Probability control_probability; + FieldTrial::Probability experiment_multi_prerender_probability; FieldTrial::Probability experiment_5min_ttl_probability; FieldTrial::Probability experiment_no_use_probability; @@ -61,30 +62,40 @@ void SetupPrerenderFieldTrial() { // Use very conservatives and stable settings in beta and stable. const FieldTrial::Probability release_prerender_enabled_probability = 980; const FieldTrial::Probability release_control_probability = 10; + const FieldTrial::Probability + release_experiment_multi_prerender_probability = 0; const FieldTrial::Probability release_experiment_5min_ttl_probability = 10; const FieldTrial::Probability release_experiment_no_use_probability = 0; COMPILE_ASSERT( release_prerender_enabled_probability + release_control_probability + + release_experiment_multi_prerender_probability + release_experiment_5min_ttl_probability + release_experiment_no_use_probability == divisor, release_experiment_probabilities_must_equal_divisor); control_probability = release_experiment_5min_ttl_probability; + experiment_multi_prerender_probability = + release_experiment_multi_prerender_probability; experiment_5min_ttl_probability = release_control_probability; experiment_no_use_probability = release_experiment_no_use_probability; } else { // In testing channels, use more experiments and a larger control group to // improve quality of data. - const FieldTrial::Probability dev_prerender_enabled_probability = 333; - const FieldTrial::Probability dev_control_probability = 333; - const FieldTrial::Probability dev_experiment_5min_ttl_probability = 167; - const FieldTrial::Probability dev_experiment_no_use_probability = 167; + const FieldTrial::Probability dev_prerender_enabled_probability = 250; + const FieldTrial::Probability dev_control_probability = 250; + const FieldTrial::Probability + dev_experiment_multi_prerender_probability = 250; + const FieldTrial::Probability dev_experiment_5min_ttl_probability = 125; + const FieldTrial::Probability dev_experiment_no_use_probability = 125; COMPILE_ASSERT(dev_prerender_enabled_probability + dev_control_probability + + dev_experiment_multi_prerender_probability + dev_experiment_5min_ttl_probability + dev_experiment_no_use_probability == divisor, dev_experiment_probabilities_must_equal_divisor); control_probability = dev_experiment_5min_ttl_probability; + experiment_multi_prerender_probability = + dev_experiment_multi_prerender_probability; experiment_5min_ttl_probability = dev_control_probability; experiment_no_use_probability = dev_experiment_no_use_probability; } @@ -97,6 +108,9 @@ void SetupPrerenderFieldTrial() { const int control_group = trial->AppendGroup("PrerenderControl", control_probability); + const int experiment_multi_prerender_group = + trial->AppendGroup("PrerenderMulti", + experiment_multi_prerender_probability); const int experiment_5_min_TTL_group = trial->AppendGroup("Prerender5minTTL", experiment_5min_ttl_probability); @@ -111,6 +125,9 @@ void SetupPrerenderFieldTrial() { } else if (trial_group == control_group) { PrerenderManager::SetMode( PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP); + } else if (trial_group == experiment_multi_prerender_group) { + PrerenderManager::SetMode( + PrerenderManager::PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP); } else if (trial_group == experiment_5_min_TTL_group) { PrerenderManager::SetMode( PrerenderManager::PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP); diff --git a/chrome/browser/prerender/prerender_histograms.cc b/chrome/browser/prerender/prerender_histograms.cc index a79c637..657d0f6 100644 --- a/chrome/browser/prerender/prerender_histograms.cc +++ b/chrome/browser/prerender/prerender_histograms.cc @@ -6,6 +6,7 @@ #include <string> +#include "base/format_macros.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram.h" #include "base/stringprintf.h" @@ -156,6 +157,18 @@ void PrerenderHistograms::RecordPrerenderStarted(Origin origin) const { } } +void PrerenderHistograms::RecordConcurrency(size_t prerender_count) const { + static const size_t kMaxRecordableConcurrency = 3; + const size_t max_concurrency = PrerenderManager::GetMaxConcurrency(); + DCHECK_GE(kMaxRecordableConcurrency, max_concurrency); + if (max_concurrency > 1) { + UMA_HISTOGRAM_ENUMERATION( + StringPrintf("Prerender.PrerenderCountOf%" PRIuS "Max", + max_concurrency), + prerender_count, kMaxRecordableConcurrency + 1); + } +} + void PrerenderHistograms::RecordUsedPrerender(Origin origin) const { if (OriginIsOmnibox(origin)) { UMA_HISTOGRAM_ENUMERATION( diff --git a/chrome/browser/prerender/prerender_histograms.h b/chrome/browser/prerender/prerender_histograms.h index 9e10541..61ca823 100644 --- a/chrome/browser/prerender/prerender_histograms.h +++ b/chrome/browser/prerender/prerender_histograms.h @@ -79,6 +79,10 @@ class PrerenderHistograms { // To be called when a new prerender is started. void RecordPrerenderStarted(Origin origin) const; + // To be called when we know how many prerenders are running after starting + // a prerender. + void RecordConcurrency(size_t prerender_count) const; + // Called when we swap in a prerender. void RecordUsedPrerender(Origin origin) const; diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index 5e7b4c6b..736792b 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc @@ -69,9 +69,6 @@ const int kWindowDurationSeconds = 30; // Time interval at which periodic cleanups are performed. const int kPeriodicCleanupIntervalMs = 1000; -// Time interval before a new prerender is allowed. -const int kMinTimeBetweenPrerendersMs = 500; - // Valid HTTP methods for prerendering. const char* const kValidHttpMethods[] = { "GET", @@ -196,6 +193,7 @@ PrerenderManager::PrerenderManager(Profile* profile, // Any other checks simply make sure that the PrerenderManager is accessed on // the same thread that it was created on. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + config_.max_concurrency = GetMaxConcurrency(); } PrerenderManager::~PrerenderManager() { @@ -555,6 +553,8 @@ const char* PrerenderManager::GetModeString() { return "_Enabled"; case PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP: return "_Control"; + case PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP: + return "_Multi"; case PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP: return "_5MinTTL"; case PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP: @@ -586,6 +586,13 @@ bool PrerenderManager::IsNoUseGroup() { return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; } +// static +size_t PrerenderManager::GetMaxConcurrency() { + if (GetMode() == PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP) + return 3; + return 1; +} + bool PrerenderManager::IsWebContentsPrerendering( WebContents* web_contents) const { DCHECK(CalledOnValidThread()); @@ -945,12 +952,14 @@ PrerenderHandle* PrerenderManager::AddPrerender( session_storage_namespace, control_group_behavior); - while (active_prerender_list_.size() > config_.max_elements) { + while (active_prerender_list_.size() > config_.max_concurrency) { prerender_contents = active_prerender_list_.front()->contents_; DCHECK(prerender_contents); prerender_contents->Destroy(FINAL_STATUS_EVICTED); } + histograms_->RecordConcurrency(active_prerender_list_.size()); + StartSchedulingPeriodicCleanups(); return prerender_handle; } diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h index 3341572..edada5a 100644 --- a/chrome/browser/prerender/prerender_manager.h +++ b/chrome/browser/prerender/prerender_manager.h @@ -78,6 +78,7 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP, PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP, PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP, + PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP, PRERENDER_MODE_MAX }; @@ -176,6 +177,7 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, static bool ActuallyPrerendering(); static bool IsControlGroup(); static bool IsNoUseGroup(); + static size_t GetMaxConcurrency(); // Query the list of current prerender pages to see if the given web contents // is prerendering a page. @@ -313,6 +315,9 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, typedef base::hash_map<content::WebContents*, bool> WouldBePrerenderedMap; + // Time interval before a new prerender is allowed. + static const int kMinTimeBetweenPrerendersMs = 500; + // Time window for which we record old navigations, in milliseconds. static const int kNavigationRecordWindowMs = 5000; diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc index 07684df..d5639af 100644 --- a/chrome/browser/prerender/prerender_unittest.cc +++ b/chrome/browser/prerender/prerender_unittest.cc @@ -5,6 +5,7 @@ #include "base/command_line.h" #include "base/memory/scoped_vector.h" #include "base/message_loop.h" +#include "base/stringprintf.h" #include "base/time.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/prerender/prerender_handle.h" @@ -74,6 +75,7 @@ const gfx::Size kSize(640, 480); class UnitTestPrerenderManager : public PrerenderManager { public: + using PrerenderManager::kMinTimeBetweenPrerendersMs; using PrerenderManager::kNavigationRecordWindowMs; using PrerenderManager::GetMaxAge; @@ -386,67 +388,50 @@ TEST_F(PrerenderTest, ExpireTest) { ASSERT_EQ(null, prerender_manager()->FindEntry(url)); } -// LRU Test. Make sure that if we prerender more than one request, that +// LRU Test. Make sure that if we prerender more requests than we support, that // the oldest one will be dropped. TEST_F(PrerenderTest, DropOldestRequestTest) { - GURL url("http://www.google.com/"); - DummyPrerenderContents* prerender_contents = - prerender_manager()->CreateNextPrerenderContents( - url, - FINAL_STATUS_EVICTED); - DummyPrerenderContents* null = NULL; - EXPECT_TRUE(AddSimplePrerender(url)); - EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); - EXPECT_TRUE(prerender_contents->prerendering_has_started()); - - GURL url1("http://news.google.com/"); - DummyPrerenderContents* prerender_contents1 = - prerender_manager()->CreateNextPrerenderContents( - url1, - FINAL_STATUS_USED); - EXPECT_TRUE(AddSimplePrerender(url1)); - EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); - EXPECT_TRUE(prerender_contents1->prerendering_has_started()); - - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); - ASSERT_EQ(prerender_contents1, prerender_manager()->FindAndUseEntry(url1)); -} + std::vector<int> concurrencies_to_test; + concurrencies_to_test.push_back( + prerender_manager()->config().max_concurrency); + concurrencies_to_test.push_back(1); + concurrencies_to_test.push_back(2); -// Two element prerender test. Ensure that the LRU operates correctly if we -// permit 2 elements to be kept prerendered. -TEST_F(PrerenderTest, TwoElementPrerenderTest) { - prerender_manager()->mutable_config().max_elements = 2; - GURL url("http://www.google.com/"); - DummyPrerenderContents* prerender_contents = - prerender_manager()->CreateNextPrerenderContents( - url, - FINAL_STATUS_EVICTED); DummyPrerenderContents* null = NULL; - EXPECT_TRUE(AddSimplePrerender(url)); - EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); - EXPECT_TRUE(prerender_contents->prerendering_has_started()); - - GURL url1("http://news.google.com/"); - DummyPrerenderContents* prerender_contents1 = - prerender_manager()->CreateNextPrerenderContents( - url1, - FINAL_STATUS_USED); - EXPECT_TRUE(AddSimplePrerender(url1)); - EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); - EXPECT_TRUE(prerender_contents1->prerendering_has_started()); - - GURL url2("http://images.google.com/"); - DummyPrerenderContents* prerender_contents2 = - prerender_manager()->CreateNextPrerenderContents( - url2, - FINAL_STATUS_USED); - EXPECT_TRUE(AddSimplePrerender(url2)); - EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); - EXPECT_TRUE(prerender_contents2->prerendering_has_started()); + GURL url_to_evict("http://www.google.com/evictme"); + + for (std::vector<int>::const_iterator i = concurrencies_to_test.begin(); + i != concurrencies_to_test.end(); + ++i) { + const int max_concurrency = *i; + prerender_manager()->mutable_config().max_concurrency = max_concurrency; + + DummyPrerenderContents* prerender_contents_to_evict = + prerender_manager()->CreateNextPrerenderContents( + url_to_evict, FINAL_STATUS_EVICTED); + EXPECT_TRUE(AddSimplePrerender(url_to_evict)); + EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); + EXPECT_TRUE(prerender_contents_to_evict->prerendering_has_started()); + + std::vector<GURL> urls; + std::vector<PrerenderContents*> prerender_contentses; + + for (int j = 0; j < max_concurrency; ++j) { + urls.push_back(GURL(base::StringPrintf("http://google.com/use#%d", j))); + prerender_contentses.push_back( + prerender_manager()->CreateNextPrerenderContents(urls.back(), + FINAL_STATUS_USED)); + EXPECT_TRUE(AddSimplePrerender(urls.back())); + EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); + EXPECT_TRUE(prerender_contentses.back()->prerendering_has_started()); + } - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); - ASSERT_EQ(prerender_contents1, prerender_manager()->FindAndUseEntry(url1)); - ASSERT_EQ(prerender_contents2, prerender_manager()->FindAndUseEntry(url2)); + ASSERT_EQ(null, prerender_manager()->FindEntry(url_to_evict)); + for (int j = 0; j < max_concurrency; ++j) { + ASSERT_EQ(prerender_contentses[j], + prerender_manager()->FindAndUseEntry(urls[j])); + } + } } TEST_F(PrerenderTest, AliasURLTest) { @@ -511,6 +496,10 @@ TEST_F(PrerenderTest, RateLimitInWindowTest) { // Ensure that we don't ignore prerender requests outside the rate limit. TEST_F(PrerenderTest, RateLimitOutsideWindowTest) { + // Setting concurrency to one lets us force eviction by adding only one more + // prerender. + prerender_manager()->mutable_config().max_concurrency = 1; + GURL url("http://www.google.com/"); DummyPrerenderContents* prerender_contents = prerender_manager()->CreateNextPrerenderContents( @@ -523,7 +512,8 @@ TEST_F(PrerenderTest, RateLimitOutsideWindowTest) { prerender_manager()->set_rate_limit_enabled(true); prerender_manager()->AdvanceTimeTicks( - base::TimeDelta::FromMilliseconds(2000)); + base::TimeDelta::FromMilliseconds( + UnitTestPrerenderManager::kMinTimeBetweenPrerendersMs + 500)); GURL url1("http://news.google.com/"); DummyPrerenderContents* rate_limit_prerender_contents = |