Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / predictors / resource_prefetch_common.cc
blobd558eab5f0f7e4708c1f126f877a4edc3676167c
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/predictors/resource_prefetch_common.h"
7 #include <stdlib.h>
9 #include "base/command_line.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/string_split.h"
13 #include "chrome/browser/net/prediction_options.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/pref_names.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/web_contents.h"
22 using base::FieldTrialList;
23 using std::string;
24 using std::vector;
26 namespace predictors {
28 const char kSpeculativePrefetchingTrialName[] =
29 "SpeculativeResourcePrefetching";
32 * SpeculativeResourcePrefetching is a field trial, and its value must have the
33 * following format: key1=value1:key2=value2:key3=value3
34 * e.g. "Prefetching=Enabled:Predictor=Url:Confidence=High"
35 * The function below extracts the value corresponding to a key provided from
36 * the SpeculativeResourcePrefetching field trial.
38 string GetFiledTrialSpecValue(string key) {
39 vector<string> elements;
40 base::SplitString(
41 FieldTrialList::FindFullName(kSpeculativePrefetchingTrialName),
42 ':',
43 &elements);
44 for (int i = 0; i < static_cast<int>(elements.size()); i++) {
45 vector<string> key_value;
46 base::SplitString(elements[i], '=', &key_value);
47 if (key_value.size() == 2 && key_value[0] == key)
48 return key_value[1];
50 return string();
53 bool IsSpeculativeResourcePrefetchingEnabled(
54 Profile* profile,
55 ResourcePrefetchPredictorConfig* config) {
56 DCHECK(config);
58 // Off the record - disabled.
59 if (!profile || profile->IsOffTheRecord())
60 return false;
62 // Enabled by command line switch. The config has the default params already
63 // set. The command line with just enable them with the default params.
64 if (CommandLine::ForCurrentProcess()->HasSwitch(
65 switches::kSpeculativeResourcePrefetching)) {
66 const std::string value =
67 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
68 switches::kSpeculativeResourcePrefetching);
70 if (value == switches::kSpeculativeResourcePrefetchingDisabled) {
71 return false;
72 } else if (value == switches::kSpeculativeResourcePrefetchingLearning) {
73 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
74 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
75 return true;
76 } else if (value == switches::kSpeculativeResourcePrefetchingEnabled) {
77 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
78 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
79 config->mode |= ResourcePrefetchPredictorConfig::URL_PREFETCHING;
80 config->mode |= ResourcePrefetchPredictorConfig::HOST_PRFETCHING;
81 return true;
85 // Disable if no field trial is specified.
86 std::string trial = base::FieldTrialList::FindFullName(
87 kSpeculativePrefetchingTrialName);
88 if (trial.empty())
89 return false;
91 // Enabled by field trial.
92 std::string spec_prefetching = GetFiledTrialSpecValue("Prefetching");
93 std::string spec_predictor = GetFiledTrialSpecValue("Predictor");
94 std::string spec_confidence = GetFiledTrialSpecValue("Confidence");
95 std::string spec_more_resources = GetFiledTrialSpecValue("MoreResources");
96 std::string spec_small_db = GetFiledTrialSpecValue("SmallDB");
98 if (spec_prefetching == "Learning") {
99 if (spec_predictor == "Url") {
100 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
101 } else if (spec_predictor == "Host") {
102 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
103 } else {
104 // Default: both Url and Host
105 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
106 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
108 } else if (spec_prefetching == "Enabled") {
109 if (spec_predictor == "Url") {
110 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
111 config->mode |= ResourcePrefetchPredictorConfig::URL_PREFETCHING;
112 } else if (spec_predictor == "Host") {
113 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
114 config->mode |= ResourcePrefetchPredictorConfig::HOST_PRFETCHING;
115 } else {
116 // Default: both Url and Host
117 config->mode |= ResourcePrefetchPredictorConfig::URL_LEARNING;
118 config->mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING;
119 config->mode |= ResourcePrefetchPredictorConfig::URL_PREFETCHING;
120 config->mode |= ResourcePrefetchPredictorConfig::HOST_PRFETCHING;
122 } else {
123 // Default: spec_prefetching == "Disabled"
124 return false;
127 if (spec_confidence == "Low") {
128 config->min_url_visit_count = 1;
129 config->min_resource_confidence_to_trigger_prefetch = 0.5f;
130 config->min_resource_hits_to_trigger_prefetch = 1;
131 } else if (spec_confidence == "High") {
132 config->min_url_visit_count = 3;
133 config->min_resource_confidence_to_trigger_prefetch = 0.9f;
134 config->min_resource_hits_to_trigger_prefetch = 3;
135 } else {
136 // default
137 config->min_url_visit_count = 2;
138 config->min_resource_confidence_to_trigger_prefetch = 0.7f;
139 config->min_resource_hits_to_trigger_prefetch = 2;
142 if (spec_more_resources == "Enabled") {
143 config->max_resources_per_entry = 100;
146 if (spec_small_db == "Enabled") {
147 config->max_urls_to_track = 200;
148 config->max_hosts_to_track = 100;
151 return true;
154 NavigationID::NavigationID()
155 : render_process_id(-1),
156 render_frame_id(-1) {
159 NavigationID::NavigationID(const NavigationID& other)
160 : render_process_id(other.render_process_id),
161 render_frame_id(other.render_frame_id),
162 main_frame_url(other.main_frame_url),
163 creation_time(other.creation_time) {
166 NavigationID::NavigationID(content::WebContents* web_contents)
167 : render_process_id(web_contents->GetRenderProcessHost()->GetID()),
168 render_frame_id(web_contents->GetRenderViewHost()->GetRoutingID()),
169 main_frame_url(web_contents->GetURL()) {
172 bool NavigationID::is_valid() const {
173 return render_process_id != -1 && render_frame_id != -1 &&
174 !main_frame_url.is_empty();
177 bool NavigationID::operator<(const NavigationID& rhs) const {
178 DCHECK(is_valid() && rhs.is_valid());
179 if (render_process_id != rhs.render_process_id)
180 return render_process_id < rhs.render_process_id;
181 else if (render_frame_id != rhs.render_frame_id)
182 return render_frame_id < rhs.render_frame_id;
183 else
184 return main_frame_url < rhs.main_frame_url;
187 bool NavigationID::operator==(const NavigationID& rhs) const {
188 DCHECK(is_valid() && rhs.is_valid());
189 return IsSameRenderer(rhs) && main_frame_url == rhs.main_frame_url;
192 bool NavigationID::IsSameRenderer(const NavigationID& other) const {
193 DCHECK(is_valid() && other.is_valid());
194 return render_process_id == other.render_process_id &&
195 render_frame_id == other.render_frame_id;
198 ResourcePrefetchPredictorConfig::ResourcePrefetchPredictorConfig()
199 : mode(0),
200 max_navigation_lifetime_seconds(60),
201 max_urls_to_track(500),
202 max_hosts_to_track(200),
203 min_url_visit_count(2),
204 max_resources_per_entry(50),
205 max_consecutive_misses(3),
206 min_resource_confidence_to_trigger_prefetch(0.7f),
207 min_resource_hits_to_trigger_prefetch(2),
208 max_prefetches_inflight_per_navigation(24),
209 max_prefetches_inflight_per_host_per_navigation(3) {
212 ResourcePrefetchPredictorConfig::~ResourcePrefetchPredictorConfig() {
215 bool ResourcePrefetchPredictorConfig::IsLearningEnabled() const {
216 return IsURLLearningEnabled() || IsHostLearningEnabled();
219 bool ResourcePrefetchPredictorConfig::IsPrefetchingEnabled(
220 Profile* profile) const {
221 return IsURLPrefetchingEnabled(profile) || IsHostPrefetchingEnabled(profile);
224 bool ResourcePrefetchPredictorConfig::IsURLLearningEnabled() const {
225 return (mode & URL_LEARNING) > 0;
228 bool ResourcePrefetchPredictorConfig::IsHostLearningEnabled() const {
229 return (mode & HOST_LEARNING) > 0;
232 bool ResourcePrefetchPredictorConfig::IsURLPrefetchingEnabled(
233 Profile* profile) const {
234 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
235 if (!profile || !profile->GetPrefs() ||
236 !chrome_browser_net::CanPrefetchAndPrerenderUI(profile->GetPrefs())) {
237 return false;
239 return (mode & URL_PREFETCHING) > 0;
242 bool ResourcePrefetchPredictorConfig::IsHostPrefetchingEnabled(
243 Profile* profile) const {
244 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
245 if (!profile || !profile->GetPrefs() ||
246 !chrome_browser_net::CanPrefetchAndPrerenderUI(profile->GetPrefs())) {
247 return false;
249 return (mode & HOST_PRFETCHING) > 0;
252 bool ResourcePrefetchPredictorConfig::IsLowConfidenceForTest() const {
253 return min_url_visit_count == 1 &&
254 std::abs(min_resource_confidence_to_trigger_prefetch - 0.5f) < 1e-6 &&
255 min_resource_hits_to_trigger_prefetch == 1;
258 bool ResourcePrefetchPredictorConfig::IsHighConfidenceForTest() const {
259 return min_url_visit_count == 3 &&
260 std::abs(min_resource_confidence_to_trigger_prefetch - 0.9f) < 1e-6 &&
261 min_resource_hits_to_trigger_prefetch == 3;
264 bool ResourcePrefetchPredictorConfig::IsMoreResourcesEnabledForTest() const {
265 return max_resources_per_entry == 100;
268 bool ResourcePrefetchPredictorConfig::IsSmallDBEnabledForTest() const {
269 return max_urls_to_track == 200 && max_hosts_to_track == 100;
272 } // namespace predictors