| OLD | NEW |
| 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/prerender/prerender_histograms.h" | 5 #include "chrome/browser/prerender/prerender_histograms.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 REDIRECT = 1 << 1, | 29 REDIRECT = 1 << 1, |
| 30 MAIN_RESOURCE = 1 << 2, | 30 MAIN_RESOURCE = 1 << 2, |
| 31 NO_STATE_PREFETCH_RESPONSE_TYPE_COUNT = 1 << 3 | 31 NO_STATE_PREFETCH_RESPONSE_TYPE_COUNT = 1 << 3 |
| 32 }; | 32 }; |
| 33 | 33 |
| 34 int GetResourceType(bool is_main_resource, bool is_redirect, bool is_no_store) { | 34 int GetResourceType(bool is_main_resource, bool is_redirect, bool is_no_store) { |
| 35 return (is_no_store * NO_STORE) + (is_redirect * REDIRECT) + | 35 return (is_no_store * NO_STORE) + (is_redirect * REDIRECT) + |
| 36 (is_main_resource * MAIN_RESOURCE); | 36 (is_main_resource * MAIN_RESOURCE); |
| 37 } | 37 } |
| 38 | 38 |
| 39 // Time window for which we will record windowed PLTs from the last observed | |
| 40 // link rel=prefetch tag. This is not intended to be the same as the prerender | |
| 41 // ttl, it's just intended to be a window during which a prerender has likely | |
| 42 // affected performance. | |
| 43 const int kWindowDurationSeconds = 30; | |
| 44 | |
| 45 std::string ComposeHistogramName(const std::string& prefix_type, | 39 std::string ComposeHistogramName(const std::string& prefix_type, |
| 46 const std::string& name) { | 40 const std::string& name) { |
| 47 if (prefix_type.empty()) | 41 if (prefix_type.empty()) |
| 48 return std::string("Prerender.") + name; | 42 return std::string("Prerender.") + name; |
| 49 return std::string("Prerender.") + prefix_type + std::string("_") + name; | 43 return std::string("Prerender.") + prefix_type + std::string("_") + name; |
| 50 } | 44 } |
| 51 | 45 |
| 52 std::string GetHistogramName(Origin origin, const std::string& name) { | 46 std::string GetHistogramName(Origin origin, const std::string& name) { |
| 53 switch (origin) { | 47 switch (origin) { |
| 54 case ORIGIN_OMNIBOX: | 48 case ORIGIN_OMNIBOX: |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 HISTOGRAM; \ | 114 HISTOGRAM; \ |
| 121 } else if (origin == ORIGIN_EXTERNAL_REQUEST_FORCED_PRERENDER) { \ | 115 } else if (origin == ORIGIN_EXTERNAL_REQUEST_FORCED_PRERENDER) { \ |
| 122 HISTOGRAM; \ | 116 HISTOGRAM; \ |
| 123 } else if (origin == ORIGIN_OFFLINE) { \ | 117 } else if (origin == ORIGIN_OFFLINE) { \ |
| 124 HISTOGRAM; \ | 118 HISTOGRAM; \ |
| 125 } else { \ | 119 } else { \ |
| 126 HISTOGRAM; \ | 120 HISTOGRAM; \ |
| 127 } \ | 121 } \ |
| 128 } while (0) | 122 } while (0) |
| 129 | 123 |
| 130 PrerenderHistograms::PrerenderHistograms() | 124 PrerenderHistograms::PrerenderHistograms() {} |
| 131 : seen_any_pageload_(true), seen_pageload_started_after_prerender_(true) {} | |
| 132 | |
| 133 void PrerenderHistograms::RecordPrerender() { | |
| 134 // If we observe multiple tags within the 30 second window, we will still | |
| 135 // reset the window to begin at the most recent occurrence, so that we will | |
| 136 // always be in a window in the 30 seconds from each occurrence. | |
| 137 last_prerender_seen_time_ = GetCurrentTimeTicks(); | |
| 138 seen_any_pageload_ = false; | |
| 139 seen_pageload_started_after_prerender_ = false; | |
| 140 } | |
| 141 | 125 |
| 142 void PrerenderHistograms::RecordPrerenderStarted(Origin origin) const { | 126 void PrerenderHistograms::RecordPrerenderStarted(Origin origin) const { |
| 143 if (OriginIsOmnibox(origin)) { | 127 if (OriginIsOmnibox(origin)) { |
| 144 UMA_HISTOGRAM_ENUMERATION( | 128 UMA_HISTOGRAM_ENUMERATION( |
| 145 "Prerender.OmniboxPrerenderCount", 1, 2); | 129 "Prerender.OmniboxPrerenderCount", 1, 2); |
| 146 } | 130 } |
| 147 } | 131 } |
| 148 | 132 |
| 149 void PrerenderHistograms::RecordConcurrency(size_t prerender_count) const { | |
| 150 static const size_t kMaxRecordableConcurrency = 20; | |
| 151 DCHECK_GE(kMaxRecordableConcurrency, Config().max_link_concurrency); | |
| 152 UMA_HISTOGRAM_ENUMERATION( | |
| 153 base::StringPrintf("Prerender.PrerenderCountOf%" PRIuS "Max", | |
| 154 kMaxRecordableConcurrency), | |
| 155 prerender_count, kMaxRecordableConcurrency + 1); | |
| 156 } | |
| 157 | |
| 158 void PrerenderHistograms::RecordUsedPrerender(Origin origin) const { | 133 void PrerenderHistograms::RecordUsedPrerender(Origin origin) const { |
| 159 if (OriginIsOmnibox(origin)) { | 134 if (OriginIsOmnibox(origin)) { |
| 160 UMA_HISTOGRAM_ENUMERATION( | 135 UMA_HISTOGRAM_ENUMERATION( |
| 161 "Prerender.OmniboxNavigationsUsedPrerenderCount", 1, 2); | 136 "Prerender.OmniboxNavigationsUsedPrerenderCount", 1, 2); |
| 162 } | 137 } |
| 163 } | 138 } |
| 164 | 139 |
| 165 void PrerenderHistograms::RecordTimeSinceLastRecentVisit( | 140 void PrerenderHistograms::RecordTimeSinceLastRecentVisit( |
| 166 Origin origin, | 141 Origin origin, |
| 167 base::TimeDelta delta) const { | 142 base::TimeDelta delta) const { |
| 168 PREFIXED_HISTOGRAM( | 143 PREFIXED_HISTOGRAM( |
| 169 "TimeSinceLastRecentVisit", origin, | 144 "TimeSinceLastRecentVisit", origin, |
| 170 UMA_HISTOGRAM_TIMES(name, delta)); | 145 UMA_HISTOGRAM_TIMES(name, delta)); |
| 171 } | 146 } |
| 172 | 147 |
| 173 base::TimeTicks PrerenderHistograms::GetCurrentTimeTicks() const { | |
| 174 return base::TimeTicks::Now(); | |
| 175 } | |
| 176 | |
| 177 // Helper macro for histograms. | |
| 178 #define RECORD_PLT(tag, perceived_page_load_time) \ | |
| 179 PREFIXED_HISTOGRAM( \ | |
| 180 tag, origin, \ | |
| 181 UMA_HISTOGRAM_CUSTOM_TIMES( \ | |
| 182 name, \ | |
| 183 perceived_page_load_time, \ | |
| 184 base::TimeDelta::FromMilliseconds(10), \ | |
| 185 base::TimeDelta::FromSeconds(60), \ | |
| 186 100)) | |
| 187 | |
| 188 // Summary of all histograms Perceived PLT histograms: | |
| 189 // (all prefixed PerceivedPLT) | |
| 190 // PerceivedPLT -- Perceived Pageloadtimes (PPLT) for all pages in the group. | |
| 191 // ...Windowed -- PPLT for pages in the 30s after a prerender is created. | |
| 192 // ...FirstAfterMiss -- First page to finish loading after a prerender, which | |
| 193 // is different from the page that was prerendered. | |
| 194 // ...FirstAfterMissNonOverlapping -- Same as FirstAfterMiss, but only | |
| 195 // triggering for the first page to finish after the prerender that also started | |
| 196 // after the prerender started. | |
| 197 // ...FirstAfterMissBoth -- pages meeting | |
| 198 // FirstAfterMiss AND FirstAfterMissNonOverlapping | |
| 199 // ...FirstAfterMissAnyOnly -- pages meeting | |
| 200 // FirstAfterMiss but NOT FirstAfterMissNonOverlapping | |
| 201 // ..FirstAfterMissNonOverlappingOnly -- pages meeting | |
| 202 // FirstAfterMissNonOverlapping but NOT FirstAfterMiss | |
| 203 | |
| 204 void PrerenderHistograms::RecordPerceivedPageLoadTime( | |
| 205 Origin origin, | |
| 206 base::TimeDelta perceived_page_load_time, | |
| 207 NavigationType navigation_type, | |
| 208 const GURL& url) { | |
| 209 if (!url.SchemeIsHTTPOrHTTPS()) | |
| 210 return; | |
| 211 bool within_window = WithinWindow(); | |
| 212 bool is_google_url = | |
| 213 google_util::IsGoogleDomainUrl(url, google_util::DISALLOW_SUBDOMAIN, | |
| 214 google_util::ALLOW_NON_STANDARD_PORTS); | |
| 215 RECORD_PLT("PerceivedPLT", perceived_page_load_time); | |
| 216 if (within_window) | |
| 217 RECORD_PLT("PerceivedPLTWindowed", perceived_page_load_time); | |
| 218 if (navigation_type != NAVIGATION_TYPE_NORMAL) { | |
| 219 DCHECK(navigation_type == NAVIGATION_TYPE_PRERENDERED); | |
| 220 seen_any_pageload_ = true; | |
| 221 seen_pageload_started_after_prerender_ = true; | |
| 222 } else if (within_window) { | |
| 223 if (!is_google_url) { | |
| 224 bool recorded_any = false; | |
| 225 bool recorded_non_overlapping = false; | |
| 226 if (!seen_any_pageload_) { | |
| 227 seen_any_pageload_ = true; | |
| 228 RECORD_PLT("PerceivedPLTFirstAfterMiss", perceived_page_load_time); | |
| 229 recorded_any = true; | |
| 230 } | |
| 231 if (!seen_pageload_started_after_prerender_ && | |
| 232 perceived_page_load_time <= GetTimeSinceLastPrerender()) { | |
| 233 seen_pageload_started_after_prerender_ = true; | |
| 234 RECORD_PLT("PerceivedPLTFirstAfterMissNonOverlapping", | |
| 235 perceived_page_load_time); | |
| 236 recorded_non_overlapping = true; | |
| 237 } | |
| 238 if (recorded_any || recorded_non_overlapping) { | |
| 239 if (recorded_any && recorded_non_overlapping) { | |
| 240 RECORD_PLT("PerceivedPLTFirstAfterMissBoth", | |
| 241 perceived_page_load_time); | |
| 242 } else if (recorded_any) { | |
| 243 RECORD_PLT("PerceivedPLTFirstAfterMissAnyOnly", | |
| 244 perceived_page_load_time); | |
| 245 } else if (recorded_non_overlapping) { | |
| 246 RECORD_PLT("PerceivedPLTFirstAfterMissNonOverlappingOnly", | |
| 247 perceived_page_load_time); | |
| 248 } | |
| 249 } | |
| 250 } | |
| 251 } | |
| 252 } | |
| 253 | |
| 254 void PrerenderHistograms::RecordPerceivedFirstContentfulPaintStatus( | 148 void PrerenderHistograms::RecordPerceivedFirstContentfulPaintStatus( |
| 255 Origin origin, | 149 Origin origin, |
| 256 bool successful, | 150 bool successful, |
| 257 bool was_hidden) { | 151 bool was_hidden) const { |
| 258 base::UmaHistogramBoolean(GetHistogramName(origin, "PerceivedTTFCPRecorded") + | 152 base::UmaHistogramBoolean(GetHistogramName(origin, "PerceivedTTFCPRecorded") + |
| 259 FirstContentfulPaintHiddenName(was_hidden), | 153 FirstContentfulPaintHiddenName(was_hidden), |
| 260 successful); | 154 successful); |
| 261 } | 155 } |
| 262 | 156 |
| 263 void PrerenderHistograms::RecordPageLoadTimeNotSwappedIn( | |
| 264 Origin origin, | |
| 265 base::TimeDelta page_load_time, | |
| 266 const GURL& url) const { | |
| 267 // If the URL to be prerendered is not a http[s] URL, or is a Google URL, | |
| 268 // do not record. | |
| 269 if (!url.SchemeIsHTTPOrHTTPS() || | |
| 270 google_util::IsGoogleDomainUrl(url, google_util::DISALLOW_SUBDOMAIN, | |
| 271 google_util::ALLOW_NON_STANDARD_PORTS)) { | |
| 272 return; | |
| 273 } | |
| 274 RECORD_PLT("PrerenderNotSwappedInPLT", page_load_time); | |
| 275 } | |
| 276 | |
| 277 void PrerenderHistograms::RecordPercentLoadDoneAtSwapin(Origin origin, | 157 void PrerenderHistograms::RecordPercentLoadDoneAtSwapin(Origin origin, |
| 278 double fraction) const { | 158 double fraction) const { |
| 279 if (fraction < 0.0 || fraction > 1.0) | 159 if (fraction < 0.0 || fraction > 1.0) |
| 280 return; | 160 return; |
| 281 int percentage = static_cast<int>(fraction * 100); | 161 int percentage = static_cast<int>(fraction * 100); |
| 282 if (percentage < 0 || percentage > 100) | 162 if (percentage < 0 || percentage > 100) |
| 283 return; | 163 return; |
| 284 PREFIXED_HISTOGRAM("PercentLoadDoneAtSwapin", | 164 PREFIXED_HISTOGRAM("PercentLoadDoneAtSwapin", |
| 285 origin, UMA_HISTOGRAM_PERCENTAGE(name, percentage)); | 165 origin, UMA_HISTOGRAM_PERCENTAGE(name, percentage)); |
| 286 } | 166 } |
| 287 | 167 |
| 288 base::TimeDelta PrerenderHistograms::GetTimeSinceLastPrerender() const { | |
| 289 return base::TimeTicks::Now() - last_prerender_seen_time_; | |
| 290 } | |
| 291 | |
| 292 bool PrerenderHistograms::WithinWindow() const { | |
| 293 if (last_prerender_seen_time_.is_null()) | |
| 294 return false; | |
| 295 return GetTimeSinceLastPrerender() <= | |
| 296 base::TimeDelta::FromSeconds(kWindowDurationSeconds); | |
| 297 } | |
| 298 | |
| 299 void PrerenderHistograms::RecordTimeUntilUsed( | 168 void PrerenderHistograms::RecordTimeUntilUsed( |
| 300 Origin origin, | 169 Origin origin, |
| 301 base::TimeDelta time_until_used) const { | 170 base::TimeDelta time_until_used) const { |
| 302 PREFIXED_HISTOGRAM( | 171 PREFIXED_HISTOGRAM( |
| 303 "TimeUntilUsed2", origin, | 172 "TimeUntilUsed2", origin, |
| 304 UMA_HISTOGRAM_CUSTOM_TIMES( | 173 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 305 name, | 174 name, |
| 306 time_until_used, | 175 time_until_used, |
| 307 base::TimeDelta::FromMilliseconds(10), | 176 base::TimeDelta::FromMilliseconds(10), |
| 308 base::TimeDelta::FromMinutes(30), | 177 base::TimeDelta::FromMinutes(30), |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 std::string histogram_name = GetHistogramName(origin, histogram_base_name); | 272 std::string histogram_name = GetHistogramName(origin, histogram_base_name); |
| 404 base::UmaHistogramExactLinear(histogram_name, redirect_count, | 273 base::UmaHistogramExactLinear(histogram_name, redirect_count, |
| 405 kMaxRedirectCount); | 274 kMaxRedirectCount); |
| 406 } | 275 } |
| 407 | 276 |
| 408 void PrerenderHistograms::RecordPrefetchFirstContentfulPaintTime( | 277 void PrerenderHistograms::RecordPrefetchFirstContentfulPaintTime( |
| 409 Origin origin, | 278 Origin origin, |
| 410 bool is_no_store, | 279 bool is_no_store, |
| 411 bool was_hidden, | 280 bool was_hidden, |
| 412 base::TimeDelta time, | 281 base::TimeDelta time, |
| 413 base::TimeDelta prefetch_age) { | 282 base::TimeDelta prefetch_age) const { |
| 414 DCHECK(thread_checker_.CalledOnValidThread()); | 283 DCHECK(thread_checker_.CalledOnValidThread()); |
| 415 | 284 |
| 416 if (!prefetch_age.is_zero()) { | 285 if (!prefetch_age.is_zero()) { |
| 417 DCHECK_NE(origin, ORIGIN_NONE); | 286 DCHECK_NE(origin, ORIGIN_NONE); |
| 418 base::UmaHistogramCustomTimes(GetHistogramName(origin, "PrefetchAge"), | 287 base::UmaHistogramCustomTimes(GetHistogramName(origin, "PrefetchAge"), |
| 419 prefetch_age, | 288 prefetch_age, |
| 420 base::TimeDelta::FromMilliseconds(10), | 289 base::TimeDelta::FromMilliseconds(10), |
| 421 base::TimeDelta::FromMinutes(30), 50); | 290 base::TimeDelta::FromMinutes(30), 50); |
| 422 } | 291 } |
| 423 | 292 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 434 histogram_base_name += is_no_store ? ".NoStore" : ".Cacheable"; | 303 histogram_base_name += is_no_store ? ".NoStore" : ".Cacheable"; |
| 435 histogram_base_name += FirstContentfulPaintHiddenName(was_hidden); | 304 histogram_base_name += FirstContentfulPaintHiddenName(was_hidden); |
| 436 std::string histogram_name = GetHistogramName(origin, histogram_base_name); | 305 std::string histogram_name = GetHistogramName(origin, histogram_base_name); |
| 437 | 306 |
| 438 base::UmaHistogramCustomTimes(histogram_name, time, | 307 base::UmaHistogramCustomTimes(histogram_name, time, |
| 439 base::TimeDelta::FromMilliseconds(10), | 308 base::TimeDelta::FromMilliseconds(10), |
| 440 base::TimeDelta::FromMinutes(2), 50); | 309 base::TimeDelta::FromMinutes(2), 50); |
| 441 } | 310 } |
| 442 | 311 |
| 443 } // namespace prerender | 312 } // namespace prerender |
| OLD | NEW |