Chromium Code Reviews| 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/renderer/page_load_histograms.h" | 5 #include "chrome/renderer/page_load_histograms.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | |
| 9 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 11 #include "base/logging.h" |
| 11 #include "base/metrics/field_trial.h" | 12 #include "base/metrics/field_trial.h" |
| 12 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/string_split.h" | 15 #include "base/strings/string_split.h" |
| 15 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 16 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 18 #include "base/time/time.h" | 19 #include "base/time/time.h" |
| (...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 820 break; | 821 break; |
| 821 default: | 822 default: |
| 822 break; | 823 break; |
| 823 } | 824 } |
| 824 } | 825 } |
| 825 } | 826 } |
| 826 | 827 |
| 827 } // namespace | 828 } // namespace |
| 828 | 829 |
| 829 PageLoadHistograms::PageLoadHistograms(content::RenderView* render_view) | 830 PageLoadHistograms::PageLoadHistograms(content::RenderView* render_view) |
| 830 : content::RenderViewObserver(render_view) { | 831 : content::RenderViewObserver(render_view), |
| 832 dumped_first_layout_histograms_(false), | |
| 833 weak_factory_(this) { | |
| 831 } | 834 } |
| 832 | 835 |
| 833 void PageLoadHistograms::Dump(WebFrame* frame) { | 836 PageLoadHistograms::~PageLoadHistograms() { |
| 837 } | |
| 838 | |
| 839 bool PageLoadHistograms::ShouldDump(WebFrame* frame) { | |
| 834 // We only dump histograms for main frames. | 840 // We only dump histograms for main frames. |
| 835 // In the future, it may be interesting to tag subframes and dump them too. | 841 // In the future, it may be interesting to tag subframes and dump them too. |
| 836 if (!frame || frame->parent()) | 842 if (!frame || frame->parent()) |
| 837 return; | 843 return false; |
| 838 | 844 |
| 839 // If the main frame lives in a different process, don't do anything. | 845 // If the main frame lives in a different process, don't do anything. |
| 840 // Histogram data will be recorded by the real main frame. | 846 // Histogram data will be recorded by the real main frame. |
| 841 if (frame->isWebRemoteFrame()) | 847 if (frame->isWebRemoteFrame()) |
| 842 return; | 848 return false; |
| 843 | 849 |
| 844 // Only dump for supported schemes. | 850 // Only dump for supported schemes. |
| 845 URLPattern::SchemeMasks scheme_type = | 851 URLPattern::SchemeMasks scheme_type = |
| 846 GetSupportedSchemeType(frame->document().url()); | 852 GetSupportedSchemeType(frame->document().url()); |
| 847 if (scheme_type == 0) | 853 if (scheme_type == 0) |
| 848 return; | 854 return false; |
| 849 | 855 |
| 850 // Ignore multipart requests. | 856 // Ignore multipart requests. |
| 851 if (frame->dataSource()->response().isMultipartPayload()) | 857 if (frame->dataSource()->response().isMultipartPayload()) |
| 858 return false; | |
| 859 | |
| 860 return true; | |
| 861 } | |
| 862 | |
| 863 void PageLoadHistograms::Dump(WebFrame* frame) { | |
| 864 if (!ShouldDump(frame)) | |
| 852 return; | 865 return; |
| 853 | 866 |
| 867 URLPattern::SchemeMasks scheme_type = | |
| 868 GetSupportedSchemeType(frame->document().url()); | |
| 869 | |
| 854 DocumentState* document_state = | 870 DocumentState* document_state = |
| 855 DocumentState::FromDataSource(frame->dataSource()); | 871 DocumentState::FromDataSource(frame->dataSource()); |
| 856 | 872 |
| 857 bool data_reduction_proxy_was_used = false; | 873 bool data_reduction_proxy_was_used = false; |
| 858 data_reduction_proxy::LoFiStatus lofi_status = | 874 data_reduction_proxy::LoFiStatus lofi_status = |
| 859 data_reduction_proxy::LOFI_STATUS_TEMPORARILY_OFF; | 875 data_reduction_proxy::LOFI_STATUS_TEMPORARILY_OFF; |
| 860 if (!document_state->proxy_server().IsEmpty()) { | 876 if (!document_state->proxy_server().IsEmpty()) { |
| 861 Send(new DataReductionProxyViewHostMsg_DataReductionProxyStatus( | 877 Send(new DataReductionProxyViewHostMsg_DataReductionProxyStatus( |
| 862 document_state->proxy_server(), &data_reduction_proxy_was_used, | 878 document_state->proxy_server(), &data_reduction_proxy_was_used, |
| 863 &lofi_status)); | 879 &lofi_status)); |
| 864 } | 880 } |
| 865 | 881 |
| 866 bool came_from_websearch = | 882 bool came_from_websearch = |
| 867 IsFromGoogleSearchResult(frame->document().url(), | 883 IsFromGoogleSearchResult(frame->document().url(), |
| 868 GURL(frame->document().referrer())); | 884 GURL(frame->document().referrer())); |
| 869 int websearch_chrome_joint_experiment_id = kNoExperiment; | 885 int websearch_chrome_joint_experiment_id = kNoExperiment; |
| 870 bool is_preview = false; | 886 bool is_preview = false; |
| 871 if (came_from_websearch) { | 887 if (came_from_websearch) { |
| 872 websearch_chrome_joint_experiment_id = | 888 websearch_chrome_joint_experiment_id = |
| 873 GetQueryStringBasedExperiment(GURL(frame->document().referrer())); | 889 GetQueryStringBasedExperiment(GURL(frame->document().referrer())); |
| 874 is_preview = ViaHeaderContains(frame, "1.1 Google Instant Proxy Preview"); | 890 is_preview = ViaHeaderContains(frame, "1.1 Google Instant Proxy Preview"); |
| 875 } | 891 } |
| 876 | 892 |
| 893 MaybeDumpFirstLayoutHistograms(); | |
| 894 | |
| 877 // Metrics based on the timing information recorded for the Navigation Timing | 895 // Metrics based on the timing information recorded for the Navigation Timing |
| 878 // API - http://www.w3.org/TR/navigation-timing/. | 896 // API - http://www.w3.org/TR/navigation-timing/. |
| 879 DumpHistograms(frame->performance(), document_state, | 897 DumpHistograms(frame->performance(), document_state, |
| 880 data_reduction_proxy_was_used, lofi_status, | 898 data_reduction_proxy_was_used, lofi_status, |
| 881 came_from_websearch, websearch_chrome_joint_experiment_id, | 899 came_from_websearch, websearch_chrome_joint_experiment_id, |
| 882 is_preview, scheme_type); | 900 is_preview, scheme_type); |
| 883 | 901 |
| 884 // Old metrics based on the timing information stored in DocumentState. These | 902 // Old metrics based on the timing information stored in DocumentState. These |
| 885 // are deprecated and should go away. | 903 // are deprecated and should go away. |
| 886 DumpDeprecatedHistograms(frame->performance(), document_state, | 904 DumpDeprecatedHistograms(frame->performance(), document_state, |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 898 // the histograms we generated. Without this call, pages that don't have an | 916 // the histograms we generated. Without this call, pages that don't have an |
| 899 // on-close-handler might generate data that is lost when the renderer is | 917 // on-close-handler might generate data that is lost when the renderer is |
| 900 // shutdown abruptly (perchance because the user closed the tab). | 918 // shutdown abruptly (perchance because the user closed the tab). |
| 901 // TODO(jar) BUG=33233: This needs to be moved to a PostDelayedTask, and it | 919 // TODO(jar) BUG=33233: This needs to be moved to a PostDelayedTask, and it |
| 902 // should post when the onload is complete, so that it doesn't interfere with | 920 // should post when the onload is complete, so that it doesn't interfere with |
| 903 // the next load. | 921 // the next load. |
| 904 content::RenderThread::Get()->UpdateHistograms( | 922 content::RenderThread::Get()->UpdateHistograms( |
| 905 content::kHistogramSynchronizerReservedSequenceNumber); | 923 content::kHistogramSynchronizerReservedSequenceNumber); |
| 906 } | 924 } |
| 907 | 925 |
| 926 void PageLoadHistograms::MaybeDumpFirstLayoutHistograms() { | |
| 927 if (dumped_first_layout_histograms_) | |
| 928 return; | |
| 929 | |
| 930 const WebPerformance& performance = | |
| 931 render_view()->GetWebView()->mainFrame()->performance(); | |
| 932 Time first_layout = Time::FromDoubleT(performance.firstLayout()); | |
| 933 if (first_layout.is_null()) | |
| 934 return; | |
| 935 | |
| 936 Time navigation_start = Time::FromDoubleT(performance.navigationStart()); | |
| 937 if (!navigation_start.is_null()) | |
| 938 PLT_HISTOGRAM("PLT.PT_NavigationStartToFirstLayout", | |
| 939 first_layout - navigation_start); | |
| 940 | |
| 941 Time response_start = Time::FromDoubleT(performance.responseStart()); | |
| 942 if (!response_start.is_null()) | |
| 943 PLT_HISTOGRAM("PLT.PT_ResponseStartToFirstLayout", | |
| 944 first_layout - response_start); | |
| 945 | |
| 946 dumped_first_layout_histograms_ = true; | |
| 947 } | |
| 948 | |
| 908 void PageLoadHistograms::FrameWillClose(WebFrame* frame) { | 949 void PageLoadHistograms::FrameWillClose(WebFrame* frame) { |
| 909 Dump(frame); | 950 Dump(frame); |
| 910 } | 951 } |
| 911 | 952 |
| 912 void PageLoadHistograms::ClosePage() { | 953 void PageLoadHistograms::ClosePage() { |
| 913 // TODO(davemoore) This code should be removed once willClose() gets | 954 // TODO(davemoore) This code should be removed once willClose() gets |
| 914 // called when a page is destroyed. page_load_histograms_.Dump() is safe | 955 // called when a page is destroyed. page_load_histograms_.Dump() is safe |
| 915 // to call multiple times for the same frame, but it will simplify things. | 956 // to call multiple times for the same frame, but it will simplify things. |
| 916 Dump(render_view()->GetWebView()->mainFrame()); | 957 Dump(render_view()->GetWebView()->mainFrame()); |
| 917 } | 958 } |
| 918 | 959 |
| 960 void PageLoadHistograms::DidUpdateLayout() { | |
|
Pat Meenan
2015/07/09 19:29:27
Just a sanity check, but do you know what the over
Bryan McQuade
2015/07/09 19:35:04
Should just be a function call, which is already b
| |
| 961 // Normally, PageLoadHistograms dumps all histograms in the FrameWillClose or | |
| 962 // ClosePage callbacks, which happen as a page is being torn down. However, | |
| 963 // renderers that are killed by fast shutdown (for example, renderers closed | |
| 964 // due to the user closing a tab) don't get a chance to run these callbacks | |
| 965 // (see crbug.com/382542 for details). | |
| 966 // | |
| 967 // Longer term, we need to migrate histogram recording to happen earlier in | |
| 968 // the page load life cycle, so histograms aren't lost when tabs are | |
| 969 // closed. As a first step, we use the RenderViewObserver::DidUpdateLayout | |
| 970 // callback to log first layout histograms earlier in the page load life | |
| 971 // cycle. | |
| 972 | |
| 973 WebFrame* frame = render_view()->GetWebView()->mainFrame(); | |
| 974 if (dumped_first_layout_histograms_ || !ShouldDump(frame)) | |
|
Pat Meenan
2015/07/09 19:29:27
Maybe fast exit the dumped_first_layout_histograms
Bryan McQuade
2015/07/09 19:35:04
Good idea, done.
| |
| 975 return; | |
| 976 | |
| 977 // The canonical source for the 'first layout time' is the | |
| 978 // blink::WebPerformance object, so we need to read the first layout timestamp | |
| 979 // from that object, rather than taking our own timestamp in this | |
| 980 // callback. This DidUpdateLayout callback gets invoked in the midst of the | |
| 981 // layout process. The logic that records the first layout time in the | |
| 982 // blink::WebPerformance object may run later in the layout process, after | |
| 983 // DidUpdateLayout gets invoked. Thus, we schedule a callback to run | |
| 984 // MaybeDumpFirstLayoutHistograms asynchronously, after the layout process is | |
| 985 // complete. | |
| 986 content::RenderThread::Get()->GetTaskRunner()->PostTask( | |
| 987 FROM_HERE, | |
| 988 base::Bind(&PageLoadHistograms::MaybeDumpFirstLayoutHistograms, | |
| 989 weak_factory_.GetWeakPtr())); | |
| 990 } | |
| 991 | |
| 919 void PageLoadHistograms::LogPageLoadTime(const DocumentState* document_state, | 992 void PageLoadHistograms::LogPageLoadTime(const DocumentState* document_state, |
| 920 const WebDataSource* ds) const { | 993 const WebDataSource* ds) const { |
| 921 // Because this function gets called on every page load, | 994 // Because this function gets called on every page load, |
| 922 // take extra care to optimize it away if logging is turned off. | 995 // take extra care to optimize it away if logging is turned off. |
| 923 if (logging::LOG_INFO < logging::GetMinLogLevel()) | 996 if (logging::LOG_INFO < logging::GetMinLogLevel()) |
| 924 return; | 997 return; |
| 925 | 998 |
| 926 DCHECK(document_state); | 999 DCHECK(document_state); |
| 927 DCHECK(ds); | 1000 DCHECK(ds); |
| 928 GURL url(ds->request().url()); | 1001 GURL url(ds->request().url()); |
| 929 Time start = document_state->start_load_time(); | 1002 Time start = document_state->start_load_time(); |
| 930 Time finish = document_state->finish_load_time(); | 1003 Time finish = document_state->finish_load_time(); |
| 931 // TODO(mbelshe): should we log more stats? | 1004 // TODO(mbelshe): should we log more stats? |
| 932 VLOG(1) << "PLT: " << (finish - start).InMilliseconds() << "ms " | 1005 VLOG(1) << "PLT: " << (finish - start).InMilliseconds() << "ms " |
| 933 << url.spec(); | 1006 << url.spec(); |
| 934 } | 1007 } |
| OLD | NEW |