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

Side by Side Diff: chrome/browser/predictors/resource_prefetch_predictor.cc

Issue 632033002: Add PLT measurement to Resource Prefetching for Mobile Web (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase to fix patch error Created 6 years, 2 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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/predictors/resource_prefetch_predictor.h" 5 #include "chrome/browser/predictors/resource_prefetch_predictor.h"
6 6
7 #include <map> 7 #include <map>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 16 matching lines...) Expand all
27 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/url_constants.h" 28 #include "chrome/common/url_constants.h"
29 #include "content/public/browser/browser_thread.h" 29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/navigation_controller.h" 30 #include "content/public/browser/navigation_controller.h"
31 #include "content/public/browser/notification_service.h" 31 #include "content/public/browser/notification_service.h"
32 #include "content/public/browser/notification_source.h" 32 #include "content/public/browser/notification_source.h"
33 #include "content/public/browser/notification_types.h" 33 #include "content/public/browser/notification_types.h"
34 #include "content/public/browser/resource_request_info.h" 34 #include "content/public/browser/resource_request_info.h"
35 #include "content/public/browser/web_contents.h" 35 #include "content/public/browser/web_contents.h"
36 #include "net/base/mime_util.h" 36 #include "net/base/mime_util.h"
37 #include "net/base/network_change_notifier.h"
37 #include "net/http/http_response_headers.h" 38 #include "net/http/http_response_headers.h"
38 #include "net/url_request/url_request.h" 39 #include "net/url_request/url_request.h"
39 #include "net/url_request/url_request_context_getter.h" 40 #include "net/url_request/url_request_context_getter.h"
40 41
41 using content::BrowserThread; 42 using content::BrowserThread;
42 43
43 namespace { 44 namespace {
44 45
45 // For reporting whether a subresource is handled or not, and for what reasons. 46 // For reporting whether a subresource is handled or not, and for what reasons.
46 enum ResourceStatus { 47 enum ResourceStatus {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, 84 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1,
84 REPORTING_EVENT_COUNT = 2 85 REPORTING_EVENT_COUNT = 2
85 }; 86 };
86 87
87 void RecordNavigationEvent(NavigationEvent event) { 88 void RecordNavigationEvent(NavigationEvent event) {
88 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", 89 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent",
89 event, 90 event,
90 NAVIGATION_EVENT_COUNT); 91 NAVIGATION_EVENT_COUNT);
91 } 92 }
92 93
94 enum AdditionalConnectionType {
95 CONNECTION_CELLULAR = net::NetworkChangeNotifier::CONNECTION_LAST + 1,
Alexei Svitkine (slow) 2014/10/14 19:27:27 Nit: Indentation is wrong.
Zhen Wang 2014/10/16 18:12:22 Done.
96 CONNECTION_ALL = net::NetworkChangeNotifier::CONNECTION_LAST + 2,
97 CONNECTION_COUNT = net::NetworkChangeNotifier::CONNECTION_LAST + 3
98 };
99
93 } // namespace 100 } // namespace
94 101
95 namespace predictors { 102 namespace predictors {
96 103
97 //////////////////////////////////////////////////////////////////////////////// 104 ////////////////////////////////////////////////////////////////////////////////
98 // History lookup task. 105 // History lookup task.
99 106
100 // Used to fetch the visit count for a URL from the History database. 107 // Used to fetch the visit count for a URL from the History database.
101 class GetUrlVisitCountTask : public history::HistoryDBTask { 108 class GetUrlVisitCountTask : public history::HistoryDBTask {
102 public: 109 public:
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 525
519 NavigationMap::iterator nav_it = 526 NavigationMap::iterator nav_it =
520 inflight_navigations_.find(navigation_id); 527 inflight_navigations_.find(navigation_id);
521 if (nav_it == inflight_navigations_.end()) { 528 if (nav_it == inflight_navigations_.end()) {
522 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_UNTRACKED_URL); 529 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_UNTRACKED_URL);
523 return; 530 return;
524 } 531 }
525 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_TRACKED_URL); 532 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_TRACKED_URL);
526 533
527 // Report any stats. 534 // Report any stats.
535 base::TimeDelta plt = base::TimeTicks::Now() - navigation_id.creation_time;
536 ReportPageLoadTimeStats(plt);
528 if (prefetch_manager_.get()) { 537 if (prefetch_manager_.get()) {
529 ResultsMap::iterator results_it = results_map_.find(navigation_id); 538 ResultsMap::iterator results_it = results_map_.find(navigation_id);
530 bool have_prefetch_results = results_it != results_map_.end(); 539 bool have_prefetch_results = results_it != results_map_.end();
531 UMA_HISTOGRAM_BOOLEAN("ResourcePrefetchPredictor.HavePrefetchResults", 540 UMA_HISTOGRAM_BOOLEAN("ResourcePrefetchPredictor.HavePrefetchResults",
532 have_prefetch_results); 541 have_prefetch_results);
533 if (have_prefetch_results) { 542 if (have_prefetch_results) {
534 ReportAccuracyStats(results_it->second->key_type, 543 ReportAccuracyStats(results_it->second->key_type,
535 *(nav_it->second), 544 *(nav_it->second),
536 results_it->second->requests.get()); 545 results_it->second->requests.get());
546 ReportPageLoadTimePrefetchedStats(results_it->second->key_type, plt);
547 } else {
548 ReportPageLoadTimeNotPrefetchedStats(plt);
537 } 549 }
538 } else { 550 } else {
539 scoped_ptr<ResourcePrefetcher::RequestVector> requests( 551 scoped_ptr<ResourcePrefetcher::RequestVector> requests(
540 new ResourcePrefetcher::RequestVector); 552 new ResourcePrefetcher::RequestVector);
541 PrefetchKeyType key_type; 553 PrefetchKeyType key_type;
542 if (GetPrefetchData(navigation_id, requests.get(), &key_type)) { 554 if (GetPrefetchData(navigation_id, requests.get(), &key_type)) {
543 RecordNavigationEvent(NAVIGATION_EVENT_HAVE_PREDICTIONS_FOR_URL); 555 RecordNavigationEvent(NAVIGATION_EVENT_HAVE_PREDICTIONS_FOR_URL);
544 ReportPredictedAccuracyStats(key_type, 556 ReportPredictedAccuracyStats(key_type,
545 *(nav_it->second), 557 *(nav_it->second),
546 *requests); 558 *requests);
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 BrowserThread::PostTask( 1008 BrowserThread::PostTask(
997 BrowserThread::DB, FROM_HERE, 1009 BrowserThread::DB, FROM_HERE,
998 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, 1010 base::Bind(&ResourcePrefetchPredictorTables::UpdateData,
999 tables_, 1011 tables_,
1000 url_data, 1012 url_data,
1001 host_data)); 1013 host_data));
1002 } 1014 }
1003 } 1015 }
1004 1016
1005 //////////////////////////////////////////////////////////////////////////////// 1017 ////////////////////////////////////////////////////////////////////////////////
1006 // Accuracy measurement. 1018 // Page load time and accuracy measurement.
1019
1020 #define REPORT_PLT(name, page_load_time) \
1021 UMA_HISTOGRAM_CUSTOM_TIMES( \
1022 name, \
1023 page_load_time, \
1024 base::TimeDelta::FromMilliseconds(10), \
1025 base::TimeDelta::FromSeconds(60), \
Alexei Svitkine (slow) 2014/10/14 19:27:27 I don't think 60s is a good upper bound - there ar
Zhen Wang 2014/10/16 18:12:22 The granularity of 3 minutes with 50 buckets is to
Alexei Svitkine (slow) 2014/10/16 20:05:36 Are you aware that these histograms will have buck
Zhen Wang 2014/10/16 21:57:34 Oh, thanks for pointing it out. Using medium times
1026 100)
1027
1028 void ResourcePrefetchPredictor::ReportPageLoadTimeStats(
1029 base::TimeDelta plt) const {
1030 net::NetworkChangeNotifier::ConnectionType connection_type =
1031 net::NetworkChangeNotifier::GetConnectionType();
1032
1033 REPORT_PLT("ResourcePrefetchPredictor.PLT", plt);
1034 if (net::NetworkChangeNotifier::IsConnectionCellular(connection_type))
1035 REPORT_PLT("ResourcePrefetchPredictor.PLT.Cellular", plt);
1036 switch (connection_type) {
1037 case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
1038 REPORT_PLT("ResourcePrefetchPredictor.PLT.Ethernet", plt);
1039 break;
1040 case net::NetworkChangeNotifier::CONNECTION_WIFI:
1041 REPORT_PLT("ResourcePrefetchPredictor.PLT.WiFi", plt);
1042 break;
1043 case net::NetworkChangeNotifier::CONNECTION_2G:
1044 REPORT_PLT("ResourcePrefetchPredictor.PLT.2G", plt);
1045 break;
1046 case net::NetworkChangeNotifier::CONNECTION_3G:
1047 REPORT_PLT("ResourcePrefetchPredictor.PLT.3G", plt);
1048 break;
1049 case net::NetworkChangeNotifier::CONNECTION_4G:
1050 REPORT_PLT("ResourcePrefetchPredictor.PLT.4G", plt);
1051 break;
1052 case net::NetworkChangeNotifier::CONNECTION_NONE:
1053 REPORT_PLT("ResourcePrefetchPredictor.PLT.None", plt);
1054 break;
1055 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
1056 REPORT_PLT("ResourcePrefetchPredictor.PLT.Bluetooth", plt);
1057 break;
1058 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
1059 default:
1060 REPORT_PLT("ResourcePrefetchPredictor.PLT.Unknown", plt);
1061 break;
1062 }
1063 }
1064
1065 void ResourcePrefetchPredictor::ReportPageLoadTimePrefetchedStats(
1066 PrefetchKeyType key_type,
1067 base::TimeDelta plt) const {
1068 net::NetworkChangeNotifier::ConnectionType connection_type =
1069 net::NetworkChangeNotifier::GetConnectionType();
1070 bool on_cellular =
1071 net::NetworkChangeNotifier::IsConnectionCellular(connection_type);
1072
1073 UMA_HISTOGRAM_ENUMERATION(
1074 "ResourcePrefetchPredictor.PagePrefetchedNetworkType",
Alexei Svitkine (slow) 2014/10/14 19:27:27 Please make a helper function for this histogram w
Zhen Wang 2014/10/16 18:12:22 Done.
1075 CONNECTION_ALL,
1076 CONNECTION_COUNT);
1077 UMA_HISTOGRAM_ENUMERATION(
1078 "ResourcePrefetchPredictor.PagePrefetchedNetworkType",
1079 net::NetworkChangeNotifier::GetConnectionType(),
1080 CONNECTION_COUNT);
1081 if (on_cellular) {
1082 UMA_HISTOGRAM_ENUMERATION(
1083 "ResourcePrefetchPredictor.PagePrefetchedNetworkType",
1084 CONNECTION_CELLULAR,
1085 CONNECTION_COUNT);
1086 }
1087
1088 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched", plt);
1089 if (on_cellular)
1090 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched.Cellular", plt);
1091 switch (connection_type) {
1092 case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
1093 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched.Ethernet", plt);
1094 break;
1095 case net::NetworkChangeNotifier::CONNECTION_WIFI:
1096 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched.WiFi", plt);
1097 break;
1098 case net::NetworkChangeNotifier::CONNECTION_2G:
1099 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched.2G", plt);
1100 break;
1101 case net::NetworkChangeNotifier::CONNECTION_3G:
1102 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched.3G", plt);
1103 break;
1104 case net::NetworkChangeNotifier::CONNECTION_4G:
1105 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched.4G", plt);
1106 break;
1107 case net::NetworkChangeNotifier::CONNECTION_NONE:
1108 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched.None", plt);
1109 break;
1110 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
1111 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched.Bluetooth", plt);
1112 break;
1113 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
1114 default:
1115 REPORT_PLT(
1116 "ResourcePrefetchPredictor.PLT.PagePrefetched.Unknown", plt);
1117 break;
1118 }
1119
1120 if (key_type == PREFETCH_KEY_TYPE_HOST) {
1121 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched.Host", plt);
1122 if (on_cellular) {
1123 REPORT_PLT(
1124 "ResourcePrefetchPredictor.PLT.PagePrefetched.Host.Cellular", plt);
1125 }
1126 switch (connection_type) {
1127 case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
1128 REPORT_PLT(
1129 "ResourcePrefetchPredictor.PLT.PagePrefetched.Host.Ethernet", plt);
1130 break;
1131 case net::NetworkChangeNotifier::CONNECTION_WIFI:
1132 REPORT_PLT(
1133 "ResourcePrefetchPredictor.PLT.PagePrefetched.Host.WiFi", plt);
1134 break;
1135 case net::NetworkChangeNotifier::CONNECTION_2G:
1136 REPORT_PLT(
1137 "ResourcePrefetchPredictor.PLT.PagePrefetched.Host.2G", plt);
1138 break;
1139 case net::NetworkChangeNotifier::CONNECTION_3G:
1140 REPORT_PLT(
1141 "ResourcePrefetchPredictor.PLT.PagePrefetched.Host.3G", plt);
1142 break;
1143 case net::NetworkChangeNotifier::CONNECTION_4G:
1144 REPORT_PLT(
1145 "ResourcePrefetchPredictor.PLT.PagePrefetched.Host.4G", plt);
1146 break;
1147 case net::NetworkChangeNotifier::CONNECTION_NONE:
1148 REPORT_PLT(
1149 "ResourcePrefetchPredictor.PLT.PagePrefetched.Host.None", plt);
1150 break;
1151 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
1152 REPORT_PLT(
1153 "ResourcePrefetchPredictor.PLT.PagePrefetched.Host.Bluetooth", plt);
1154 break;
1155 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
1156 default:
1157 REPORT_PLT(
1158 "ResourcePrefetchPredictor.PLT.PagePrefetched.Host.Unknown", plt);
1159 break;
1160 }
1161 } else {
1162 REPORT_PLT("ResourcePrefetchPredictor.PLT.PagePrefetched.Url", plt);
Alexei Svitkine (slow) 2014/10/14 19:27:27 Honestly, I feel like it would be better to just u
Zhen Wang 2014/10/16 18:12:22 I originally have a more concise version (patch 1)
Alexei Svitkine (slow) 2014/10/16 20:05:36 Yeah, you can't use the macro. You need to use the
Zhen Wang 2014/10/16 21:57:34 Using self-defined RPP_HISTOGRAM_MEDIUM_TIMES now.
1163 if (on_cellular) {
1164 REPORT_PLT(
1165 "ResourcePrefetchPredictor.PLT.PagePrefetched.Url.Cellular", plt);
1166 }
1167 switch (connection_type) {
1168 case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
1169 REPORT_PLT(
1170 "ResourcePrefetchPredictor.PLT.PagePrefetched.Url.Ethernet", plt);
1171 break;
1172 case net::NetworkChangeNotifier::CONNECTION_WIFI:
1173 REPORT_PLT(
1174 "ResourcePrefetchPredictor.PLT.PagePrefetched.Url.WiFi", plt);
1175 break;
1176 case net::NetworkChangeNotifier::CONNECTION_2G:
1177 REPORT_PLT(
1178 "ResourcePrefetchPredictor.PLT.PagePrefetched.Url.2G", plt);
1179 break;
1180 case net::NetworkChangeNotifier::CONNECTION_3G:
1181 REPORT_PLT(
1182 "ResourcePrefetchPredictor.PLT.PagePrefetched.Url.3G", plt);
1183 break;
1184 case net::NetworkChangeNotifier::CONNECTION_4G:
1185 REPORT_PLT(
1186 "ResourcePrefetchPredictor.PLT.PagePrefetched.Url.4G", plt);
1187 break;
1188 case net::NetworkChangeNotifier::CONNECTION_NONE:
1189 REPORT_PLT(
1190 "ResourcePrefetchPredictor.PLT.PagePrefetched.Url.None", plt);
1191 break;
1192 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
1193 REPORT_PLT(
1194 "ResourcePrefetchPredictor.PLT.PagePrefetched.Url.Bluetooth", plt);
1195 break;
1196 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
1197 default:
1198 REPORT_PLT(
1199 "ResourcePrefetchPredictor.PLT.PagePrefetched.Url.Unknown", plt);
1200 break;
1201 }
1202 }
1203 }
1204
1205 void ResourcePrefetchPredictor::ReportPageLoadTimeNotPrefetchedStats(
1206 base::TimeDelta plt) const {
1207 net::NetworkChangeNotifier::ConnectionType connection_type =
1208 net::NetworkChangeNotifier::GetConnectionType();
1209 bool on_cellular =
1210 net::NetworkChangeNotifier::IsConnectionCellular(connection_type);
1211
1212 UMA_HISTOGRAM_ENUMERATION(
1213 "ResourcePrefetchPredictor.PageNotPrefetchedNetworkType",
1214 CONNECTION_ALL,
1215 CONNECTION_COUNT);
1216 UMA_HISTOGRAM_ENUMERATION(
1217 "ResourcePrefetchPredictor.PageNotPrefetchedNetworkType",
1218 net::NetworkChangeNotifier::GetConnectionType(),
1219 CONNECTION_COUNT);
1220 if (on_cellular) {
1221 UMA_HISTOGRAM_ENUMERATION(
1222 "ResourcePrefetchPredictor.PagePrefetchedNetworkType",
1223 CONNECTION_CELLULAR,
1224 CONNECTION_COUNT);
1225 }
1226
1227 REPORT_PLT("ResourcePrefetchPredictor.PLT.PageNotPrefetched", plt);
1228 if (on_cellular)
1229 REPORT_PLT("ResourcePrefetchPredictor.PLT.PageNotPrefetched.Cellular", plt);
1230 switch (connection_type) {
1231 case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
1232 REPORT_PLT(
1233 "ResourcePrefetchPredictor.PLT.PageNotPrefetched.Ethernet", plt);
1234 break;
1235 case net::NetworkChangeNotifier::CONNECTION_WIFI:
1236 REPORT_PLT("ResourcePrefetchPredictor.PLT.PageNotPrefetched.WiFi", plt);
1237 break;
1238 case net::NetworkChangeNotifier::CONNECTION_2G:
1239 REPORT_PLT("ResourcePrefetchPredictor.PLT.PageNotPrefetched.2G", plt);
1240 break;
1241 case net::NetworkChangeNotifier::CONNECTION_3G:
1242 REPORT_PLT("ResourcePrefetchPredictor.PLT.PageNotPrefetched.3G", plt);
1243 break;
1244 case net::NetworkChangeNotifier::CONNECTION_4G:
1245 REPORT_PLT("ResourcePrefetchPredictor.PLT.PageNotPrefetched.4G", plt);
1246 break;
1247 case net::NetworkChangeNotifier::CONNECTION_NONE:
1248 REPORT_PLT("ResourcePrefetchPredictor.PLT.PageNotPrefetched.None", plt);
1249 break;
1250 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
1251 REPORT_PLT(
1252 "ResourcePrefetchPredictor.PLT.PageNotPrefetched.Bluetooth", plt);
1253 break;
1254 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
1255 default:
1256 REPORT_PLT(
1257 "ResourcePrefetchPredictor.PLT.PageNotPrefetched.Unknown", plt);
1258 break;
1259 }
1260 }
1007 1261
1008 void ResourcePrefetchPredictor::ReportAccuracyStats( 1262 void ResourcePrefetchPredictor::ReportAccuracyStats(
1009 PrefetchKeyType key_type, 1263 PrefetchKeyType key_type,
1010 const std::vector<URLRequestSummary>& actual, 1264 const std::vector<URLRequestSummary>& actual,
1011 ResourcePrefetcher::RequestVector* prefetched) const { 1265 ResourcePrefetcher::RequestVector* prefetched) const {
1012 // Annotate the results. 1266 // Annotate the results.
1013 std::map<GURL, bool> actual_resources; 1267 std::map<GURL, bool> actual_resources;
1014 for (std::vector<URLRequestSummary>::const_iterator it = actual.begin(); 1268 for (std::vector<URLRequestSummary>::const_iterator it = actual.begin();
1015 it != actual.end(); ++it) { 1269 it != actual.end(); ++it) {
1016 actual_resources[it->resource_url] = it->was_cached; 1270 actual_resources[it->resource_url] = it->was_cached;
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 RPP_PREDICTED_HISTOGRAM_PERCENTAGE( 1469 RPP_PREDICTED_HISTOGRAM_PERCENTAGE(
1216 "PrefetchFromNetworkPercentOfTotalFromNetwork", 1470 "PrefetchFromNetworkPercentOfTotalFromNetwork",
1217 prefetch_network * 100.0 / total_resources_fetched_from_network); 1471 prefetch_network * 100.0 / total_resources_fetched_from_network);
1218 } 1472 }
1219 1473
1220 #undef RPP_PREDICTED_HISTOGRAM_PERCENTAGE 1474 #undef RPP_PREDICTED_HISTOGRAM_PERCENTAGE
1221 #undef RPP_PREDICTED_HISTOGRAM_COUNTS 1475 #undef RPP_PREDICTED_HISTOGRAM_COUNTS
1222 } 1476 }
1223 1477
1224 } // namespace predictors 1478 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698