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

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

Powered by Google App Engine
This is Rietveld 408576698