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

Side by Side Diff: base/metrics/histogram.cc

Issue 10703037: Move StatisticsRecorder out of histogram.cc/h for further refactoring. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « base/metrics/histogram.h ('k') | base/metrics/histogram_snapshot_manager.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // Histogram is an object that aggregates statistics, and can summarize them in 5 // Histogram is an object that aggregates statistics, and can summarize them in
6 // various forms, including ASCII graphical, HTML, and numerically (as a 6 // various forms, including ASCII graphical, HTML, and numerically (as a
7 // vector of numbers corresponding to each of the aggregating buckets). 7 // vector of numbers corresponding to each of the aggregating buckets).
8 // See header file for details and examples. 8 // See header file for details and examples.
9 9
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 11
12 #include <math.h> 12 #include <math.h>
13 13
14 #include <algorithm> 14 #include <algorithm>
15 #include <string> 15 #include <string>
16 16
17 #include "base/debug/leak_annotations.h"
18 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/metrics/statistics_recorder.h"
19 #include "base/pickle.h" 19 #include "base/pickle.h"
20 #include "base/stringprintf.h" 20 #include "base/stringprintf.h"
21 #include "base/synchronization/lock.h" 21 #include "base/synchronization/lock.h"
22 22
23 namespace base { 23 namespace base {
24 24
25 // Static table of checksums for all possible 8 bit bytes. 25 // Static table of checksums for all possible 8 bit bytes.
26 const uint32 Histogram::kCrcTable[256] = {0x0, 0x77073096L, 0xee0e612cL, 26 const uint32 Histogram::kCrcTable[256] = {0x0, 0x77073096L, 0xee0e612cL,
27 0x990951baL, 0x76dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0xedb8832L, 27 0x990951baL, 0x76dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0xedb8832L,
28 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x9b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 28 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x9b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 67 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL,
68 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 68 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
69 0x2d02ef8dL, 69 0x2d02ef8dL,
70 }; 70 };
71 71
72 typedef Histogram::Count Count; 72 typedef Histogram::Count Count;
73 73
74 // static 74 // static
75 const size_t Histogram::kBucketCount_MAX = 16384u; 75 const size_t Histogram::kBucketCount_MAX = 16384u;
76 76
77 // Collect the number of histograms created.
78 static uint32 number_of_histograms_ = 0;
79 // Collect the number of vectors saved because of caching ranges.
80 static uint32 number_of_vectors_saved_ = 0;
81 // Collect the number of ranges_ elements saved because of caching ranges.
82 static size_t saved_ranges_size_ = 0;
83
84 Histogram* Histogram::FactoryGet(const std::string& name, 77 Histogram* Histogram::FactoryGet(const std::string& name,
85 Sample minimum, 78 Sample minimum,
86 Sample maximum, 79 Sample maximum,
87 size_t bucket_count, 80 size_t bucket_count,
88 Flags flags) { 81 Flags flags) {
89 Histogram* histogram(NULL); 82 Histogram* histogram(NULL);
90 83
91 // Defensive code. 84 // Defensive code.
92 if (minimum < 1) 85 if (minimum < 1)
93 minimum = 1; 86 minimum = 1;
(...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 DCHECK_LE(custom_ranges.size(), bucket_count()); 1023 DCHECK_LE(custom_ranges.size(), bucket_count());
1031 for (size_t index = 0; index < custom_ranges.size(); ++index) 1024 for (size_t index = 0; index < custom_ranges.size(); ++index)
1032 SetBucketRange(index, custom_ranges[index]); 1025 SetBucketRange(index, custom_ranges[index]);
1033 ResetRangeChecksum(); 1026 ResetRangeChecksum();
1034 } 1027 }
1035 1028
1036 double CustomHistogram::GetBucketSize(Count current, size_t i) const { 1029 double CustomHistogram::GetBucketSize(Count current, size_t i) const {
1037 return 1; 1030 return 1;
1038 } 1031 }
1039 1032
1040 //------------------------------------------------------------------------------
1041 // The next section handles global (central) support for all histograms, as well
1042 // as startup/teardown of this service.
1043 //------------------------------------------------------------------------------
1044
1045 // This singleton instance should be started during the single threaded portion
1046 // of main(), and hence it is not thread safe. It initializes globals to
1047 // provide support for all future calls.
1048 StatisticsRecorder::StatisticsRecorder() {
1049 DCHECK(!histograms_);
1050 if (lock_ == NULL) {
1051 // This will leak on purpose. It's the only way to make sure we won't race
1052 // against the static uninitialization of the module while one of our
1053 // static methods relying on the lock get called at an inappropriate time
1054 // during the termination phase. Since it's a static data member, we will
1055 // leak one per process, which would be similar to the instance allocated
1056 // during static initialization and released only on process termination.
1057 lock_ = new base::Lock;
1058 }
1059 base::AutoLock auto_lock(*lock_);
1060 histograms_ = new HistogramMap;
1061 ranges_ = new RangesMap;
1062 }
1063
1064 StatisticsRecorder::~StatisticsRecorder() {
1065 DCHECK(histograms_ && lock_);
1066
1067 if (dump_on_exit_) {
1068 std::string output;
1069 WriteGraph("", &output);
1070 DLOG(INFO) << output;
1071 }
1072 // Clean up.
1073 HistogramMap* histograms = NULL;
1074 {
1075 base::AutoLock auto_lock(*lock_);
1076 histograms = histograms_;
1077 histograms_ = NULL;
1078 }
1079 RangesMap* ranges = NULL;
1080 {
1081 base::AutoLock auto_lock(*lock_);
1082 ranges = ranges_;
1083 ranges_ = NULL;
1084 }
1085 // We are going to leak the histograms and the ranges.
1086 delete histograms;
1087 delete ranges;
1088 // We don't delete lock_ on purpose to avoid having to properly protect
1089 // against it going away after we checked for NULL in the static methods.
1090 }
1091
1092 // static
1093 bool StatisticsRecorder::IsActive() {
1094 if (lock_ == NULL)
1095 return false;
1096 base::AutoLock auto_lock(*lock_);
1097 return NULL != histograms_;
1098 }
1099
1100 Histogram* StatisticsRecorder::RegisterOrDeleteDuplicate(Histogram* histogram) {
1101 // As per crbug.com/79322 the histograms are intentionally leaked, so we need
1102 // to annotate them. Because ANNOTATE_LEAKING_OBJECT_PTR may be used only once
1103 // for an object, the duplicates should not be annotated.
1104 // Callers are responsible for not calling RegisterOrDeleteDuplicate(ptr)
1105 // twice if (lock_ == NULL) || (!histograms_).
1106 DCHECK(histogram->HasValidRangeChecksum());
1107 if (lock_ == NULL) {
1108 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322
1109 return histogram;
1110 }
1111 base::AutoLock auto_lock(*lock_);
1112 if (!histograms_) {
1113 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322
1114 return histogram;
1115 }
1116 const std::string name = histogram->histogram_name();
1117 HistogramMap::iterator it = histograms_->find(name);
1118 // Avoid overwriting a previous registration.
1119 if (histograms_->end() == it) {
1120 (*histograms_)[name] = histogram;
1121 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322
1122 RegisterOrDeleteDuplicateRanges(histogram);
1123 ++number_of_histograms_;
1124 } else {
1125 delete histogram; // We already have one by this name.
1126 histogram = it->second;
1127 }
1128 return histogram;
1129 }
1130
1131 // static
1132 void StatisticsRecorder::RegisterOrDeleteDuplicateRanges(Histogram* histogram) {
1133 DCHECK(histogram);
1134 CachedRanges* histogram_ranges = histogram->cached_ranges();
1135 DCHECK(histogram_ranges);
1136 uint32 checksum = histogram->range_checksum();
1137 histogram_ranges->SetRangeChecksum(checksum);
1138
1139 RangesMap::iterator ranges_it = ranges_->find(checksum);
1140 if (ranges_->end() == ranges_it) {
1141 // Register the new CachedRanges.
1142 std::list<CachedRanges*>* checksum_matching_list(
1143 new std::list<CachedRanges*>());
1144 checksum_matching_list->push_front(histogram_ranges);
1145 (*ranges_)[checksum] = checksum_matching_list;
1146 return;
1147 }
1148
1149 // Use the registered CachedRanges if the registered CachedRanges has same
1150 // ranges_ as |histogram|'s CachedRanges.
1151 std::list<CachedRanges*>* checksum_matching_list = ranges_it->second;
1152 std::list<CachedRanges*>::iterator checksum_matching_list_it;
1153 for (checksum_matching_list_it = checksum_matching_list->begin();
1154 checksum_matching_list_it != checksum_matching_list->end();
1155 ++checksum_matching_list_it) {
1156 CachedRanges* existing_histogram_ranges = *checksum_matching_list_it;
1157 DCHECK(existing_histogram_ranges);
1158 if (existing_histogram_ranges->Equals(histogram_ranges)) {
1159 histogram->set_cached_ranges(existing_histogram_ranges);
1160 ++number_of_vectors_saved_;
1161 saved_ranges_size_ += histogram_ranges->size();
1162 delete histogram_ranges;
1163 return;
1164 }
1165 }
1166
1167 // We haven't found a CachedRanges which has the same ranges. Register the
1168 // new CachedRanges.
1169 DCHECK(checksum_matching_list_it == checksum_matching_list->end());
1170 checksum_matching_list->push_front(histogram_ranges);
1171 }
1172
1173 // static
1174 void StatisticsRecorder::CollectHistogramStats(const std::string& suffix) {
1175 static int uma_upload_attempt = 0;
1176 ++uma_upload_attempt;
1177 if (uma_upload_attempt == 1) {
1178 UMA_HISTOGRAM_COUNTS_10000(
1179 "Histogram.SharedRange.Count.FirstUpload." + suffix,
1180 number_of_histograms_);
1181 UMA_HISTOGRAM_COUNTS_10000(
1182 "Histogram.SharedRange.RangesSaved.FirstUpload." + suffix,
1183 number_of_vectors_saved_);
1184 UMA_HISTOGRAM_COUNTS(
1185 "Histogram.SharedRange.ElementsSaved.FirstUpload." + suffix,
1186 static_cast<int>(saved_ranges_size_));
1187 number_of_histograms_ = 0;
1188 number_of_vectors_saved_ = 0;
1189 saved_ranges_size_ = 0;
1190 return;
1191 }
1192 if (uma_upload_attempt == 2) {
1193 UMA_HISTOGRAM_COUNTS_10000(
1194 "Histogram.SharedRange.Count.SecondUpload." + suffix,
1195 number_of_histograms_);
1196 UMA_HISTOGRAM_COUNTS_10000(
1197 "Histogram.SharedRange.RangesSaved.SecondUpload." + suffix,
1198 number_of_vectors_saved_);
1199 UMA_HISTOGRAM_COUNTS(
1200 "Histogram.SharedRange.ElementsSaved.SecondUpload." + suffix,
1201 static_cast<int>(saved_ranges_size_));
1202 number_of_histograms_ = 0;
1203 number_of_vectors_saved_ = 0;
1204 saved_ranges_size_ = 0;
1205 return;
1206 }
1207 UMA_HISTOGRAM_COUNTS_10000(
1208 "Histogram.SharedRange.Count.RestOfUploads." + suffix,
1209 number_of_histograms_);
1210 UMA_HISTOGRAM_COUNTS_10000(
1211 "Histogram.SharedRange.RangesSaved.RestOfUploads." + suffix,
1212 number_of_vectors_saved_);
1213 UMA_HISTOGRAM_COUNTS(
1214 "Histogram.SharedRange.ElementsSaved.RestOfUploads." + suffix,
1215 static_cast<int>(saved_ranges_size_));
1216 }
1217
1218 // static
1219 void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
1220 std::string* output) {
1221 if (!IsActive())
1222 return;
1223
1224 Histograms snapshot;
1225 GetSnapshot(query, &snapshot);
1226 for (Histograms::iterator it = snapshot.begin();
1227 it != snapshot.end();
1228 ++it) {
1229 (*it)->WriteHTMLGraph(output);
1230 output->append("<br><hr><br>");
1231 }
1232 }
1233
1234 // static
1235 void StatisticsRecorder::WriteGraph(const std::string& query,
1236 std::string* output) {
1237 if (!IsActive())
1238 return;
1239 if (query.length())
1240 StringAppendF(output, "Collections of histograms for %s\n", query.c_str());
1241 else
1242 output->append("Collections of all histograms\n");
1243
1244 Histograms snapshot;
1245 GetSnapshot(query, &snapshot);
1246 for (Histograms::iterator it = snapshot.begin();
1247 it != snapshot.end();
1248 ++it) {
1249 (*it)->WriteAscii(true, "\n", output);
1250 output->append("\n");
1251 }
1252 }
1253
1254 // static
1255 void StatisticsRecorder::GetHistograms(Histograms* output) {
1256 if (lock_ == NULL)
1257 return;
1258 base::AutoLock auto_lock(*lock_);
1259 if (!histograms_)
1260 return;
1261 for (HistogramMap::iterator it = histograms_->begin();
1262 histograms_->end() != it;
1263 ++it) {
1264 DCHECK_EQ(it->first, it->second->histogram_name());
1265 output->push_back(it->second);
1266 }
1267 }
1268
1269 bool StatisticsRecorder::FindHistogram(const std::string& name,
1270 Histogram** histogram) {
1271 if (lock_ == NULL)
1272 return false;
1273 base::AutoLock auto_lock(*lock_);
1274 if (!histograms_)
1275 return false;
1276 HistogramMap::iterator it = histograms_->find(name);
1277 if (histograms_->end() == it)
1278 return false;
1279 *histogram = it->second;
1280 return true;
1281 }
1282
1283 // private static
1284 void StatisticsRecorder::GetSnapshot(const std::string& query,
1285 Histograms* snapshot) {
1286 if (lock_ == NULL)
1287 return;
1288 base::AutoLock auto_lock(*lock_);
1289 if (!histograms_)
1290 return;
1291 for (HistogramMap::iterator it = histograms_->begin();
1292 histograms_->end() != it;
1293 ++it) {
1294 if (it->first.find(query) != std::string::npos)
1295 snapshot->push_back(it->second);
1296 }
1297 }
1298
1299 CachedRanges::CachedRanges(size_t bucket_count, int initial_value) 1033 CachedRanges::CachedRanges(size_t bucket_count, int initial_value)
1300 : ranges_(bucket_count, initial_value), 1034 : ranges_(bucket_count, initial_value),
1301 range_checksum_(0) { 1035 range_checksum_(0) {
1302 } 1036 }
1303 1037
1304 CachedRanges::~CachedRanges() { 1038 CachedRanges::~CachedRanges() {
1305 } 1039 }
1306 1040
1307 void CachedRanges::SetBucketRange(size_t i, Histogram::Sample value) { 1041 void CachedRanges::SetBucketRange(size_t i, Histogram::Sample value) {
1308 DCHECK_LT(i, ranges_.size()); 1042 DCHECK_LT(i, ranges_.size());
1309 DCHECK_GE(value, 0); 1043 DCHECK_GE(value, 0);
1310 ranges_[i] = value; 1044 ranges_[i] = value;
1311 } 1045 }
1312 1046
1313 bool CachedRanges::Equals(CachedRanges* other) const { 1047 bool CachedRanges::Equals(CachedRanges* other) const {
1314 if (range_checksum_ != other->range_checksum_) 1048 if (range_checksum_ != other->range_checksum_)
1315 return false; 1049 return false;
1316 if (ranges_.size() != other->ranges_.size()) 1050 if (ranges_.size() != other->ranges_.size())
1317 return false; 1051 return false;
1318 for (size_t index = 0; index < ranges_.size(); ++index) { 1052 for (size_t index = 0; index < ranges_.size(); ++index) {
1319 if (ranges_[index] != other->ranges_[index]) 1053 if (ranges_[index] != other->ranges_[index])
1320 return false; 1054 return false;
1321 } 1055 }
1322 return true; 1056 return true;
1323 } 1057 }
1324 1058
1325 // static
1326 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;
1327 // static
1328 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL;
1329 // static
1330 base::Lock* StatisticsRecorder::lock_ = NULL;
1331 // static
1332 bool StatisticsRecorder::dump_on_exit_ = false;
1333 } // namespace base 1059 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/histogram.h ('k') | base/metrics/histogram_snapshot_manager.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698