Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/renderer/page_load_histograms.h" | 5 #include "chrome/renderer/page_load_histograms.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/time.h" | 10 #include "base/time.h" |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 // Returns the scheme type of the given URL if its type is one for which we | 31 // Returns the scheme type of the given URL if its type is one for which we |
| 32 // dump page load histograms. Otherwise returns NULL. | 32 // dump page load histograms. Otherwise returns NULL. |
| 33 static URLPattern::SchemeMasks GetSupportedSchemeType(const GURL& url) { | 33 static URLPattern::SchemeMasks GetSupportedSchemeType(const GURL& url) { |
| 34 if (url.SchemeIs("http")) | 34 if (url.SchemeIs("http")) |
| 35 return URLPattern::SCHEME_HTTP; | 35 return URLPattern::SCHEME_HTTP; |
| 36 else if (url.SchemeIs("https")) | 36 else if (url.SchemeIs("https")) |
| 37 return URLPattern::SCHEME_HTTPS; | 37 return URLPattern::SCHEME_HTTPS; |
| 38 return static_cast<URLPattern::SchemeMasks>(0); | 38 return static_cast<URLPattern::SchemeMasks>(0); |
| 39 } | 39 } |
| 40 | 40 |
| 41 static void DumpWebTiming(const Time& navigation_start, | |
| 42 const Time& load_event_start, | |
| 43 const Time& load_event_end, | |
| 44 NavigationState* navigation_state) { | |
| 45 if (navigation_start.is_null() || | |
| 46 load_event_start.is_null() || | |
| 47 load_event_end.is_null()) | |
| 48 return; | |
| 49 | |
| 50 if (navigation_state->web_timing_histograms_recorded()) | |
| 51 return; | |
| 52 navigation_state->set_web_timing_histograms_recorded(true); | |
| 53 | |
| 54 // TODO(tonyg): There are many new details we can record, add them after the | |
| 55 // basic metrics are evaluated. | |
| 56 // TODO(simonjam): There is no way to distinguish between abandonment and | |
| 57 // intentional Javascript navigation before the load event fires. | |
| 58 PLT_HISTOGRAM("PLT.NavStartToLoadStart", load_event_start - navigation_start); | |
| 59 PLT_HISTOGRAM("PLT.NavStartToLoadEnd", load_event_end - navigation_start); | |
| 60 } | |
| 61 | |
| 41 enum MissingStartType { | 62 enum MissingStartType { |
| 42 START_MISSING = 0x1, | 63 START_MISSING = 0x1, |
| 43 COMMIT_MISSING = 0x2, | 64 COMMIT_MISSING = 0x2, |
| 44 NAV_START_MISSING = 0x4, | 65 NAV_START_MISSING = 0x4, |
| 45 MISSING_START_TYPE_MAX = 0x8 | 66 MISSING_START_TYPE_MAX = 0x8 |
| 46 }; | 67 }; |
| 47 | 68 |
| 48 enum AbandonType { | 69 enum AbandonType { |
| 49 FINISH_DOC_MISSING = 0x1, | 70 FINISH_DOC_MISSING = 0x1, |
| 50 FINISH_ALL_LOADS_MISSING = 0x2, | 71 FINISH_ALL_LOADS_MISSING = 0x2, |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 62 // We only dump histograms for main frames. | 83 // We only dump histograms for main frames. |
| 63 // In the future, it may be interesting to tag subframes and dump them too. | 84 // In the future, it may be interesting to tag subframes and dump them too. |
| 64 if (!frame || frame->parent()) | 85 if (!frame || frame->parent()) |
| 65 return; | 86 return; |
| 66 | 87 |
| 67 // Only dump for supported schemes. | 88 // Only dump for supported schemes. |
| 68 URLPattern::SchemeMasks scheme_type = GetSupportedSchemeType(frame->url()); | 89 URLPattern::SchemeMasks scheme_type = GetSupportedSchemeType(frame->url()); |
| 69 if (scheme_type == 0) | 90 if (scheme_type == 0) |
| 70 return; | 91 return; |
| 71 | 92 |
| 72 // If we've already dumped, do nothing. | |
| 73 // This simple bool works because we only dump for the main frame. | |
| 74 NavigationState* navigation_state = | 93 NavigationState* navigation_state = |
| 75 NavigationState::FromDataSource(frame->dataSource()); | 94 NavigationState::FromDataSource(frame->dataSource()); |
| 76 if (navigation_state->load_histograms_recorded()) | |
| 77 return; | |
| 78 | 95 |
| 79 // Times based on the Web Timing metrics. | 96 // Times based on the Web Timing metrics. |
| 80 // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview .html | 97 // http://www.w3.org/TR/navigation-timing/ |
| 81 // TODO(tonyg, jar): We are in the process of vetting these metrics against | 98 // TODO(tonyg, jar): We are in the process of vetting these metrics against |
| 82 // the existing ones. Once we understand any differences, we will standardize | 99 // the existing ones. Once we understand any differences, we will standardize |
| 83 // on a single set of metrics. | 100 // on a single set of metrics. |
| 84 const WebPerformance& performance = frame->performance(); | 101 const WebPerformance& performance = frame->performance(); |
| 85 Time navigation_start = Time::FromDoubleT(performance.navigationStart()); | 102 Time navigation_start = Time::FromDoubleT(performance.navigationStart()); |
| 86 Time load_event_start = Time::FromDoubleT(performance.loadEventStart()); | 103 Time load_event_start = Time::FromDoubleT(performance.loadEventStart()); |
| 87 Time load_event_end = Time::FromDoubleT(performance.loadEventEnd()); | 104 Time load_event_end = Time::FromDoubleT(performance.loadEventEnd()); |
| 105 DumpWebTiming(navigation_start, load_event_start, load_event_end, | |
| 106 navigation_state); | |
|
James Simonsen
2011/01/13 03:35:28
Line up with (.
tonyg
2011/01/13 22:14:07
Done.
| |
| 107 | |
| 108 // If we've already dumped, do nothing. | |
| 109 // This simple bool works because we only dump for the main frame. | |
| 110 if (navigation_state->load_histograms_recorded()) | |
| 111 return; | |
| 88 | 112 |
| 89 // Collect measurement times. | 113 // Collect measurement times. |
| 90 Time start = navigation_state->start_load_time(); | 114 Time start = navigation_state->start_load_time(); |
| 91 Time commit = navigation_state->commit_load_time(); | 115 Time commit = navigation_state->commit_load_time(); |
| 92 | 116 |
| 93 // TODO(tonyg, jar): We aren't certain why the start is missing sometimes, but | 117 // TODO(tonyg, jar): Start can be missing after an in-document navigation and |
| 94 // we presume it is a very premature abandonment of the page. | 118 // possibly other cases like a very premature abandonment of the page. |
| 95 // The PLT.MissingStart histogram should help us troubleshoot and then we can | 119 // The PLT.MissingStart histogram should help us troubleshoot and then we can |
| 96 // remove this. | 120 // remove this. |
| 97 int missing_start_type = 0; | 121 int missing_start_type = 0; |
| 98 missing_start_type |= start.is_null() ? START_MISSING : 0; | 122 missing_start_type |= start.is_null() ? START_MISSING : 0; |
| 99 missing_start_type |= commit.is_null() ? COMMIT_MISSING : 0; | 123 missing_start_type |= commit.is_null() ? COMMIT_MISSING : 0; |
| 100 missing_start_type |= navigation_start.is_null() ? NAV_START_MISSING : 0; | 124 missing_start_type |= navigation_start.is_null() ? NAV_START_MISSING : 0; |
| 101 UMA_HISTOGRAM_ENUMERATION("PLT.MissingStart", missing_start_type, | 125 UMA_HISTOGRAM_ENUMERATION("PLT.MissingStart", missing_start_type, |
| 102 MISSING_START_TYPE_MAX); | 126 MISSING_START_TYPE_MAX); |
| 103 if (missing_start_type) | 127 if (missing_start_type) |
| 104 return; | 128 return; |
| 105 | 129 |
| 106 // Record the new PLT times prior to the faulty abandon check below. | |
| 107 // TODO(tonyg): There are many new details we can record, add them after the | |
| 108 // basic metrics are evaluated. | |
| 109 // TODO(simonjam): There is no way to distinguish between abandonment and | |
| 110 // intentional Javascript navigation before the load event fires. | |
| 111 if (!load_event_start.is_null()) | |
| 112 PLT_HISTOGRAM("PLT.NavStartToLoadStart", | |
| 113 load_event_start - navigation_start); | |
| 114 if (!load_event_end.is_null()) | |
| 115 PLT_HISTOGRAM("PLT.NavStartToLoadEnd", load_event_end - navigation_start); | |
| 116 | |
| 117 // We properly handle null values for the next 3 variables. | 130 // We properly handle null values for the next 3 variables. |
| 118 Time request = navigation_state->request_time(); | 131 Time request = navigation_state->request_time(); |
| 119 Time first_paint = navigation_state->first_paint_time(); | 132 Time first_paint = navigation_state->first_paint_time(); |
| 120 Time first_paint_after_load = navigation_state->first_paint_after_load_time(); | 133 Time first_paint_after_load = navigation_state->first_paint_after_load_time(); |
| 121 Time finish_doc = navigation_state->finish_document_load_time(); | 134 Time finish_doc = navigation_state->finish_document_load_time(); |
| 122 Time finish_all_loads = navigation_state->finish_load_time(); | 135 Time finish_all_loads = navigation_state->finish_load_time(); |
| 123 | 136 |
| 124 // TODO(tonyg, jar): We suspect a bug in abandonment counting, this temporary | 137 // TODO(tonyg, jar): We suspect a bug in abandonment counting, this temporary |
| 125 // historgram should help us to troubleshoot. | 138 // histogram should help us to troubleshoot. |
| 126 int abandon_type = 0; | 139 int abandon_type = 0; |
| 127 abandon_type |= finish_doc.is_null() ? FINISH_DOC_MISSING : 0; | 140 abandon_type |= finish_doc.is_null() ? FINISH_DOC_MISSING : 0; |
| 128 abandon_type |= finish_all_loads.is_null() ? FINISH_ALL_LOADS_MISSING : 0; | 141 abandon_type |= finish_all_loads.is_null() ? FINISH_ALL_LOADS_MISSING : 0; |
| 129 abandon_type |= load_event_start.is_null() ? LOAD_EVENT_START_MISSING : 0; | 142 abandon_type |= load_event_start.is_null() ? LOAD_EVENT_START_MISSING : 0; |
| 130 abandon_type |= load_event_end.is_null() ? LOAD_EVENT_END_MISSING : 0; | 143 abandon_type |= load_event_end.is_null() ? LOAD_EVENT_END_MISSING : 0; |
| 131 UMA_HISTOGRAM_ENUMERATION("PLT.AbandonType", abandon_type, ABANDON_TYPE_MAX); | 144 UMA_HISTOGRAM_ENUMERATION("PLT.AbandonType", abandon_type, ABANDON_TYPE_MAX); |
| 132 | 145 |
| 133 // Handle case where user hits "stop" or "back" before loading completely. | 146 // Handle case where user hits "stop" or "back" before loading completely. |
| 134 bool abandoned_page = finish_doc.is_null(); | 147 bool abandoned_page = finish_doc.is_null(); |
| 135 if (abandoned_page) { | 148 if (abandoned_page) { |
| (...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 770 | 783 |
| 771 DCHECK(state); | 784 DCHECK(state); |
| 772 DCHECK(ds); | 785 DCHECK(ds); |
| 773 GURL url(ds->request().url()); | 786 GURL url(ds->request().url()); |
| 774 Time start = state->start_load_time(); | 787 Time start = state->start_load_time(); |
| 775 Time finish = state->finish_load_time(); | 788 Time finish = state->finish_load_time(); |
| 776 // TODO(mbelshe): should we log more stats? | 789 // TODO(mbelshe): should we log more stats? |
| 777 VLOG(1) << "PLT: " << (finish - start).InMilliseconds() << "ms " | 790 VLOG(1) << "PLT: " << (finish - start).InMilliseconds() << "ms " |
| 778 << url.spec(); | 791 << url.spec(); |
| 779 } | 792 } |
| OLD | NEW |