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 // 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" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 #include "base/string_util.h" | 23 #include "base/string_util.h" |
24 #include "base/stringprintf.h" | 24 #include "base/stringprintf.h" |
25 #include "base/synchronization/lock.h" | 25 #include "base/synchronization/lock.h" |
26 #include "base/values.h" | 26 #include "base/values.h" |
27 | 27 |
28 using std::string; | 28 using std::string; |
29 using std::vector; | 29 using std::vector; |
30 | 30 |
31 namespace base { | 31 namespace base { |
32 | 32 |
33 namespace { | |
34 | |
35 bool ReadHistogramArguments(PickleIterator* iter, | |
36 string* histogram_name, | |
37 int* flags, | |
38 int* declared_min, | |
39 int* declared_max, | |
40 uint64* bucket_count, | |
41 uint32* range_checksum) { | |
42 if (!iter->ReadString(histogram_name) || | |
43 !iter->ReadInt(flags) || | |
44 !iter->ReadInt(declared_min) || | |
45 !iter->ReadInt(declared_max) || | |
46 !iter->ReadUInt64(bucket_count) || | |
47 !iter->ReadUInt32(range_checksum)) { | |
48 DLOG(ERROR) << "Pickle error decoding Histogram: " << *histogram_name; | |
49 return false; | |
50 } | |
51 | |
52 // Since these fields may have come from an untrusted renderer, do additional | |
53 // checks above and beyond those in Histogram::Initialize() | |
54 if (*declared_max <= 0 || | |
55 *declared_min <= 0 || | |
56 *declared_max < *declared_min || | |
57 INT_MAX / sizeof(HistogramBase::Count) <= *bucket_count || | |
58 *bucket_count < 2) { | |
59 DLOG(ERROR) << "Values error decoding Histogram: " << histogram_name; | |
60 return false; | |
61 } | |
62 | |
63 // We use the arguments to find or create the local version of the histogram | |
64 // in this process. So need to clear IPC flag first. | |
Ilya Sherman
2012/12/29 00:17:30
nit: "in this process. So need to clear IPC flag"
kaiwang
2013/01/08 00:51:40
Done.
| |
65 DCHECK(*flags & HistogramBase::kIPCSerializationSourceFlag); | |
66 *flags &= ~HistogramBase::kIPCSerializationSourceFlag; | |
67 | |
68 return true; | |
69 } | |
70 | |
71 bool ValidateRangeChecksum(const HistogramBase* histogram, | |
Ilya Sherman
2012/12/29 00:17:30
nit: Please pass by const-reference.
kaiwang
2013/01/08 00:51:40
Done.
| |
72 uint32 range_checksum) { | |
73 const Histogram* casted_histogram = | |
74 static_cast<const Histogram*>(histogram); | |
75 | |
76 return casted_histogram->bucket_ranges()->checksum() == range_checksum; | |
77 } | |
78 | |
79 } // namespace | |
80 | |
33 typedef HistogramBase::Count Count; | 81 typedef HistogramBase::Count Count; |
34 typedef HistogramBase::Sample Sample; | 82 typedef HistogramBase::Sample Sample; |
35 | 83 |
36 // static | 84 // static |
37 const size_t Histogram::kBucketCount_MAX = 16384u; | 85 const size_t Histogram::kBucketCount_MAX = 16384u; |
38 | 86 |
39 // TODO(rtenneti): delete this code after debugging. | 87 // TODO(rtenneti): delete this code after debugging. |
40 void CheckCorruption(const Histogram& histogram, bool new_histogram) { | 88 void CheckCorruption(const Histogram& histogram, bool new_histogram) { |
41 const std::string& histogram_name = histogram.histogram_name(); | 89 const std::string& histogram_name = histogram.histogram_name(); |
42 char histogram_name_buf[128]; | 90 char histogram_name_buf[128]; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
146 ranges->set_range(bucket_index, current); | 194 ranges->set_range(bucket_index, current); |
147 } | 195 } |
148 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); | 196 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); |
149 ranges->ResetChecksum(); | 197 ranges->ResetChecksum(); |
150 } | 198 } |
151 | 199 |
152 void Histogram::AddBoolean(bool value) { | 200 void Histogram::AddBoolean(bool value) { |
153 DCHECK(false); | 201 DCHECK(false); |
154 } | 202 } |
155 | 203 |
156 void Histogram::AddSamples(const HistogramSamples& samples) { | |
157 samples_->Add(samples); | |
158 } | |
159 | |
160 bool Histogram::AddSamplesFromPickle(PickleIterator* iter) { | |
161 return samples_->AddFromPickle(iter); | |
162 } | |
163 | |
164 // static | |
165 string Histogram::SerializeHistogramInfo(const Histogram& histogram, | |
166 const HistogramSamples& snapshot) { | |
167 DCHECK(histogram.bucket_ranges()->HasValidChecksum()); | |
Ilya Sherman
2012/12/29 00:17:30
What happened to this DCHECK?
kaiwang
2013/01/08 00:51:40
Added to Histogram::SerializeInfoImpl
| |
168 | |
169 Pickle pickle; | |
170 pickle.WriteString(histogram.histogram_name()); | |
171 pickle.WriteInt(histogram.declared_min()); | |
172 pickle.WriteInt(histogram.declared_max()); | |
173 pickle.WriteUInt64(histogram.bucket_count()); | |
174 pickle.WriteUInt32(histogram.bucket_ranges()->checksum()); | |
175 pickle.WriteInt(histogram.GetHistogramType()); | |
176 pickle.WriteInt(histogram.flags()); | |
177 | |
178 histogram.SerializeRanges(&pickle); | |
179 | |
180 snapshot.Serialize(&pickle); | |
181 | |
182 return string(static_cast<const char*>(pickle.data()), pickle.size()); | |
183 } | |
184 | |
185 // static | |
186 bool Histogram::DeserializeHistogramInfo(const string& histogram_info) { | |
187 if (histogram_info.empty()) { | |
188 return false; | |
189 } | |
190 | |
191 Pickle pickle(histogram_info.data(), | |
192 static_cast<int>(histogram_info.size())); | |
193 string histogram_name; | |
194 int declared_min; | |
195 int declared_max; | |
196 uint64 bucket_count; | |
197 uint32 range_checksum; | |
198 int histogram_type; | |
199 int pickle_flags; | |
200 | |
201 PickleIterator iter(pickle); | |
202 if (!iter.ReadString(&histogram_name) || | |
203 !iter.ReadInt(&declared_min) || | |
204 !iter.ReadInt(&declared_max) || | |
205 !iter.ReadUInt64(&bucket_count) || | |
206 !iter.ReadUInt32(&range_checksum) || | |
207 !iter.ReadInt(&histogram_type) || | |
208 !iter.ReadInt(&pickle_flags)) { | |
209 DLOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name; | |
210 return false; | |
211 } | |
212 | |
213 DCHECK(pickle_flags & kIPCSerializationSourceFlag); | |
214 // Since these fields may have come from an untrusted renderer, do additional | |
215 // checks above and beyond those in Histogram::Initialize() | |
216 if (declared_max <= 0 || declared_min <= 0 || declared_max < declared_min || | |
217 INT_MAX / sizeof(Count) <= bucket_count || bucket_count < 2) { | |
218 DLOG(ERROR) << "Values error decoding Histogram: " << histogram_name; | |
219 return false; | |
220 } | |
221 | |
222 Flags flags = static_cast<Flags>(pickle_flags & ~kIPCSerializationSourceFlag); | |
223 | |
224 Histogram* render_histogram(NULL); | |
225 | |
226 if (histogram_type == HISTOGRAM) { | |
227 render_histogram = Histogram::FactoryGet( | |
228 histogram_name, declared_min, declared_max, bucket_count, flags); | |
229 } else if (histogram_type == LINEAR_HISTOGRAM) { | |
230 render_histogram = LinearHistogram::FactoryGet( | |
231 histogram_name, declared_min, declared_max, bucket_count, flags); | |
232 } else if (histogram_type == BOOLEAN_HISTOGRAM) { | |
233 render_histogram = BooleanHistogram::FactoryGet(histogram_name, flags); | |
234 } else if (histogram_type == CUSTOM_HISTOGRAM) { | |
235 vector<Sample> sample_ranges(bucket_count); | |
236 if (!CustomHistogram::DeserializeRanges(&iter, &sample_ranges)) { | |
237 DLOG(ERROR) << "Pickle error decoding ranges: " << histogram_name; | |
238 return false; | |
239 } | |
240 render_histogram = | |
241 CustomHistogram::FactoryGet(histogram_name, sample_ranges, flags); | |
242 } else { | |
243 DLOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " | |
244 << histogram_type; | |
245 return false; | |
246 } | |
247 | |
248 DCHECK_EQ(render_histogram->declared_min(), declared_min); | |
249 DCHECK_EQ(render_histogram->declared_max(), declared_max); | |
250 DCHECK_EQ(render_histogram->bucket_count(), bucket_count); | |
251 DCHECK_EQ(render_histogram->GetHistogramType(), histogram_type); | |
252 | |
253 if (render_histogram->bucket_ranges()->checksum() != range_checksum) { | |
254 return false; | |
255 } | |
256 | |
257 if (render_histogram->flags() & kIPCSerializationSourceFlag) { | |
258 DVLOG(1) << "Single process mode, histogram observed and not copied: " | |
259 << histogram_name; | |
260 return true; | |
261 } | |
262 | |
263 DCHECK_EQ(flags & render_histogram->flags(), flags); | |
Ilya Sherman
2012/12/29 00:17:30
nit: What happened to this DCHECK?
kaiwang
2013/01/08 00:51:40
Actually I really don't understand what's this DCH
Ilya Sherman
2013/01/08 22:31:53
I'm also not sure; perhaps Jim can comment? I thi
| |
264 return render_histogram->AddSamplesFromPickle(&iter); | |
265 } | |
266 | |
267 // static | 204 // static |
268 const int Histogram::kCommonRaceBasedCountMismatch = 5; | 205 const int Histogram::kCommonRaceBasedCountMismatch = 5; |
269 | 206 |
270 Histogram::Inconsistencies Histogram::FindCorruption( | 207 Histogram::Inconsistencies Histogram::FindCorruption( |
271 const HistogramSamples& samples) const { | 208 const HistogramSamples& samples) const { |
272 int inconsistencies = NO_INCONSISTENCIES; | 209 int inconsistencies = NO_INCONSISTENCIES; |
273 Sample previous_range = -1; // Bottom range is always 0. | 210 Sample previous_range = -1; // Bottom range is always 0. |
274 for (size_t index = 0; index < bucket_count(); ++index) { | 211 for (size_t index = 0; index < bucket_count(); ++index) { |
275 int new_range = ranges(index); | 212 int new_range = ranges(index); |
276 if (previous_range >= new_range) | 213 if (previous_range >= new_range) |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
356 value = kSampleType_MAX - 1; | 293 value = kSampleType_MAX - 1; |
357 if (value < 0) | 294 if (value < 0) |
358 value = 0; | 295 value = 0; |
359 samples_->Accumulate(value, 1); | 296 samples_->Accumulate(value, 1); |
360 } | 297 } |
361 | 298 |
362 scoped_ptr<HistogramSamples> Histogram::SnapshotSamples() const { | 299 scoped_ptr<HistogramSamples> Histogram::SnapshotSamples() const { |
363 return SnapshotSampleVector().PassAs<HistogramSamples>(); | 300 return SnapshotSampleVector().PassAs<HistogramSamples>(); |
364 } | 301 } |
365 | 302 |
303 void Histogram::AddSamples(const HistogramSamples& samples) { | |
304 samples_->Add(samples); | |
305 } | |
306 | |
307 bool Histogram::AddSamplesFromPickle(PickleIterator* iter) { | |
308 return samples_->AddFromPickle(iter); | |
309 } | |
310 | |
366 // The following methods provide a graphical histogram display. | 311 // The following methods provide a graphical histogram display. |
367 void Histogram::WriteHTMLGraph(string* output) const { | 312 void Histogram::WriteHTMLGraph(string* output) const { |
368 // TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc. | 313 // TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc. |
369 output->append("<PRE>"); | 314 output->append("<PRE>"); |
370 WriteAsciiImpl(true, "<br>", output); | 315 WriteAsciiImpl(true, "<br>", output); |
371 output->append("</PRE>"); | 316 output->append("</PRE>"); |
372 } | 317 } |
373 | 318 |
374 void Histogram::WriteAscii(string* output) const { | 319 void Histogram::WriteAscii(string* output) const { |
375 WriteAsciiImpl(true, "\n", output); | 320 WriteAsciiImpl(true, "\n", output); |
376 } | 321 } |
377 | 322 |
323 bool Histogram::SerializeInfoImpl(Pickle* pickle) const { | |
324 if (pickle->WriteString(histogram_name()) && | |
325 pickle->WriteInt(flags()) && | |
Ilya Sherman
2012/12/29 00:17:30
I'm curious, why did you move flags to be written
kaiwang
2013/01/08 00:51:40
histogram_name and flags are fields from Histogram
| |
326 pickle->WriteInt(declared_min()) && | |
327 pickle->WriteInt(declared_max()) && | |
328 pickle->WriteUInt64(bucket_count()) && | |
329 pickle->WriteUInt32(bucket_ranges()->checksum())) { | |
330 return true; | |
331 } | |
332 return false; | |
Ilya Sherman
2012/12/29 00:17:30
Optional nit: IMO it's tidier to write this as
re
kaiwang
2013/01/08 00:51:40
Done.
| |
333 } | |
334 | |
378 Histogram::Histogram(const string& name, | 335 Histogram::Histogram(const string& name, |
379 Sample minimum, | 336 Sample minimum, |
380 Sample maximum, | 337 Sample maximum, |
381 size_t bucket_count, | 338 size_t bucket_count, |
382 const BucketRanges* ranges) | 339 const BucketRanges* ranges) |
383 : HistogramBase(name), | 340 : HistogramBase(name), |
384 bucket_ranges_(ranges), | 341 bucket_ranges_(ranges), |
385 declared_min_(minimum), | 342 declared_min_(minimum), |
386 declared_max_(maximum), | 343 declared_max_(maximum), |
387 bucket_count_(bucket_count) { | 344 bucket_count_(bucket_count) { |
388 if (ranges) | 345 if (ranges) |
389 samples_.reset(new SampleVector(ranges)); | 346 samples_.reset(new SampleVector(ranges)); |
390 } | 347 } |
391 | 348 |
392 Histogram::~Histogram() { | 349 Histogram::~Histogram() { |
393 if (StatisticsRecorder::dump_on_exit()) { | 350 if (StatisticsRecorder::dump_on_exit()) { |
394 string output; | 351 string output; |
395 WriteAsciiImpl(true, "\n", &output); | 352 WriteAsciiImpl(true, "\n", &output); |
396 DLOG(INFO) << output; | 353 DLOG(INFO) << output; |
397 } | 354 } |
398 } | 355 } |
399 | 356 |
400 bool Histogram::SerializeRanges(Pickle* pickle) const { | |
401 return true; | |
402 } | |
403 | |
404 bool Histogram::PrintEmptyBucket(size_t index) const { | 357 bool Histogram::PrintEmptyBucket(size_t index) const { |
405 return true; | 358 return true; |
406 } | 359 } |
407 | 360 |
408 // Use the actual bucket widths (like a linear histogram) until the widths get | 361 // Use the actual bucket widths (like a linear histogram) until the widths get |
409 // over some transition value, and then use that transition width. Exponentials | 362 // over some transition value, and then use that transition width. Exponentials |
410 // get so big so fast (and we don't expect to see a lot of entries in the large | 363 // get so big so fast (and we don't expect to see a lot of entries in the large |
411 // buckets), so we need this to make it possible to see what is going on and | 364 // buckets), so we need this to make it possible to see what is going on and |
412 // not have 0-graphical-height buckets. | 365 // not have 0-graphical-height buckets. |
413 double Histogram::GetBucketSize(Count current, size_t i) const { | 366 double Histogram::GetBucketSize(Count current, size_t i) const { |
(...skipping 10 matching lines...) Expand all Loading... | |
424 if (kHexRangePrintingFlag & flags()) | 377 if (kHexRangePrintingFlag & flags()) |
425 StringAppendF(&result, "%#x", ranges(i)); | 378 StringAppendF(&result, "%#x", ranges(i)); |
426 else | 379 else |
427 StringAppendF(&result, "%d", ranges(i)); | 380 StringAppendF(&result, "%d", ranges(i)); |
428 return result; | 381 return result; |
429 } | 382 } |
430 | 383 |
431 //------------------------------------------------------------------------------ | 384 //------------------------------------------------------------------------------ |
432 // Private methods | 385 // Private methods |
433 | 386 |
387 // static | |
388 HistogramBase* Histogram::DeserializeHistogramInfo(PickleIterator* iter) { | |
389 string histogram_name; | |
390 int flags; | |
391 int declared_min; | |
392 int declared_max; | |
393 uint64 bucket_count; | |
394 uint32 range_checksum; | |
395 | |
396 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | |
397 &declared_max, &bucket_count, &range_checksum)) { | |
398 return NULL; | |
399 } | |
400 | |
401 // Find or create the local version of the histogram in this process. | |
402 HistogramBase* histogram = Histogram::FactoryGet( | |
403 histogram_name, declared_min, declared_max, bucket_count, flags); | |
404 | |
405 if (!ValidateRangeChecksum(histogram, range_checksum)) { | |
406 // The serialized histogram might be corrupted. | |
407 return NULL; | |
408 } | |
409 return histogram; | |
410 } | |
411 | |
434 scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { | 412 scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { |
435 scoped_ptr<SampleVector> samples(new SampleVector(bucket_ranges())); | 413 scoped_ptr<SampleVector> samples(new SampleVector(bucket_ranges())); |
436 samples->Add(*samples_); | 414 samples->Add(*samples_); |
437 return samples.Pass(); | 415 return samples.Pass(); |
438 } | 416 } |
439 | 417 |
440 void Histogram::WriteAsciiImpl(bool graph_it, | 418 void Histogram::WriteAsciiImpl(bool graph_it, |
441 const string& newline, | 419 const string& newline, |
442 string* output) const { | 420 string* output) const { |
443 // Get local (stack) copies of all effectively volatile class data so that we | 421 // Get local (stack) copies of all effectively volatile class data so that we |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
703 size_t i; | 681 size_t i; |
704 for (i = 1; i < bucket_count; ++i) { | 682 for (i = 1; i < bucket_count; ++i) { |
705 double linear_range = | 683 double linear_range = |
706 (min * (bucket_count -1 - i) + max * (i - 1)) / (bucket_count - 2); | 684 (min * (bucket_count -1 - i) + max * (i - 1)) / (bucket_count - 2); |
707 ranges->set_range(i, static_cast<Sample>(linear_range + 0.5)); | 685 ranges->set_range(i, static_cast<Sample>(linear_range + 0.5)); |
708 } | 686 } |
709 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); | 687 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); |
710 ranges->ResetChecksum(); | 688 ranges->ResetChecksum(); |
711 } | 689 } |
712 | 690 |
691 // static | |
692 HistogramBase* LinearHistogram::DeserializeHistogramInfo(PickleIterator* iter) { | |
693 string histogram_name; | |
694 int flags; | |
695 int declared_min; | |
696 int declared_max; | |
697 uint64 bucket_count; | |
698 uint32 range_checksum; | |
699 | |
700 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | |
701 &declared_max, &bucket_count, &range_checksum)) { | |
702 return NULL; | |
703 } | |
704 | |
705 HistogramBase* histogram = LinearHistogram::FactoryGet( | |
706 histogram_name, declared_min, declared_max, bucket_count, flags); | |
707 if (!ValidateRangeChecksum(histogram, range_checksum)) { | |
708 // The serialized histogram might be corrupted. | |
709 return NULL; | |
710 } | |
711 return histogram; | |
712 } | |
713 | |
713 //------------------------------------------------------------------------------ | 714 //------------------------------------------------------------------------------ |
714 // This section provides implementation for BooleanHistogram. | 715 // This section provides implementation for BooleanHistogram. |
715 //------------------------------------------------------------------------------ | 716 //------------------------------------------------------------------------------ |
716 | 717 |
717 Histogram* BooleanHistogram::FactoryGet(const string& name, int32 flags) { | 718 Histogram* BooleanHistogram::FactoryGet(const string& name, int32 flags) { |
718 Histogram* histogram = StatisticsRecorder::FindHistogram(name); | 719 Histogram* histogram = StatisticsRecorder::FindHistogram(name); |
719 if (!histogram) { | 720 if (!histogram) { |
720 // To avoid racy destruction at shutdown, the following will be leaked. | 721 // To avoid racy destruction at shutdown, the following will be leaked. |
721 BucketRanges* ranges = new BucketRanges(4); | 722 BucketRanges* ranges = new BucketRanges(4); |
722 LinearHistogram::InitializeBucketRanges(1, 2, 3, ranges); | 723 LinearHistogram::InitializeBucketRanges(1, 2, 3, ranges); |
(...skipping 20 matching lines...) Expand all Loading... | |
743 } | 744 } |
744 | 745 |
745 void BooleanHistogram::AddBoolean(bool value) { | 746 void BooleanHistogram::AddBoolean(bool value) { |
746 Add(value ? 1 : 0); | 747 Add(value ? 1 : 0); |
747 } | 748 } |
748 | 749 |
749 BooleanHistogram::BooleanHistogram(const string& name, | 750 BooleanHistogram::BooleanHistogram(const string& name, |
750 const BucketRanges* ranges) | 751 const BucketRanges* ranges) |
751 : LinearHistogram(name, 1, 2, 3, ranges) {} | 752 : LinearHistogram(name, 1, 2, 3, ranges) {} |
752 | 753 |
754 HistogramBase* BooleanHistogram::DeserializeHistogramInfo( | |
755 PickleIterator* iter) { | |
756 string histogram_name; | |
757 int flags; | |
758 int declared_min; | |
759 int declared_max; | |
760 uint64 bucket_count; | |
761 uint32 range_checksum; | |
762 | |
763 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | |
764 &declared_max, &bucket_count, &range_checksum)) { | |
765 return NULL; | |
766 } | |
767 | |
768 HistogramBase* histogram = BooleanHistogram::FactoryGet( | |
769 histogram_name, flags); | |
770 if (!ValidateRangeChecksum(histogram, range_checksum)) { | |
771 // The serialized histogram might be corrupted. | |
772 return NULL; | |
773 } | |
774 return histogram; | |
775 } | |
Ilya Sherman
2012/12/29 00:17:30
It would be good to share more of this code, rathe
kaiwang
2013/01/08 00:51:40
I think the good thing of current code is it distr
Ilya Sherman
2013/01/08 22:31:53
I'm not convinced that this is true: HistogramBase
| |
776 | |
753 //------------------------------------------------------------------------------ | 777 //------------------------------------------------------------------------------ |
754 // CustomHistogram: | 778 // CustomHistogram: |
755 //------------------------------------------------------------------------------ | 779 //------------------------------------------------------------------------------ |
756 | 780 |
757 Histogram* CustomHistogram::FactoryGet(const string& name, | 781 Histogram* CustomHistogram::FactoryGet(const string& name, |
758 const vector<Sample>& custom_ranges, | 782 const vector<Sample>& custom_ranges, |
759 int32 flags) { | 783 int32 flags) { |
760 CHECK(ValidateCustomRanges(custom_ranges)); | 784 CHECK(ValidateCustomRanges(custom_ranges)); |
761 | 785 |
762 Histogram* histogram = StatisticsRecorder::FindHistogram(name); | 786 Histogram* histogram = StatisticsRecorder::FindHistogram(name); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
802 } | 826 } |
803 | 827 |
804 CustomHistogram::CustomHistogram(const string& name, | 828 CustomHistogram::CustomHistogram(const string& name, |
805 const BucketRanges* ranges) | 829 const BucketRanges* ranges) |
806 : Histogram(name, | 830 : Histogram(name, |
807 ranges->range(1), | 831 ranges->range(1), |
808 ranges->range(ranges->size() - 2), | 832 ranges->range(ranges->size() - 2), |
809 ranges->size() - 1, | 833 ranges->size() - 1, |
810 ranges) {} | 834 ranges) {} |
811 | 835 |
812 bool CustomHistogram::SerializeRanges(Pickle* pickle) const { | 836 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { |
813 for (size_t i = 0; i < bucket_ranges()->size(); ++i) { | 837 if (!Histogram::SerializeInfoImpl(pickle)) |
838 return false; | |
839 | |
840 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't | |
841 // write them. | |
842 for (size_t i = 1; i < bucket_ranges()->size() - 1; ++i) { | |
814 if (!pickle->WriteInt(bucket_ranges()->range(i))) | 843 if (!pickle->WriteInt(bucket_ranges()->range(i))) |
815 return false; | 844 return false; |
816 } | 845 } |
817 return true; | 846 return true; |
818 } | 847 } |
819 | 848 |
820 // static | |
821 bool CustomHistogram::DeserializeRanges( | |
822 PickleIterator* iter, vector<Sample>* ranges) { | |
823 for (size_t i = 0; i < ranges->size(); ++i) { | |
824 if (!iter->ReadInt(&(*ranges)[i])) | |
825 return false; | |
826 } | |
827 return true; | |
828 } | |
829 | |
830 double CustomHistogram::GetBucketSize(Count current, size_t i) const { | 849 double CustomHistogram::GetBucketSize(Count current, size_t i) const { |
831 return 1; | 850 return 1; |
832 } | 851 } |
833 | 852 |
834 // static | 853 // static |
854 HistogramBase* CustomHistogram::DeserializeHistogramInfo(PickleIterator* iter) { | |
855 string histogram_name; | |
856 int flags; | |
857 int declared_min; | |
858 int declared_max; | |
859 uint64 bucket_count; | |
860 uint32 range_checksum; | |
861 | |
862 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | |
863 &declared_max, &bucket_count, &range_checksum)) { | |
864 return NULL; | |
865 } | |
866 | |
867 // First and last ranges are not serialized. | |
868 vector<Sample> sample_ranges(bucket_count - 1); | |
869 | |
870 for (size_t i = 0; i < sample_ranges.size(); ++i) { | |
871 if (!iter->ReadInt(&sample_ranges[i])) | |
872 return NULL; | |
873 } | |
874 | |
875 HistogramBase* histogram = CustomHistogram::FactoryGet( | |
876 histogram_name, sample_ranges, flags); | |
877 if (!ValidateRangeChecksum(histogram, range_checksum)) { | |
878 // The serialized histogram might be corrupted. | |
879 return NULL; | |
880 } | |
881 return histogram; | |
882 } | |
883 | |
884 // static | |
835 bool CustomHistogram::ValidateCustomRanges( | 885 bool CustomHistogram::ValidateCustomRanges( |
836 const vector<Sample>& custom_ranges) { | 886 const vector<Sample>& custom_ranges) { |
837 bool has_valid_range = false; | 887 bool has_valid_range = false; |
838 for (size_t i = 0; i < custom_ranges.size(); i++) { | 888 for (size_t i = 0; i < custom_ranges.size(); i++) { |
839 Sample sample = custom_ranges[i]; | 889 Sample sample = custom_ranges[i]; |
840 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) | 890 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) |
841 return false; | 891 return false; |
842 if (sample != 0) | 892 if (sample != 0) |
843 has_valid_range = true; | 893 has_valid_range = true; |
844 } | 894 } |
(...skipping 12 matching lines...) Expand all Loading... | |
857 | 907 |
858 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); | 908 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); |
859 for (size_t i = 0; i < ranges.size(); i++) { | 909 for (size_t i = 0; i < ranges.size(); i++) { |
860 bucket_ranges->set_range(i, ranges[i]); | 910 bucket_ranges->set_range(i, ranges[i]); |
861 } | 911 } |
862 bucket_ranges->ResetChecksum(); | 912 bucket_ranges->ResetChecksum(); |
863 return bucket_ranges; | 913 return bucket_ranges; |
864 } | 914 } |
865 | 915 |
866 } // namespace base | 916 } // namespace base |
OLD | NEW |