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

Side by Side Diff: base/metrics/statistics_recorder.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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "base/metrics/statistics_recorder.h"
6
7 #include "base/debug/leak_annotations.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram.h"
10 #include "base/stringprintf.h"
11 #include "base/synchronization/lock.h"
12
13 namespace base {
14
15 // Collect the number of histograms created.
16 static uint32 number_of_histograms_ = 0;
17 // Collect the number of vectors saved because of caching ranges.
18 static uint32 number_of_vectors_saved_ = 0;
19 // Collect the number of ranges_ elements saved because of caching ranges.
20 static size_t saved_ranges_size_ = 0;
21
22 // This singleton instance should be started during the single threaded portion
23 // of main(), and hence it is not thread safe. It initializes globals to
24 // provide support for all future calls.
25 StatisticsRecorder::StatisticsRecorder() {
26 DCHECK(!histograms_);
27 if (lock_ == NULL) {
28 // This will leak on purpose. It's the only way to make sure we won't race
29 // against the static uninitialization of the module while one of our
30 // static methods relying on the lock get called at an inappropriate time
31 // during the termination phase. Since it's a static data member, we will
32 // leak one per process, which would be similar to the instance allocated
33 // during static initialization and released only on process termination.
34 lock_ = new base::Lock;
35 }
36 base::AutoLock auto_lock(*lock_);
37 histograms_ = new HistogramMap;
38 ranges_ = new RangesMap;
39 }
40
41 StatisticsRecorder::~StatisticsRecorder() {
42 DCHECK(histograms_ && lock_);
43
44 if (dump_on_exit_) {
45 std::string output;
46 WriteGraph("", &output);
47 DLOG(INFO) << output;
48 }
49 // Clean up.
50 HistogramMap* histograms = NULL;
51 {
52 base::AutoLock auto_lock(*lock_);
53 histograms = histograms_;
54 histograms_ = NULL;
55 }
56 RangesMap* ranges = NULL;
57 {
58 base::AutoLock auto_lock(*lock_);
59 ranges = ranges_;
60 ranges_ = NULL;
61 }
62 // We are going to leak the histograms and the ranges.
63 delete histograms;
64 delete ranges;
65 // We don't delete lock_ on purpose to avoid having to properly protect
66 // against it going away after we checked for NULL in the static methods.
67 }
68
69 // static
70 bool StatisticsRecorder::IsActive() {
71 if (lock_ == NULL)
72 return false;
73 base::AutoLock auto_lock(*lock_);
74 return NULL != histograms_;
75 }
76
77 Histogram* StatisticsRecorder::RegisterOrDeleteDuplicate(Histogram* histogram) {
78 // As per crbug.com/79322 the histograms are intentionally leaked, so we need
79 // to annotate them. Because ANNOTATE_LEAKING_OBJECT_PTR may be used only once
80 // for an object, the duplicates should not be annotated.
81 // Callers are responsible for not calling RegisterOrDeleteDuplicate(ptr)
82 // twice if (lock_ == NULL) || (!histograms_).
83 DCHECK(histogram->HasValidRangeChecksum());
84 if (lock_ == NULL) {
85 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322
86 return histogram;
87 }
88 base::AutoLock auto_lock(*lock_);
89 if (!histograms_) {
90 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322
91 return histogram;
92 }
93 const std::string name = histogram->histogram_name();
94 HistogramMap::iterator it = histograms_->find(name);
95 // Avoid overwriting a previous registration.
96 if (histograms_->end() == it) {
97 (*histograms_)[name] = histogram;
98 ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322
99 RegisterOrDeleteDuplicateRanges(histogram);
100 ++number_of_histograms_;
101 } else {
102 delete histogram; // We already have one by this name.
103 histogram = it->second;
104 }
105 return histogram;
106 }
107
108 // static
109 void StatisticsRecorder::RegisterOrDeleteDuplicateRanges(Histogram* histogram) {
110 DCHECK(histogram);
111 CachedRanges* histogram_ranges = histogram->cached_ranges();
112 DCHECK(histogram_ranges);
113 uint32 checksum = histogram->range_checksum();
114 histogram_ranges->SetRangeChecksum(checksum);
115
116 RangesMap::iterator ranges_it = ranges_->find(checksum);
117 if (ranges_->end() == ranges_it) {
118 // Register the new CachedRanges.
119 std::list<CachedRanges*>* checksum_matching_list(
120 new std::list<CachedRanges*>());
121 checksum_matching_list->push_front(histogram_ranges);
122 (*ranges_)[checksum] = checksum_matching_list;
123 return;
124 }
125
126 // Use the registered CachedRanges if the registered CachedRanges has same
127 // ranges_ as |histogram|'s CachedRanges.
128 std::list<CachedRanges*>* checksum_matching_list = ranges_it->second;
129 std::list<CachedRanges*>::iterator checksum_matching_list_it;
130 for (checksum_matching_list_it = checksum_matching_list->begin();
131 checksum_matching_list_it != checksum_matching_list->end();
132 ++checksum_matching_list_it) {
133 CachedRanges* existing_histogram_ranges = *checksum_matching_list_it;
134 DCHECK(existing_histogram_ranges);
135 if (existing_histogram_ranges->Equals(histogram_ranges)) {
136 histogram->set_cached_ranges(existing_histogram_ranges);
137 ++number_of_vectors_saved_;
138 saved_ranges_size_ += histogram_ranges->size();
139 delete histogram_ranges;
140 return;
141 }
142 }
143
144 // We haven't found a CachedRanges which has the same ranges. Register the
145 // new CachedRanges.
146 DCHECK(checksum_matching_list_it == checksum_matching_list->end());
147 checksum_matching_list->push_front(histogram_ranges);
148 }
149
150 // static
151 void StatisticsRecorder::CollectHistogramStats(const std::string& suffix) {
152 static int uma_upload_attempt = 0;
153 ++uma_upload_attempt;
154 if (uma_upload_attempt == 1) {
155 UMA_HISTOGRAM_COUNTS_10000(
156 "Histogram.SharedRange.Count.FirstUpload." + suffix,
157 number_of_histograms_);
158 UMA_HISTOGRAM_COUNTS_10000(
159 "Histogram.SharedRange.RangesSaved.FirstUpload." + suffix,
160 number_of_vectors_saved_);
161 UMA_HISTOGRAM_COUNTS(
162 "Histogram.SharedRange.ElementsSaved.FirstUpload." + suffix,
163 static_cast<int>(saved_ranges_size_));
164 number_of_histograms_ = 0;
165 number_of_vectors_saved_ = 0;
166 saved_ranges_size_ = 0;
167 return;
168 }
169 if (uma_upload_attempt == 2) {
170 UMA_HISTOGRAM_COUNTS_10000(
171 "Histogram.SharedRange.Count.SecondUpload." + suffix,
172 number_of_histograms_);
173 UMA_HISTOGRAM_COUNTS_10000(
174 "Histogram.SharedRange.RangesSaved.SecondUpload." + suffix,
175 number_of_vectors_saved_);
176 UMA_HISTOGRAM_COUNTS(
177 "Histogram.SharedRange.ElementsSaved.SecondUpload." + suffix,
178 static_cast<int>(saved_ranges_size_));
179 number_of_histograms_ = 0;
180 number_of_vectors_saved_ = 0;
181 saved_ranges_size_ = 0;
182 return;
183 }
184 UMA_HISTOGRAM_COUNTS_10000(
185 "Histogram.SharedRange.Count.RestOfUploads." + suffix,
186 number_of_histograms_);
187 UMA_HISTOGRAM_COUNTS_10000(
188 "Histogram.SharedRange.RangesSaved.RestOfUploads." + suffix,
189 number_of_vectors_saved_);
190 UMA_HISTOGRAM_COUNTS(
191 "Histogram.SharedRange.ElementsSaved.RestOfUploads." + suffix,
192 static_cast<int>(saved_ranges_size_));
193 }
194
195 // static
196 void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
197 std::string* output) {
198 if (!IsActive())
199 return;
200
201 Histograms snapshot;
202 GetSnapshot(query, &snapshot);
203 for (Histograms::iterator it = snapshot.begin();
204 it != snapshot.end();
205 ++it) {
206 (*it)->WriteHTMLGraph(output);
207 output->append("<br><hr><br>");
208 }
209 }
210
211 // static
212 void StatisticsRecorder::WriteGraph(const std::string& query,
213 std::string* output) {
214 if (!IsActive())
215 return;
216 if (query.length())
217 StringAppendF(output, "Collections of histograms for %s\n", query.c_str());
218 else
219 output->append("Collections of all histograms\n");
220
221 Histograms snapshot;
222 GetSnapshot(query, &snapshot);
223 for (Histograms::iterator it = snapshot.begin();
224 it != snapshot.end();
225 ++it) {
226 (*it)->WriteAscii(true, "\n", output);
227 output->append("\n");
228 }
229 }
230
231 // static
232 void StatisticsRecorder::GetHistograms(Histograms* output) {
233 if (lock_ == NULL)
234 return;
235 base::AutoLock auto_lock(*lock_);
236 if (!histograms_)
237 return;
238 for (HistogramMap::iterator it = histograms_->begin();
239 histograms_->end() != it;
240 ++it) {
241 DCHECK_EQ(it->first, it->second->histogram_name());
242 output->push_back(it->second);
243 }
244 }
245
246 bool StatisticsRecorder::FindHistogram(const std::string& name,
247 Histogram** histogram) {
248 if (lock_ == NULL)
249 return false;
250 base::AutoLock auto_lock(*lock_);
251 if (!histograms_)
252 return false;
253 HistogramMap::iterator it = histograms_->find(name);
254 if (histograms_->end() == it)
255 return false;
256 *histogram = it->second;
257 return true;
258 }
259
260 // private static
261 void StatisticsRecorder::GetSnapshot(const std::string& query,
262 Histograms* snapshot) {
263 if (lock_ == NULL)
264 return;
265 base::AutoLock auto_lock(*lock_);
266 if (!histograms_)
267 return;
268 for (HistogramMap::iterator it = histograms_->begin();
269 histograms_->end() != it;
270 ++it) {
271 if (it->first.find(query) != std::string::npos)
272 snapshot->push_back(it->second);
273 }
274 }
275
276 // static
277 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;
278 // static
279 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL;
280 // static
281 base::Lock* StatisticsRecorder::lock_ = NULL;
282 // static
283 bool StatisticsRecorder::dump_on_exit_ = false;
284
285 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/statistics_recorder.h ('k') | chrome/browser/chrome_browser_application_mac_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698