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

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

Issue 4349002: Revert 64687 - Try to detect internal corruption of histogram instances.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 1 month 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_unittest.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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 } 54 }
55 55
56 Histogram::Histogram(const std::string& name, Sample minimum, 56 Histogram::Histogram(const std::string& name, Sample minimum,
57 Sample maximum, size_t bucket_count) 57 Sample maximum, size_t bucket_count)
58 : histogram_name_(name), 58 : histogram_name_(name),
59 declared_min_(minimum), 59 declared_min_(minimum),
60 declared_max_(maximum), 60 declared_max_(maximum),
61 bucket_count_(bucket_count), 61 bucket_count_(bucket_count),
62 flags_(kNoFlags), 62 flags_(kNoFlags),
63 ranges_(bucket_count + 1, 0), 63 ranges_(bucket_count + 1, 0),
64 range_checksum_(0),
65 sample_() { 64 sample_() {
66 Initialize(); 65 Initialize();
67 } 66 }
68 67
69 Histogram::Histogram(const std::string& name, TimeDelta minimum, 68 Histogram::Histogram(const std::string& name, TimeDelta minimum,
70 TimeDelta maximum, size_t bucket_count) 69 TimeDelta maximum, size_t bucket_count)
71 : histogram_name_(name), 70 : histogram_name_(name),
72 declared_min_(static_cast<int> (minimum.InMilliseconds())), 71 declared_min_(static_cast<int> (minimum.InMilliseconds())),
73 declared_max_(static_cast<int> (maximum.InMilliseconds())), 72 declared_max_(static_cast<int> (maximum.InMilliseconds())),
74 bucket_count_(bucket_count), 73 bucket_count_(bucket_count),
75 flags_(kNoFlags), 74 flags_(kNoFlags),
76 ranges_(bucket_count + 1, 0), 75 ranges_(bucket_count + 1, 0),
77 range_checksum_(0),
78 sample_() { 76 sample_() {
79 Initialize(); 77 Initialize();
80 } 78 }
81 79
82 Histogram::~Histogram() { 80 Histogram::~Histogram() {
83 if (StatisticsRecorder::dump_on_exit()) { 81 if (StatisticsRecorder::dump_on_exit()) {
84 std::string output; 82 std::string output;
85 WriteAscii(true, "\n", &output); 83 WriteAscii(true, "\n", &output);
86 LOG(INFO) << output; 84 LOG(INFO) << output;
87 } 85 }
88 86
89 // Just to make sure most derived class did this properly... 87 // Just to make sure most derived class did this properly...
90 DCHECK(ValidateBucketRanges()); 88 DCHECK(ValidateBucketRanges());
91 DCHECK(HasValidRangeChecksum());
92 } 89 }
93 90
94 bool Histogram::PrintEmptyBucket(size_t index) const { 91 bool Histogram::PrintEmptyBucket(size_t index) const {
95 return true; 92 return true;
96 } 93 }
97 94
98 void Histogram::Add(int value) { 95 void Histogram::Add(int value) {
99 if (value > kSampleType_MAX - 1) 96 if (value > kSampleType_MAX - 1)
100 value = kSampleType_MAX - 1; 97 value = kSampleType_MAX - 1;
101 if (value < 0) 98 if (value < 0)
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 ranges_[bucket_count_] = kSampleType_MAX; 211 ranges_[bucket_count_] = kSampleType_MAX;
215 InitializeBucketRange(); 212 InitializeBucketRange();
216 DCHECK(ValidateBucketRanges()); 213 DCHECK(ValidateBucketRanges());
217 StatisticsRecorder::Register(this); 214 StatisticsRecorder::Register(this);
218 } 215 }
219 216
220 // Calculate what range of values are held in each bucket. 217 // Calculate what range of values are held in each bucket.
221 // We have to be careful that we don't pick a ratio between starting points in 218 // We have to be careful that we don't pick a ratio between starting points in
222 // consecutive buckets that is sooo small, that the integer bounds are the same 219 // consecutive buckets that is sooo small, that the integer bounds are the same
223 // (effectively making one bucket get no values). We need to avoid: 220 // (effectively making one bucket get no values). We need to avoid:
224 // ranges_[i] == ranges_[i + 1] 221 // (ranges_[i] == ranges_[i + 1]
225 // To avoid that, we just do a fine-grained bucket width as far as we need to 222 // To avoid that, we just do a fine-grained bucket width as far as we need to
226 // until we get a ratio that moves us along at least 2 units at a time. From 223 // until we get a ratio that moves us along at least 2 units at a time. From
227 // that bucket onward we do use the exponential growth of buckets. 224 // that bucket onward we do use the exponential growth of buckets.
228 void Histogram::InitializeBucketRange() { 225 void Histogram::InitializeBucketRange() {
229 double log_max = log(static_cast<double>(declared_max())); 226 double log_max = log(static_cast<double>(declared_max()));
230 double log_ratio; 227 double log_ratio;
231 double log_next; 228 double log_next;
232 size_t bucket_index = 1; 229 size_t bucket_index = 1;
233 Sample current = declared_min(); 230 Sample current = declared_min();
234 SetBucketRange(bucket_index, current); 231 SetBucketRange(bucket_index, current);
235 while (bucket_count() > ++bucket_index) { 232 while (bucket_count() > ++bucket_index) {
236 double log_current; 233 double log_current;
237 log_current = log(static_cast<double>(current)); 234 log_current = log(static_cast<double>(current));
238 // Calculate the count'th root of the range. 235 // Calculate the count'th root of the range.
239 log_ratio = (log_max - log_current) / (bucket_count() - bucket_index); 236 log_ratio = (log_max - log_current) / (bucket_count() - bucket_index);
240 // See where the next bucket would start. 237 // See where the next bucket would start.
241 log_next = log_current + log_ratio; 238 log_next = log_current + log_ratio;
242 int next; 239 int next;
243 next = static_cast<int>(floor(exp(log_next) + 0.5)); 240 next = static_cast<int>(floor(exp(log_next) + 0.5));
244 if (next > current) 241 if (next > current)
245 current = next; 242 current = next;
246 else 243 else
247 ++current; // Just do a narrow bucket, and keep trying. 244 ++current; // Just do a narrow bucket, and keep trying.
248 SetBucketRange(bucket_index, current); 245 SetBucketRange(bucket_index, current);
249 } 246 }
250 ResetRangeChecksum();
251 247
252 DCHECK_EQ(bucket_count(), bucket_index); 248 DCHECK_EQ(bucket_count(), bucket_index);
253 } 249 }
254 250
255 size_t Histogram::BucketIndex(Sample value) const { 251 size_t Histogram::BucketIndex(Sample value) const {
256 // Use simple binary search. This is very general, but there are better 252 // Use simple binary search. This is very general, but there are better
257 // approaches if we knew that the buckets were linearly distributed. 253 // approaches if we knew that the buckets were linearly distributed.
258 DCHECK_LE(ranges(0), value); 254 DCHECK_LE(ranges(0), value);
259 DCHECK_GT(ranges(bucket_count()), value); 255 DCHECK_GT(ranges(bucket_count()), value);
260 size_t under = 0; 256 size_t under = 0;
(...skipping 23 matching lines...) Expand all
284 // not have 0-graphical-height buckets. 280 // not have 0-graphical-height buckets.
285 double Histogram::GetBucketSize(Count current, size_t i) const { 281 double Histogram::GetBucketSize(Count current, size_t i) const {
286 DCHECK_GT(ranges(i + 1), ranges(i)); 282 DCHECK_GT(ranges(i + 1), ranges(i));
287 static const double kTransitionWidth = 5; 283 static const double kTransitionWidth = 5;
288 double denominator = ranges(i + 1) - ranges(i); 284 double denominator = ranges(i + 1) - ranges(i);
289 if (denominator > kTransitionWidth) 285 if (denominator > kTransitionWidth)
290 denominator = kTransitionWidth; // Stop trying to normalize. 286 denominator = kTransitionWidth; // Stop trying to normalize.
291 return current/denominator; 287 return current/denominator;
292 } 288 }
293 289
294 void Histogram::ResetRangeChecksum() {
295 range_checksum_ = CalculateRangeChecksum();
296 }
297
298 bool Histogram::HasValidRangeChecksum() const {
299 return CalculateRangeChecksum() == range_checksum_;
300 }
301
302 Histogram::Sample Histogram::CalculateRangeChecksum() const {
303 DCHECK_EQ(ranges_.size(), bucket_count() + 1);
304 Sample checksum = 0;
305 for (size_t index = 0; index < bucket_count(); ++index) {
306 checksum += ranges(index);
307 }
308 return checksum;
309 }
310
311 //------------------------------------------------------------------------------ 290 //------------------------------------------------------------------------------
312 // The following two methods can be overridden to provide a thread safe 291 // The following two methods can be overridden to provide a thread safe
313 // version of this class. The cost of locking is low... but an error in each 292 // version of this class. The cost of locking is low... but an error in each
314 // of these methods has minimal impact. For now, I'll leave this unlocked, 293 // of these methods has minimal impact. For now, I'll leave this unlocked,
315 // and I don't believe I can loose more than a count or two. 294 // and I don't believe I can loose more than a count or two.
316 // The vectors are NOT reallocated, so there is no risk of them moving around. 295 // The vectors are NOT reallocated, so there is no risk of them moving around.
317 296
318 // Update histogram data with new sample. 297 // Update histogram data with new sample.
319 void Histogram::Accumulate(Sample value, Count count, size_t index) { 298 void Histogram::Accumulate(Sample value, Count count, size_t index) {
320 // Note locking not done in this version!!! 299 // Note locking not done in this version!!!
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 // static 410 // static
432 std::string Histogram::SerializeHistogramInfo(const Histogram& histogram, 411 std::string Histogram::SerializeHistogramInfo(const Histogram& histogram,
433 const SampleSet& snapshot) { 412 const SampleSet& snapshot) {
434 DCHECK_NE(NOT_VALID_IN_RENDERER, histogram.histogram_type()); 413 DCHECK_NE(NOT_VALID_IN_RENDERER, histogram.histogram_type());
435 414
436 Pickle pickle; 415 Pickle pickle;
437 pickle.WriteString(histogram.histogram_name()); 416 pickle.WriteString(histogram.histogram_name());
438 pickle.WriteInt(histogram.declared_min()); 417 pickle.WriteInt(histogram.declared_min());
439 pickle.WriteInt(histogram.declared_max()); 418 pickle.WriteInt(histogram.declared_max());
440 pickle.WriteSize(histogram.bucket_count()); 419 pickle.WriteSize(histogram.bucket_count());
441 pickle.WriteInt(histogram.range_checksum());
442 pickle.WriteInt(histogram.histogram_type()); 420 pickle.WriteInt(histogram.histogram_type());
443 pickle.WriteInt(histogram.flags()); 421 pickle.WriteInt(histogram.flags());
444 422
445 snapshot.Serialize(&pickle); 423 snapshot.Serialize(&pickle);
446 return std::string(static_cast<const char*>(pickle.data()), pickle.size()); 424 return std::string(static_cast<const char*>(pickle.data()), pickle.size());
447 } 425 }
448 426
449 // static 427 // static
450 bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) { 428 bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) {
451 if (histogram_info.empty()) { 429 if (histogram_info.empty()) {
452 return false; 430 return false;
453 } 431 }
454 432
455 Pickle pickle(histogram_info.data(), 433 Pickle pickle(histogram_info.data(),
456 static_cast<int>(histogram_info.size())); 434 static_cast<int>(histogram_info.size()));
457 std::string histogram_name; 435 void* iter = NULL;
436 size_t bucket_count;
458 int declared_min; 437 int declared_min;
459 int declared_max; 438 int declared_max;
460 size_t bucket_count;
461 int range_checksum;
462 int histogram_type; 439 int histogram_type;
463 int pickle_flags; 440 int pickle_flags;
441 std::string histogram_name;
464 SampleSet sample; 442 SampleSet sample;
465 443
466 void* iter = NULL;
467 if (!pickle.ReadString(&iter, &histogram_name) || 444 if (!pickle.ReadString(&iter, &histogram_name) ||
468 !pickle.ReadInt(&iter, &declared_min) || 445 !pickle.ReadInt(&iter, &declared_min) ||
469 !pickle.ReadInt(&iter, &declared_max) || 446 !pickle.ReadInt(&iter, &declared_max) ||
470 !pickle.ReadSize(&iter, &bucket_count) || 447 !pickle.ReadSize(&iter, &bucket_count) ||
471 !pickle.ReadInt(&iter, &range_checksum) ||
472 !pickle.ReadInt(&iter, &histogram_type) || 448 !pickle.ReadInt(&iter, &histogram_type) ||
473 !pickle.ReadInt(&iter, &pickle_flags) || 449 !pickle.ReadInt(&iter, &pickle_flags) ||
474 !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) { 450 !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) {
475 LOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name; 451 LOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name;
476 return false; 452 return false;
477 } 453 }
478 DCHECK(pickle_flags & kIPCSerializationSourceFlag); 454 DCHECK(pickle_flags & kIPCSerializationSourceFlag);
479 // Since these fields may have come from an untrusted renderer, do additional 455 // Since these fields may have come from an untrusted renderer, do additional
480 // checks above and beyond those in Histogram::Initialize() 456 // checks above and beyond those in Histogram::Initialize()
481 if (declared_max <= 0 || declared_min <= 0 || declared_max < declared_min || 457 if (declared_max <= 0 || declared_min <= 0 || declared_max < declared_min ||
(...skipping 18 matching lines...) Expand all
500 render_histogram = BooleanHistogram::FactoryGet(histogram_name, flags); 476 render_histogram = BooleanHistogram::FactoryGet(histogram_name, flags);
501 } else { 477 } else {
502 LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " 478 LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: "
503 << histogram_type; 479 << histogram_type;
504 return false; 480 return false;
505 } 481 }
506 482
507 DCHECK_EQ(render_histogram->declared_min(), declared_min); 483 DCHECK_EQ(render_histogram->declared_min(), declared_min);
508 DCHECK_EQ(render_histogram->declared_max(), declared_max); 484 DCHECK_EQ(render_histogram->declared_max(), declared_max);
509 DCHECK_EQ(render_histogram->bucket_count(), bucket_count); 485 DCHECK_EQ(render_histogram->bucket_count(), bucket_count);
510 DCHECK_EQ(render_histogram->range_checksum(), range_checksum);
511 DCHECK_EQ(render_histogram->histogram_type(), histogram_type); 486 DCHECK_EQ(render_histogram->histogram_type(), histogram_type);
512 487
513 if (render_histogram->flags() & kIPCSerializationSourceFlag) { 488 if (render_histogram->flags() & kIPCSerializationSourceFlag) {
514 DVLOG(1) << "Single process mode, histogram observed and not copied: " 489 DVLOG(1) << "Single process mode, histogram observed and not copied: "
515 << histogram_name; 490 << histogram_name;
516 } else { 491 } else {
517 DCHECK_EQ(flags & render_histogram->flags(), flags); 492 DCHECK_EQ(flags & render_histogram->flags(), flags);
518 render_histogram->AddSampleSet(sample); 493 render_histogram->AddSampleSet(sample);
519 } 494 }
520 495
521 return true; 496 return true;
522 } 497 }
523 498
524 //------------------------------------------------------------------------------ 499 //------------------------------------------------------------------------------
525 // Methods for the validating a sample and a related histogram.
526 //------------------------------------------------------------------------------
527
528 Histogram::Inconsistencies Histogram::FindCorruption(
529 const SampleSet& snapshot) const {
530 int inconsistencies = NO_INCONSISTENCIES;
531 Sample previous_range = -1; // Bottom range is always 0.
532 Sample checksum = 0;
533 int64 count = 0;
534 for (size_t index = 0; index < bucket_count(); ++index) {
535 count += snapshot.counts(index);
536 int new_range = ranges(index);
537 checksum += new_range;
538 if (previous_range >= new_range)
539 inconsistencies |= BUCKET_ORDER_ERROR;
540 previous_range = new_range;
541 }
542
543 if (checksum != range_checksum_)
544 inconsistencies |= RANGE_CHECKSUM_ERROR;
545
546 int64 delta64 = snapshot.redundant_count() - count;
547 if (delta64 != 0) {
548 int delta = static_cast<int>(delta64);
549 if (delta != delta64)
550 delta = INT_MAX; // Flag all giant errors as INT_MAX.
551 // Since snapshots of histograms are taken asynchronously relative to
552 // sampling (and snapped from different threads), it is pretty likely that
553 // we'll catch a redundant count that doesn't match the sample count. We
554 // allow for a certain amount of slop before flagging this as an
555 // inconsistency. Even with an inconsistency, we'll snapshot it again (for
556 // UMA in about a half hour, so we'll eventually get the data, if it was
557 // not the result of a corruption. If histograms show that 1 is "too tight"
558 // then we may try to use 2 or 3 for this slop value.
559 const int kCommonRaceBasedCountMismatch = 1;
560 if (delta > 0) {
561 UMA_HISTOGRAM_COUNTS("Histogram.InconsistentCountHigh", delta);
562 if (delta > kCommonRaceBasedCountMismatch)
563 inconsistencies |= COUNT_HIGH_ERROR;
564 } else {
565 DCHECK_GT(0, delta);
566 UMA_HISTOGRAM_COUNTS("Histogram.InconsistentCountLow", -delta);
567 if (-delta > kCommonRaceBasedCountMismatch)
568 inconsistencies |= COUNT_LOW_ERROR;
569 }
570 }
571 return static_cast<Inconsistencies>(inconsistencies);
572 }
573
574 //------------------------------------------------------------------------------
575 // Methods for the Histogram::SampleSet class 500 // Methods for the Histogram::SampleSet class
576 //------------------------------------------------------------------------------ 501 //------------------------------------------------------------------------------
577 502
578 Histogram::SampleSet::SampleSet() 503 Histogram::SampleSet::SampleSet()
579 : counts_(), 504 : counts_(),
580 sum_(0), 505 sum_(0),
581 square_sum_(0), 506 square_sum_(0) {
582 redundant_count_(0) {
583 } 507 }
584 508
585 Histogram::SampleSet::~SampleSet() { 509 Histogram::SampleSet::~SampleSet() {
586 } 510 }
587 511
588 void Histogram::SampleSet::Resize(const Histogram& histogram) { 512 void Histogram::SampleSet::Resize(const Histogram& histogram) {
589 counts_.resize(histogram.bucket_count(), 0); 513 counts_.resize(histogram.bucket_count(), 0);
590 } 514 }
591 515
592 void Histogram::SampleSet::CheckSize(const Histogram& histogram) const { 516 void Histogram::SampleSet::CheckSize(const Histogram& histogram) const {
593 DCHECK_EQ(histogram.bucket_count(), counts_.size()); 517 DCHECK_EQ(histogram.bucket_count(), counts_.size());
594 } 518 }
595 519
596 520
597 void Histogram::SampleSet::Accumulate(Sample value, Count count, 521 void Histogram::SampleSet::Accumulate(Sample value, Count count,
598 size_t index) { 522 size_t index) {
599 DCHECK(count == 1 || count == -1); 523 DCHECK(count == 1 || count == -1);
600 counts_[index] += count; 524 counts_[index] += count;
601 sum_ += count * value; 525 sum_ += count * value;
602 square_sum_ += (count * value) * static_cast<int64>(value); 526 square_sum_ += (count * value) * static_cast<int64>(value);
603 redundant_count_ += count;
604 DCHECK_GE(counts_[index], 0); 527 DCHECK_GE(counts_[index], 0);
605 DCHECK_GE(sum_, 0); 528 DCHECK_GE(sum_, 0);
606 DCHECK_GE(square_sum_, 0); 529 DCHECK_GE(square_sum_, 0);
607 DCHECK_GE(redundant_count_, 0);
608 } 530 }
609 531
610 Count Histogram::SampleSet::TotalCount() const { 532 Count Histogram::SampleSet::TotalCount() const {
611 Count total = 0; 533 Count total = 0;
612 for (Counts::const_iterator it = counts_.begin(); 534 for (Counts::const_iterator it = counts_.begin();
613 it != counts_.end(); 535 it != counts_.end();
614 ++it) { 536 ++it) {
615 total += *it; 537 total += *it;
616 } 538 }
617 DCHECK_EQ(total, redundant_count_);
618 return total; 539 return total;
619 } 540 }
620 541
621 void Histogram::SampleSet::Add(const SampleSet& other) { 542 void Histogram::SampleSet::Add(const SampleSet& other) {
622 DCHECK_EQ(counts_.size(), other.counts_.size()); 543 DCHECK_EQ(counts_.size(), other.counts_.size());
623 sum_ += other.sum_; 544 sum_ += other.sum_;
624 square_sum_ += other.square_sum_; 545 square_sum_ += other.square_sum_;
625 redundant_count_ += other.redundant_count_;
626 for (size_t index = 0; index < counts_.size(); ++index) 546 for (size_t index = 0; index < counts_.size(); ++index)
627 counts_[index] += other.counts_[index]; 547 counts_[index] += other.counts_[index];
628 } 548 }
629 549
630 void Histogram::SampleSet::Subtract(const SampleSet& other) { 550 void Histogram::SampleSet::Subtract(const SampleSet& other) {
631 DCHECK_EQ(counts_.size(), other.counts_.size()); 551 DCHECK_EQ(counts_.size(), other.counts_.size());
632 // Note: Race conditions in snapshotting a sum or square_sum may lead to 552 // Note: Race conditions in snapshotting a sum or square_sum may lead to
633 // (temporary) negative values when snapshots are later combined (and deltas 553 // (temporary) negative values when snapshots are later combined (and deltas
634 // calculated). As a result, we don't currently CHCEK() for positive values. 554 // calculated). As a result, we don't currently CHCEK() for positive values.
635 sum_ -= other.sum_; 555 sum_ -= other.sum_;
636 square_sum_ -= other.square_sum_; 556 square_sum_ -= other.square_sum_;
637 redundant_count_ -= other.redundant_count_;
638 for (size_t index = 0; index < counts_.size(); ++index) { 557 for (size_t index = 0; index < counts_.size(); ++index) {
639 counts_[index] -= other.counts_[index]; 558 counts_[index] -= other.counts_[index];
640 DCHECK_GE(counts_[index], 0); 559 DCHECK_GE(counts_[index], 0);
641 } 560 }
642 } 561 }
643 562
644 bool Histogram::SampleSet::Serialize(Pickle* pickle) const { 563 bool Histogram::SampleSet::Serialize(Pickle* pickle) const {
645 pickle->WriteInt64(sum_); 564 pickle->WriteInt64(sum_);
646 pickle->WriteInt64(square_sum_); 565 pickle->WriteInt64(square_sum_);
647 pickle->WriteInt64(redundant_count_);
648 pickle->WriteSize(counts_.size()); 566 pickle->WriteSize(counts_.size());
649 567
650 for (size_t index = 0; index < counts_.size(); ++index) { 568 for (size_t index = 0; index < counts_.size(); ++index) {
651 pickle->WriteInt(counts_[index]); 569 pickle->WriteInt(counts_[index]);
652 } 570 }
653 571
654 return true; 572 return true;
655 } 573 }
656 574
657 bool Histogram::SampleSet::Deserialize(void** iter, const Pickle& pickle) { 575 bool Histogram::SampleSet::Deserialize(void** iter, const Pickle& pickle) {
658 DCHECK_EQ(counts_.size(), 0u); 576 DCHECK_EQ(counts_.size(), 0u);
659 DCHECK_EQ(sum_, 0); 577 DCHECK_EQ(sum_, 0);
660 DCHECK_EQ(square_sum_, 0); 578 DCHECK_EQ(square_sum_, 0);
661 DCHECK_EQ(redundant_count_, 0);
662 579
663 size_t counts_size; 580 size_t counts_size;
664 581
665 if (!pickle.ReadInt64(iter, &sum_) || 582 if (!pickle.ReadInt64(iter, &sum_) ||
666 !pickle.ReadInt64(iter, &square_sum_) || 583 !pickle.ReadInt64(iter, &square_sum_) ||
667 !pickle.ReadInt64(iter, &redundant_count_) ||
668 !pickle.ReadSize(iter, &counts_size)) { 584 !pickle.ReadSize(iter, &counts_size)) {
669 return false; 585 return false;
670 } 586 }
671 587
672 if (counts_size == 0) 588 if (counts_size == 0)
673 return false; 589 return false;
674 590
675 int count = 0;
676 for (size_t index = 0; index < counts_size; ++index) { 591 for (size_t index = 0; index < counts_size; ++index) {
677 int i; 592 int i;
678 if (!pickle.ReadInt(iter, &i)) 593 if (!pickle.ReadInt(iter, &i))
679 return false; 594 return false;
680 counts_.push_back(i); 595 counts_.push_back(i);
681 count += i;
682 } 596 }
683 DCHECK_EQ(count, redundant_count_); 597
684 return count == redundant_count_; 598 return true;
685 } 599 }
686 600
687 //------------------------------------------------------------------------------ 601 //------------------------------------------------------------------------------
688 // LinearHistogram: This histogram uses a traditional set of evenly spaced 602 // LinearHistogram: This histogram uses a traditional set of evenly spaced
689 // buckets. 603 // buckets.
690 //------------------------------------------------------------------------------ 604 //------------------------------------------------------------------------------
691 605
692 scoped_refptr<Histogram> LinearHistogram::FactoryGet(const std::string& name, 606 scoped_refptr<Histogram> LinearHistogram::FactoryGet(const std::string& name,
693 Sample minimum, 607 Sample minimum,
694 Sample maximum, 608 Sample maximum,
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 void LinearHistogram::InitializeBucketRange() { 687 void LinearHistogram::InitializeBucketRange() {
774 DCHECK_GT(declared_min(), 0); // 0 is the underflow bucket here. 688 DCHECK_GT(declared_min(), 0); // 0 is the underflow bucket here.
775 double min = declared_min(); 689 double min = declared_min();
776 double max = declared_max(); 690 double max = declared_max();
777 size_t i; 691 size_t i;
778 for (i = 1; i < bucket_count(); ++i) { 692 for (i = 1; i < bucket_count(); ++i) {
779 double linear_range = (min * (bucket_count() -1 - i) + max * (i - 1)) / 693 double linear_range = (min * (bucket_count() -1 - i) + max * (i - 1)) /
780 (bucket_count() - 2); 694 (bucket_count() - 2);
781 SetBucketRange(i, static_cast<int> (linear_range + 0.5)); 695 SetBucketRange(i, static_cast<int> (linear_range + 0.5));
782 } 696 }
783 ResetRangeChecksum();
784 } 697 }
785 698
786 double LinearHistogram::GetBucketSize(Count current, size_t i) const { 699 double LinearHistogram::GetBucketSize(Count current, size_t i) const {
787 DCHECK_GT(ranges(i + 1), ranges(i)); 700 DCHECK_GT(ranges(i + 1), ranges(i));
788 // Adjacent buckets with different widths would have "surprisingly" many (few) 701 // Adjacent buckets with different widths would have "surprisingly" many (few)
789 // samples in a histogram if we didn't normalize this way. 702 // samples in a histogram if we didn't normalize this way.
790 double denominator = ranges(i + 1) - ranges(i); 703 double denominator = ranges(i + 1) - ranges(i);
791 return current/denominator; 704 return current/denominator;
792 } 705 }
793 706
(...skipping 26 matching lines...) Expand all
820 BooleanHistogram::BooleanHistogram(const std::string& name) 733 BooleanHistogram::BooleanHistogram(const std::string& name)
821 : LinearHistogram(name, 1, 2, 3) { 734 : LinearHistogram(name, 1, 2, 3) {
822 } 735 }
823 736
824 //------------------------------------------------------------------------------ 737 //------------------------------------------------------------------------------
825 // CustomHistogram: 738 // CustomHistogram:
826 //------------------------------------------------------------------------------ 739 //------------------------------------------------------------------------------
827 740
828 scoped_refptr<Histogram> CustomHistogram::FactoryGet( 741 scoped_refptr<Histogram> CustomHistogram::FactoryGet(
829 const std::string& name, 742 const std::string& name,
830 const std::vector<Sample>& custom_ranges, 743 const std::vector<int>& custom_ranges,
831 Flags flags) { 744 Flags flags) {
832 scoped_refptr<Histogram> histogram(NULL); 745 scoped_refptr<Histogram> histogram(NULL);
833 746
834 // Remove the duplicates in the custom ranges array. 747 // Remove the duplicates in the custom ranges array.
835 std::vector<int> ranges = custom_ranges; 748 std::vector<int> ranges = custom_ranges;
836 ranges.push_back(0); // Ensure we have a zero value. 749 ranges.push_back(0); // Ensure we have a zero value.
837 std::sort(ranges.begin(), ranges.end()); 750 std::sort(ranges.begin(), ranges.end());
838 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end()); 751 ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end());
839 if (ranges.size() <= 1) { 752 if (ranges.size() <= 1) {
840 DCHECK(false); 753 DCHECK(false);
(...skipping 13 matching lines...) Expand all
854 ranges.size())); 767 ranges.size()));
855 histogram->SetFlags(flags); 768 histogram->SetFlags(flags);
856 return histogram; 769 return histogram;
857 } 770 }
858 771
859 Histogram::ClassType CustomHistogram::histogram_type() const { 772 Histogram::ClassType CustomHistogram::histogram_type() const {
860 return CUSTOM_HISTOGRAM; 773 return CUSTOM_HISTOGRAM;
861 } 774 }
862 775
863 CustomHistogram::CustomHistogram(const std::string& name, 776 CustomHistogram::CustomHistogram(const std::string& name,
864 const std::vector<Sample>& custom_ranges) 777 const std::vector<int>& custom_ranges)
865 : Histogram(name, custom_ranges[1], custom_ranges.back(), 778 : Histogram(name, custom_ranges[1], custom_ranges.back(),
866 custom_ranges.size()) { 779 custom_ranges.size()) {
867 DCHECK_GT(custom_ranges.size(), 1u); 780 DCHECK_GT(custom_ranges.size(), 1u);
868 DCHECK_EQ(custom_ranges[0], 0); 781 DCHECK_EQ(custom_ranges[0], 0);
869 ranges_vector_ = &custom_ranges; 782 ranges_vector_ = &custom_ranges;
870 InitializeBucketRange(); 783 InitializeBucketRange();
871 ranges_vector_ = NULL; 784 ranges_vector_ = NULL;
872 DCHECK(ValidateBucketRanges()); 785 DCHECK(ValidateBucketRanges());
873 } 786 }
874 787
875 void CustomHistogram::InitializeBucketRange() { 788 void CustomHistogram::InitializeBucketRange() {
876 DCHECK_LE(ranges_vector_->size(), bucket_count()); 789 DCHECK_LE(ranges_vector_->size(), bucket_count());
877 for (size_t index = 0; index < ranges_vector_->size(); ++index) 790 for (size_t index = 0; index < ranges_vector_->size(); ++index)
878 SetBucketRange(index, (*ranges_vector_)[index]); 791 SetBucketRange(index, (*ranges_vector_)[index]);
879 ResetRangeChecksum();
880 } 792 }
881 793
882 double CustomHistogram::GetBucketSize(Count current, size_t i) const { 794 double CustomHistogram::GetBucketSize(Count current, size_t i) const {
883 return 1; 795 return 1;
884 } 796 }
885 797
886 //------------------------------------------------------------------------------ 798 //------------------------------------------------------------------------------
887 // The next section handles global (central) support for all histograms, as well 799 // The next section handles global (central) support for all histograms, as well
888 // as startup/teardown of this service. 800 // as startup/teardown of this service.
889 //------------------------------------------------------------------------------ 801 //------------------------------------------------------------------------------
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 } 927 }
1016 928
1017 // static 929 // static
1018 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; 930 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;
1019 // static 931 // static
1020 Lock* StatisticsRecorder::lock_ = NULL; 932 Lock* StatisticsRecorder::lock_ = NULL;
1021 // static 933 // static
1022 bool StatisticsRecorder::dump_on_exit_ = false; 934 bool StatisticsRecorder::dump_on_exit_ = false;
1023 935
1024 } // namespace base 936 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/histogram.h ('k') | base/metrics/histogram_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698