Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(572)

Side by Side Diff: chrome/browser/net/predictor.cc

Issue 16514008: Add metrics for calculating precision/recall of link navigation pre-connect triggers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove PRERENDER flag change Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/net/predictor.h ('k') | chrome/browser/net/predictor_tab_helper.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/net/predictor.h" 5 #include "chrome/browser/net/predictor.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <set> 9 #include <set>
10 #include <sstream> 10 #include <sstream>
11 11
12 #include "base/basictypes.h"
12 #include "base/bind.h" 13 #include "base/bind.h"
13 #include "base/command_line.h" 14 #include "base/command_line.h"
14 #include "base/compiler_specific.h" 15 #include "base/compiler_specific.h"
16 #include "base/containers/mru_cache.h"
15 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_service.h" 18 #include "base/prefs/pref_service.h"
17 #include "base/stl_util.h" 19 #include "base/stl_util.h"
18 #include "base/strings/string_split.h" 20 #include "base/strings/string_split.h"
19 #include "base/strings/string_util.h" 21 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h" 22 #include "base/strings/stringprintf.h"
21 #include "base/synchronization/waitable_event.h" 23 #include "base/synchronization/waitable_event.h"
22 #include "base/threading/thread_restrictions.h" 24 #include "base/threading/thread_restrictions.h"
23 #include "base/time/time.h" 25 #include "base/time/time.h"
24 #include "base/values.h" 26 #include "base/values.h"
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 120
119 Predictor* predictor_; // The predictor which started us. 121 Predictor* predictor_; // The predictor which started us.
120 122
121 const GURL url_; // Hostname to resolve. 123 const GURL url_; // Hostname to resolve.
122 net::SingleRequestHostResolver resolver_; 124 net::SingleRequestHostResolver resolver_;
123 net::AddressList addresses_; 125 net::AddressList addresses_;
124 126
125 DISALLOW_COPY_AND_ASSIGN(LookupRequest); 127 DISALLOW_COPY_AND_ASSIGN(LookupRequest);
126 }; 128 };
127 129
130 // This records UMAs for preconnect usage based on navigation URLs to
131 // gather precision/recall for user-event based preconnect triggers.
132 // Stats are gathered via a LRU cache that remembers all preconnect within the
133 // last N seconds.
134 // A preconnect trigger is considered as used iff a navigation including
135 // access to the preconnected host occurs within a time period specified by
136 // kMaxUnusedSocketLifetimeSecondsWithoutAGet.
137 class Predictor::PreconnectUsage {
138 public:
139 PreconnectUsage();
140 ~PreconnectUsage();
141
142 // Record a preconnect trigger to |url|.
143 void ObservePreconnect(const GURL& url);
144
145 // Record a user navigation with its redirect history, |url_chain|.
146 // We are uncertain if this is actually a link navigation.
147 void ObserveNavigationChain(const std::vector<GURL>& url_chain,
148 bool is_subresource);
149
150 // Record a user link navigation to |final_url|.
151 // We are certain that this is a user-triggered link navigation.
152 void ObserveLinkNavigation(const GURL& final_url);
153
154 private:
155 // This tracks whether a preconnect was used in some navigation or not
156 class PreconnectPrecisionStat {
157 public:
158 PreconnectPrecisionStat()
159 : timestamp_(base::TimeTicks::Now()),
160 was_used_(false) {
161 }
162
163 const base::TimeTicks& timestamp() { return timestamp_; }
164
165 void set_was_used() { was_used_ = true; }
166 bool was_used() const { return was_used_; }
167
168 private:
169 base::TimeTicks timestamp_;
170 bool was_used_;
171 };
172
173 typedef base::MRUCache<GURL, PreconnectPrecisionStat> MRUPreconnects;
174 MRUPreconnects mru_preconnects_;
175
176 // The longest time an entry can persist in mru_preconnect_
177 const base::TimeDelta max_duration_;
178
179 std::vector<GURL> recent_navigation_chain_;
180
181 DISALLOW_COPY_AND_ASSIGN(PreconnectUsage);
182 };
183
184 Predictor::PreconnectUsage::PreconnectUsage()
185 : mru_preconnects_(MRUPreconnects::NO_AUTO_EVICT),
186 max_duration_(base::TimeDelta::FromSeconds(
187 Predictor::kMaxUnusedSocketLifetimeSecondsWithoutAGet)) {
188 }
189
190 Predictor::PreconnectUsage::~PreconnectUsage() {}
191
192 void Predictor::PreconnectUsage::ObservePreconnect(const GURL& url) {
193 // Evict any overly old entries and record stats.
194 base::TimeTicks now = base::TimeTicks::Now();
195
196 MRUPreconnects::reverse_iterator eldest_preconnect =
197 mru_preconnects_.rbegin();
198 while (!mru_preconnects_.empty()) {
199 DCHECK(eldest_preconnect == mru_preconnects_.rbegin());
200 if (now - eldest_preconnect->second.timestamp() < max_duration_)
201 break;
202
203 UMA_HISTOGRAM_BOOLEAN("Net.PreconnectTriggerUsed",
204 eldest_preconnect->second.was_used());
205 eldest_preconnect = mru_preconnects_.Erase(eldest_preconnect);
206 }
207
208 // Add new entry.
209 GURL canonical_url(Predictor::CanonicalizeUrl(url));
210 mru_preconnects_.Put(canonical_url, PreconnectPrecisionStat());
211 }
212
213 void Predictor::PreconnectUsage::ObserveNavigationChain(
214 const std::vector<GURL>& url_chain,
215 bool is_subresource) {
216 if (url_chain.empty())
217 return;
218
219 if (!is_subresource)
220 recent_navigation_chain_ = url_chain;
221
222 GURL canonical_url(Predictor::CanonicalizeUrl(url_chain.back()));
223
224 // Record the preconnect trigger for the url as used if exist
225 MRUPreconnects::iterator itPreconnect = mru_preconnects_.Peek(canonical_url);
226 bool was_preconnected = (itPreconnect != mru_preconnects_.end());
227 if (was_preconnected)
228 itPreconnect->second.set_was_used();
229
230 // This is an UMA which was named incorrectly. This actually measures the
231 // ratio of URLRequests which have used a preconnected session.
232 UMA_HISTOGRAM_BOOLEAN("Net.PreconnectedNavigation", was_preconnected);
233 }
234
235 void Predictor::PreconnectUsage::ObserveLinkNavigation(const GURL& url) {
236 if (recent_navigation_chain_.empty() ||
237 url != recent_navigation_chain_.back()) {
238 // The navigation chain is not available for this navigation.
239 recent_navigation_chain_.clear();
240 recent_navigation_chain_.push_back(url);
241 }
242
243 // See if the link navigation involved preconnected session.
244 bool did_use_preconnect = false;
245 for (std::vector<GURL>::const_iterator it = recent_navigation_chain_.begin();
246 it != recent_navigation_chain_.end();
247 ++it) {
248 GURL canonical_url(Predictor::CanonicalizeUrl(*it));
249
250 // Record the preconnect trigger for the url as used if exist
251 MRUPreconnects::iterator itPreconnect =
252 mru_preconnects_.Peek(canonical_url);
253 bool was_preconnected = (itPreconnect != mru_preconnects_.end());
254 if (was_preconnected)
255 did_use_preconnect = true;
256 }
257
258 UMA_HISTOGRAM_BOOLEAN("Net.PreconnectedLinkNavigations", did_use_preconnect);
259 }
260
128 Predictor::Predictor(bool preconnect_enabled) 261 Predictor::Predictor(bool preconnect_enabled)
129 : url_request_context_getter_(NULL), 262 : url_request_context_getter_(NULL),
130 predictor_enabled_(true), 263 predictor_enabled_(true),
131 peak_pending_lookups_(0), 264 peak_pending_lookups_(0),
132 shutdown_(false), 265 shutdown_(false),
133 max_concurrent_dns_lookups_(g_max_parallel_resolves), 266 max_concurrent_dns_lookups_(g_max_parallel_resolves),
134 max_dns_queue_delay_( 267 max_dns_queue_delay_(
135 TimeDelta::FromMilliseconds(g_max_queueing_delay_ms)), 268 TimeDelta::FromMilliseconds(g_max_queueing_delay_ms)),
136 host_resolver_(NULL), 269 host_resolver_(NULL),
137 preconnect_enabled_(preconnect_enabled), 270 preconnect_enabled_(preconnect_enabled),
138 consecutive_omnibox_preconnect_count_(0), 271 consecutive_omnibox_preconnect_count_(0),
139 recent_preconnects_(
140 TimeDelta::FromSeconds(kMaxUnusedSocketLifetimeSecondsWithoutAGet)),
141 next_trim_time_(base::TimeTicks::Now() + 272 next_trim_time_(base::TimeTicks::Now() +
142 TimeDelta::FromHours(kDurationBetweenTrimmingsHours)) { 273 TimeDelta::FromHours(kDurationBetweenTrimmingsHours)) {
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
144 } 275 }
145 276
146 Predictor::~Predictor() { 277 Predictor::~Predictor() {
147 // TODO(rlp): Add DCHECK for CurrentlyOn(BrowserThread::IO) when the 278 // TODO(rlp): Add DCHECK for CurrentlyOn(BrowserThread::IO) when the
148 // ProfileManagerTest has been updated with a mock profile. 279 // ProfileManagerTest has been updated with a mock profile.
149 DCHECK(shutdown_); 280 DCHECK(shutdown_);
150 } 281 }
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 void Predictor::FinalizeInitializationOnIOThread( 792 void Predictor::FinalizeInitializationOnIOThread(
662 const UrlList& startup_urls, 793 const UrlList& startup_urls,
663 base::ListValue* referral_list, 794 base::ListValue* referral_list,
664 IOThread* io_thread, 795 IOThread* io_thread,
665 bool predictor_enabled) { 796 bool predictor_enabled) {
666 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 797 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
667 798
668 predictor_enabled_ = predictor_enabled; 799 predictor_enabled_ = predictor_enabled;
669 initial_observer_.reset(new InitialObserver()); 800 initial_observer_.reset(new InitialObserver());
670 host_resolver_ = io_thread->globals()->host_resolver.get(); 801 host_resolver_ = io_thread->globals()->host_resolver.get();
802 preconnect_usage_.reset(new PreconnectUsage());
671 803
672 // base::WeakPtrFactory instances need to be created and destroyed 804 // base::WeakPtrFactory instances need to be created and destroyed
673 // on the same thread. The predictor lives on the IO thread and will die 805 // on the same thread. The predictor lives on the IO thread and will die
674 // from there so now that we're on the IO thread we need to properly 806 // from there so now that we're on the IO thread we need to properly
675 // initialize the base::WeakPtrFactory. 807 // initialize the base::WeakPtrFactory.
676 // TODO(groby): Check if WeakPtrFactory has the same constraint. 808 // TODO(groby): Check if WeakPtrFactory has the same constraint.
677 weak_factory_.reset(new base::WeakPtrFactory<Predictor>(this)); 809 weak_factory_.reset(new base::WeakPtrFactory<Predictor>(this));
678 810
679 // Prefetch these hostnames on startup. 811 // Prefetch these hostnames on startup.
680 DnsPrefetchMotivatedList(startup_urls, UrlInfo::STARTUP_LIST_MOTIVATED); 812 DnsPrefetchMotivatedList(startup_urls, UrlInfo::STARTUP_LIST_MOTIVATED);
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 BrowserThread::PostTask( 969 BrowserThread::PostTask(
838 BrowserThread::IO, 970 BrowserThread::IO,
839 FROM_HERE, 971 FROM_HERE,
840 base::Bind(&Predictor::PreconnectUrlOnIOThread, 972 base::Bind(&Predictor::PreconnectUrlOnIOThread,
841 base::Unretained(this), url, first_party_for_cookies, 973 base::Unretained(this), url, first_party_for_cookies,
842 motivation, count)); 974 motivation, count));
843 } 975 }
844 } 976 }
845 977
846 void Predictor::PreconnectUrlOnIOThread( 978 void Predictor::PreconnectUrlOnIOThread(
847 const GURL& url, const GURL& first_party_for_cookies, 979 const GURL& url,
848 UrlInfo::ResolutionMotivation motivation, int count) { 980 const GURL& first_party_for_cookies,
849 GURL canonical_url(CanonicalizeUrl(url)); 981 UrlInfo::ResolutionMotivation motivation,
850 recent_preconnects_.SetRecentlySeen(canonical_url); 982 int count) {
983 if (motivation == UrlInfo::MOUSE_OVER_MOTIVATED)
984 RecordPreconnectTrigger(url);
851 985
852 PreconnectOnIOThread(url, 986 PreconnectOnIOThread(url,
853 first_party_for_cookies, 987 first_party_for_cookies,
854 motivation, 988 motivation,
855 count, 989 count,
856 url_request_context_getter_.get()); 990 url_request_context_getter_.get());
857 } 991 }
858 992
859 void Predictor::RecordPreconnectNavigationStats(const GURL& url) { 993 void Predictor::RecordPreconnectTrigger(const GURL& url) {
860 UMA_HISTOGRAM_BOOLEAN( 994 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
861 "Net.PreconnectedNavigation", 995 if (preconnect_usage_)
862 recent_preconnects_.WasRecentlySeen(url)); 996 preconnect_usage_->ObservePreconnect(url);
997 }
998
999 void Predictor::RecordPreconnectNavigationStat(
1000 const std::vector<GURL>& url_chain,
1001 bool is_subresource) {
1002 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1003
1004 if (preconnect_usage_)
1005 preconnect_usage_->ObserveNavigationChain(url_chain, is_subresource);
1006 }
1007
1008 void Predictor::RecordLinkNavigation(const GURL& url) {
1009 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1010 if (preconnect_usage_)
1011 preconnect_usage_->ObserveLinkNavigation(url);
863 } 1012 }
864 1013
865 void Predictor::PredictFrameSubresources(const GURL& url, 1014 void Predictor::PredictFrameSubresources(const GURL& url,
866 const GURL& first_party_for_cookies) { 1015 const GURL& first_party_for_cookies) {
867 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 1016 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
868 BrowserThread::CurrentlyOn(BrowserThread::IO)); 1017 BrowserThread::CurrentlyOn(BrowserThread::IO));
869 if (!predictor_enabled_) 1018 if (!predictor_enabled_)
870 return; 1019 return;
871 DCHECK_EQ(url.GetWithEmptyPath(), url); 1020 DCHECK_EQ(url.GetWithEmptyPath(), url);
872 // Add one pass through the message loop to allow current navigation to 1021 // Add one pass through the message loop to allow current navigation to
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
1227 IOThread* io_thread, 1376 IOThread* io_thread,
1228 net::URLRequestContextGetter* getter) { 1377 net::URLRequestContextGetter* getter) {
1229 // Empty function for unittests. 1378 // Empty function for unittests.
1230 } 1379 }
1231 1380
1232 void SimplePredictor::ShutdownOnUIThread(PrefService* user_prefs) { 1381 void SimplePredictor::ShutdownOnUIThread(PrefService* user_prefs) {
1233 SetShutdown(true); 1382 SetShutdown(true);
1234 } 1383 }
1235 1384
1236 } // namespace chrome_browser_net 1385 } // namespace chrome_browser_net
OLDNEW
« no previous file with comments | « chrome/browser/net/predictor.h ('k') | chrome/browser/net/predictor_tab_helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698