| 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" |
| 11 | 11 |
| 12 #include <limits.h> |
| 12 #include <math.h> | 13 #include <math.h> |
| 13 | 14 |
| 14 #include <algorithm> | 15 #include <algorithm> |
| 15 #include <string> | 16 #include <string> |
| 16 | 17 |
| 17 #include "base/compiler_specific.h" | 18 #include "base/compiler_specific.h" |
| 18 #include "base/debug/alias.h" | 19 #include "base/debug/alias.h" |
| 19 #include "base/logging.h" | 20 #include "base/logging.h" |
| 20 #include "base/metrics/histogram_macros.h" | 21 #include "base/metrics/histogram_macros.h" |
| 21 #include "base/metrics/metrics_hashes.h" | 22 #include "base/metrics/metrics_hashes.h" |
| 22 #include "base/metrics/sample_vector.h" | 23 #include "base/metrics/sample_vector.h" |
| 23 #include "base/metrics/statistics_recorder.h" | 24 #include "base/metrics/statistics_recorder.h" |
| 24 #include "base/pickle.h" | 25 #include "base/pickle.h" |
| 25 #include "base/strings/string_util.h" | 26 #include "base/strings/string_util.h" |
| 26 #include "base/strings/stringprintf.h" | 27 #include "base/strings/stringprintf.h" |
| 27 #include "base/synchronization/lock.h" | 28 #include "base/synchronization/lock.h" |
| 28 #include "base/values.h" | 29 #include "base/values.h" |
| 29 | 30 |
| 30 namespace base { | 31 namespace base { |
| 31 | 32 |
| 32 namespace { | 33 namespace { |
| 33 | 34 |
| 34 bool ReadHistogramArguments(PickleIterator* iter, | 35 bool ReadHistogramArguments(PickleIterator* iter, |
| 35 std::string* histogram_name, | 36 std::string* histogram_name, |
| 36 int* flags, | 37 int* flags, |
| 37 int* declared_min, | 38 int* declared_min, |
| 38 int* declared_max, | 39 int* declared_max, |
| 39 size_t* bucket_count, | 40 size_t* bucket_count, |
| 40 uint32* range_checksum) { | 41 uint32_t* range_checksum) { |
| 41 if (!iter->ReadString(histogram_name) || | 42 if (!iter->ReadString(histogram_name) || |
| 42 !iter->ReadInt(flags) || | 43 !iter->ReadInt(flags) || |
| 43 !iter->ReadInt(declared_min) || | 44 !iter->ReadInt(declared_min) || |
| 44 !iter->ReadInt(declared_max) || | 45 !iter->ReadInt(declared_max) || |
| 45 !iter->ReadSizeT(bucket_count) || | 46 !iter->ReadSizeT(bucket_count) || |
| 46 !iter->ReadUInt32(range_checksum)) { | 47 !iter->ReadUInt32(range_checksum)) { |
| 47 DLOG(ERROR) << "Pickle error decoding Histogram: " << *histogram_name; | 48 DLOG(ERROR) << "Pickle error decoding Histogram: " << *histogram_name; |
| 48 return false; | 49 return false; |
| 49 } | 50 } |
| 50 | 51 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 61 | 62 |
| 62 // We use the arguments to find or create the local version of the histogram | 63 // We use the arguments to find or create the local version of the histogram |
| 63 // in this process, so we need to clear the IPC flag. | 64 // in this process, so we need to clear the IPC flag. |
| 64 DCHECK(*flags & HistogramBase::kIPCSerializationSourceFlag); | 65 DCHECK(*flags & HistogramBase::kIPCSerializationSourceFlag); |
| 65 *flags &= ~HistogramBase::kIPCSerializationSourceFlag; | 66 *flags &= ~HistogramBase::kIPCSerializationSourceFlag; |
| 66 | 67 |
| 67 return true; | 68 return true; |
| 68 } | 69 } |
| 69 | 70 |
| 70 bool ValidateRangeChecksum(const HistogramBase& histogram, | 71 bool ValidateRangeChecksum(const HistogramBase& histogram, |
| 71 uint32 range_checksum) { | 72 uint32_t range_checksum) { |
| 72 const Histogram& casted_histogram = | 73 const Histogram& casted_histogram = |
| 73 static_cast<const Histogram&>(histogram); | 74 static_cast<const Histogram&>(histogram); |
| 74 | 75 |
| 75 return casted_histogram.bucket_ranges()->checksum() == range_checksum; | 76 return casted_histogram.bucket_ranges()->checksum() == range_checksum; |
| 76 } | 77 } |
| 77 | 78 |
| 78 } // namespace | 79 } // namespace |
| 79 | 80 |
| 80 typedef HistogramBase::Count Count; | 81 typedef HistogramBase::Count Count; |
| 81 typedef HistogramBase::Sample Sample; | 82 typedef HistogramBase::Sample Sample; |
| 82 | 83 |
| 83 // static | 84 // static |
| 84 const size_t Histogram::kBucketCount_MAX = 16384u; | 85 const size_t Histogram::kBucketCount_MAX = 16384u; |
| 85 | 86 |
| 86 HistogramBase* Histogram::FactoryGet(const std::string& name, | 87 HistogramBase* Histogram::FactoryGet(const std::string& name, |
| 87 Sample minimum, | 88 Sample minimum, |
| 88 Sample maximum, | 89 Sample maximum, |
| 89 size_t bucket_count, | 90 size_t bucket_count, |
| 90 int32 flags) { | 91 int32_t flags) { |
| 91 bool valid_arguments = | 92 bool valid_arguments = |
| 92 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); | 93 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); |
| 93 DCHECK(valid_arguments); | 94 DCHECK(valid_arguments); |
| 94 | 95 |
| 95 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 96 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| 96 if (!histogram) { | 97 if (!histogram) { |
| 97 // To avoid racy destruction at shutdown, the following will be leaked. | 98 // To avoid racy destruction at shutdown, the following will be leaked. |
| 98 BucketRanges* ranges = new BucketRanges(bucket_count + 1); | 99 BucketRanges* ranges = new BucketRanges(bucket_count + 1); |
| 99 InitializeBucketRanges(minimum, maximum, ranges); | 100 InitializeBucketRanges(minimum, maximum, ranges); |
| 100 const BucketRanges* registered_ranges = | 101 const BucketRanges* registered_ranges = |
| (...skipping 18 matching lines...) Expand all Loading... |
| 119 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments"; | 120 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments"; |
| 120 return NULL; | 121 return NULL; |
| 121 } | 122 } |
| 122 return histogram; | 123 return histogram; |
| 123 } | 124 } |
| 124 | 125 |
| 125 HistogramBase* Histogram::FactoryTimeGet(const std::string& name, | 126 HistogramBase* Histogram::FactoryTimeGet(const std::string& name, |
| 126 TimeDelta minimum, | 127 TimeDelta minimum, |
| 127 TimeDelta maximum, | 128 TimeDelta maximum, |
| 128 size_t bucket_count, | 129 size_t bucket_count, |
| 129 int32 flags) { | 130 int32_t flags) { |
| 130 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), | 131 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), |
| 131 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, | 132 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, |
| 132 flags); | 133 flags); |
| 133 } | 134 } |
| 134 | 135 |
| 135 HistogramBase* Histogram::FactoryGet(const char* name, | 136 HistogramBase* Histogram::FactoryGet(const char* name, |
| 136 Sample minimum, | 137 Sample minimum, |
| 137 Sample maximum, | 138 Sample maximum, |
| 138 size_t bucket_count, | 139 size_t bucket_count, |
| 139 int32 flags) { | 140 int32_t flags) { |
| 140 return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags); | 141 return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags); |
| 141 } | 142 } |
| 142 | 143 |
| 143 HistogramBase* Histogram::FactoryTimeGet(const char* name, | 144 HistogramBase* Histogram::FactoryTimeGet(const char* name, |
| 144 TimeDelta minimum, | 145 TimeDelta minimum, |
| 145 TimeDelta maximum, | 146 TimeDelta maximum, |
| 146 size_t bucket_count, | 147 size_t bucket_count, |
| 147 int32 flags) { | 148 int32_t flags) { |
| 148 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, | 149 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, |
| 149 flags); | 150 flags); |
| 150 } | 151 } |
| 151 | 152 |
| 152 // Calculate what range of values are held in each bucket. | 153 // Calculate what range of values are held in each bucket. |
| 153 // We have to be careful that we don't pick a ratio between starting points in | 154 // We have to be careful that we don't pick a ratio between starting points in |
| 154 // consecutive buckets that is sooo small, that the integer bounds are the same | 155 // consecutive buckets that is sooo small, that the integer bounds are the same |
| 155 // (effectively making one bucket get no values). We need to avoid: | 156 // (effectively making one bucket get no values). We need to avoid: |
| 156 // ranges(i) == ranges(i + 1) | 157 // ranges(i) == ranges(i + 1) |
| 157 // To avoid that, we just do a fine-grained bucket width as far as we need to | 158 // To avoid that, we just do a fine-grained bucket width as far as we need to |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 for (size_t index = 0; index < bucket_count(); ++index) { | 198 for (size_t index = 0; index < bucket_count(); ++index) { |
| 198 int new_range = ranges(index); | 199 int new_range = ranges(index); |
| 199 if (previous_range >= new_range) | 200 if (previous_range >= new_range) |
| 200 inconsistencies |= BUCKET_ORDER_ERROR; | 201 inconsistencies |= BUCKET_ORDER_ERROR; |
| 201 previous_range = new_range; | 202 previous_range = new_range; |
| 202 } | 203 } |
| 203 | 204 |
| 204 if (!bucket_ranges()->HasValidChecksum()) | 205 if (!bucket_ranges()->HasValidChecksum()) |
| 205 inconsistencies |= RANGE_CHECKSUM_ERROR; | 206 inconsistencies |= RANGE_CHECKSUM_ERROR; |
| 206 | 207 |
| 207 int64 delta64 = samples.redundant_count() - samples.TotalCount(); | 208 int64_t delta64 = samples.redundant_count() - samples.TotalCount(); |
| 208 if (delta64 != 0) { | 209 if (delta64 != 0) { |
| 209 int delta = static_cast<int>(delta64); | 210 int delta = static_cast<int>(delta64); |
| 210 if (delta != delta64) | 211 if (delta != delta64) |
| 211 delta = INT_MAX; // Flag all giant errors as INT_MAX. | 212 delta = INT_MAX; // Flag all giant errors as INT_MAX. |
| 212 if (delta > 0) { | 213 if (delta > 0) { |
| 213 UMA_HISTOGRAM_COUNTS("Histogram.InconsistentCountHigh", delta); | 214 UMA_HISTOGRAM_COUNTS("Histogram.InconsistentCountHigh", delta); |
| 214 if (delta > kCommonRaceBasedCountMismatch) | 215 if (delta > kCommonRaceBasedCountMismatch) |
| 215 inconsistencies |= COUNT_HIGH_ERROR; | 216 inconsistencies |= COUNT_HIGH_ERROR; |
| 216 } else { | 217 } else { |
| 217 DCHECK_GT(0, delta); | 218 DCHECK_GT(0, delta); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 //------------------------------------------------------------------------------ | 372 //------------------------------------------------------------------------------ |
| 372 // Private methods | 373 // Private methods |
| 373 | 374 |
| 374 // static | 375 // static |
| 375 HistogramBase* Histogram::DeserializeInfoImpl(PickleIterator* iter) { | 376 HistogramBase* Histogram::DeserializeInfoImpl(PickleIterator* iter) { |
| 376 std::string histogram_name; | 377 std::string histogram_name; |
| 377 int flags; | 378 int flags; |
| 378 int declared_min; | 379 int declared_min; |
| 379 int declared_max; | 380 int declared_max; |
| 380 size_t bucket_count; | 381 size_t bucket_count; |
| 381 uint32 range_checksum; | 382 uint32_t range_checksum; |
| 382 | 383 |
| 383 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | 384 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
| 384 &declared_max, &bucket_count, &range_checksum)) { | 385 &declared_max, &bucket_count, &range_checksum)) { |
| 385 return NULL; | 386 return NULL; |
| 386 } | 387 } |
| 387 | 388 |
| 388 // Find or create the local version of the histogram in this process. | 389 // Find or create the local version of the histogram in this process. |
| 389 HistogramBase* histogram = Histogram::FactoryGet( | 390 HistogramBase* histogram = Histogram::FactoryGet( |
| 390 histogram_name, declared_min, declared_max, bucket_count, flags); | 391 histogram_name, declared_min, declared_max, bucket_count, flags); |
| 391 | 392 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 // Calculate largest print width needed for any of our bucket range displays. | 432 // Calculate largest print width needed for any of our bucket range displays. |
| 432 size_t print_width = 1; | 433 size_t print_width = 1; |
| 433 for (size_t i = 0; i < bucket_count(); ++i) { | 434 for (size_t i = 0; i < bucket_count(); ++i) { |
| 434 if (snapshot->GetCountAtIndex(i)) { | 435 if (snapshot->GetCountAtIndex(i)) { |
| 435 size_t width = GetAsciiBucketRange(i).size() + 1; | 436 size_t width = GetAsciiBucketRange(i).size() + 1; |
| 436 if (width > print_width) | 437 if (width > print_width) |
| 437 print_width = width; | 438 print_width = width; |
| 438 } | 439 } |
| 439 } | 440 } |
| 440 | 441 |
| 441 int64 remaining = sample_count; | 442 int64_t remaining = sample_count; |
| 442 int64 past = 0; | 443 int64_t past = 0; |
| 443 // Output the actual histogram graph. | 444 // Output the actual histogram graph. |
| 444 for (size_t i = 0; i < bucket_count(); ++i) { | 445 for (size_t i = 0; i < bucket_count(); ++i) { |
| 445 Count current = snapshot->GetCountAtIndex(i); | 446 Count current = snapshot->GetCountAtIndex(i); |
| 446 if (!current && !PrintEmptyBucket(i)) | 447 if (!current && !PrintEmptyBucket(i)) |
| 447 continue; | 448 continue; |
| 448 remaining -= current; | 449 remaining -= current; |
| 449 std::string range = GetAsciiBucketRange(i); | 450 std::string range = GetAsciiBucketRange(i); |
| 450 output->append(range); | 451 output->append(range); |
| 451 for (size_t j = 0; range.size() + j < print_width + 1; ++j) | 452 for (size_t j = 0; range.size() + j < print_width + 1; ++j) |
| 452 output->push_back(' '); | 453 output->push_back(' '); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 DCHECK_EQ(samples.sum(), 0); | 492 DCHECK_EQ(samples.sum(), 0); |
| 492 } else { | 493 } else { |
| 493 double average = static_cast<float>(samples.sum()) / sample_count; | 494 double average = static_cast<float>(samples.sum()) / sample_count; |
| 494 | 495 |
| 495 StringAppendF(output, ", average = %.1f", average); | 496 StringAppendF(output, ", average = %.1f", average); |
| 496 } | 497 } |
| 497 if (flags() & ~kHexRangePrintingFlag) | 498 if (flags() & ~kHexRangePrintingFlag) |
| 498 StringAppendF(output, " (flags = 0x%x)", flags() & ~kHexRangePrintingFlag); | 499 StringAppendF(output, " (flags = 0x%x)", flags() & ~kHexRangePrintingFlag); |
| 499 } | 500 } |
| 500 | 501 |
| 501 void Histogram::WriteAsciiBucketContext(const int64 past, | 502 void Histogram::WriteAsciiBucketContext(const int64_t past, |
| 502 const Count current, | 503 const Count current, |
| 503 const int64 remaining, | 504 const int64_t remaining, |
| 504 const size_t i, | 505 const size_t i, |
| 505 std::string* output) const { | 506 std::string* output) const { |
| 506 double scaled_sum = (past + current + remaining) / 100.0; | 507 double scaled_sum = (past + current + remaining) / 100.0; |
| 507 WriteAsciiBucketValue(current, scaled_sum, output); | 508 WriteAsciiBucketValue(current, scaled_sum, output); |
| 508 if (0 < i) { | 509 if (0 < i) { |
| 509 double percentage = past / scaled_sum; | 510 double percentage = past / scaled_sum; |
| 510 StringAppendF(output, " {%3.1f%%}", percentage); | 511 StringAppendF(output, " {%3.1f%%}", percentage); |
| 511 } | 512 } |
| 512 } | 513 } |
| 513 | 514 |
| 514 void Histogram::GetParameters(DictionaryValue* params) const { | 515 void Histogram::GetParameters(DictionaryValue* params) const { |
| 515 params->SetString("type", HistogramTypeToString(GetHistogramType())); | 516 params->SetString("type", HistogramTypeToString(GetHistogramType())); |
| 516 params->SetInteger("min", declared_min()); | 517 params->SetInteger("min", declared_min()); |
| 517 params->SetInteger("max", declared_max()); | 518 params->SetInteger("max", declared_max()); |
| 518 params->SetInteger("bucket_count", static_cast<int>(bucket_count())); | 519 params->SetInteger("bucket_count", static_cast<int>(bucket_count())); |
| 519 } | 520 } |
| 520 | 521 |
| 521 void Histogram::GetCountAndBucketData(Count* count, | 522 void Histogram::GetCountAndBucketData(Count* count, |
| 522 int64* sum, | 523 int64_t* sum, |
| 523 ListValue* buckets) const { | 524 ListValue* buckets) const { |
| 524 scoped_ptr<SampleVector> snapshot = SnapshotSampleVector(); | 525 scoped_ptr<SampleVector> snapshot = SnapshotSampleVector(); |
| 525 *count = snapshot->TotalCount(); | 526 *count = snapshot->TotalCount(); |
| 526 *sum = snapshot->sum(); | 527 *sum = snapshot->sum(); |
| 527 size_t index = 0; | 528 size_t index = 0; |
| 528 for (size_t i = 0; i < bucket_count(); ++i) { | 529 for (size_t i = 0; i < bucket_count(); ++i) { |
| 529 Sample count_at_index = snapshot->GetCountAtIndex(i); | 530 Sample count_at_index = snapshot->GetCountAtIndex(i); |
| 530 if (count_at_index > 0) { | 531 if (count_at_index > 0) { |
| 531 scoped_ptr<DictionaryValue> bucket_value(new DictionaryValue()); | 532 scoped_ptr<DictionaryValue> bucket_value(new DictionaryValue()); |
| 532 bucket_value->SetInteger("low", ranges(i)); | 533 bucket_value->SetInteger("low", ranges(i)); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 543 // LinearHistogram: This histogram uses a traditional set of evenly spaced | 544 // LinearHistogram: This histogram uses a traditional set of evenly spaced |
| 544 // buckets. | 545 // buckets. |
| 545 //------------------------------------------------------------------------------ | 546 //------------------------------------------------------------------------------ |
| 546 | 547 |
| 547 LinearHistogram::~LinearHistogram() {} | 548 LinearHistogram::~LinearHistogram() {} |
| 548 | 549 |
| 549 HistogramBase* LinearHistogram::FactoryGet(const std::string& name, | 550 HistogramBase* LinearHistogram::FactoryGet(const std::string& name, |
| 550 Sample minimum, | 551 Sample minimum, |
| 551 Sample maximum, | 552 Sample maximum, |
| 552 size_t bucket_count, | 553 size_t bucket_count, |
| 553 int32 flags) { | 554 int32_t flags) { |
| 554 return FactoryGetWithRangeDescription( | 555 return FactoryGetWithRangeDescription( |
| 555 name, minimum, maximum, bucket_count, flags, NULL); | 556 name, minimum, maximum, bucket_count, flags, NULL); |
| 556 } | 557 } |
| 557 | 558 |
| 558 HistogramBase* LinearHistogram::FactoryTimeGet(const std::string& name, | 559 HistogramBase* LinearHistogram::FactoryTimeGet(const std::string& name, |
| 559 TimeDelta minimum, | 560 TimeDelta minimum, |
| 560 TimeDelta maximum, | 561 TimeDelta maximum, |
| 561 size_t bucket_count, | 562 size_t bucket_count, |
| 562 int32 flags) { | 563 int32_t flags) { |
| 563 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), | 564 return FactoryGet(name, static_cast<Sample>(minimum.InMilliseconds()), |
| 564 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, | 565 static_cast<Sample>(maximum.InMilliseconds()), bucket_count, |
| 565 flags); | 566 flags); |
| 566 } | 567 } |
| 567 | 568 |
| 568 HistogramBase* LinearHistogram::FactoryGet(const char* name, | 569 HistogramBase* LinearHistogram::FactoryGet(const char* name, |
| 569 Sample minimum, | 570 Sample minimum, |
| 570 Sample maximum, | 571 Sample maximum, |
| 571 size_t bucket_count, | 572 size_t bucket_count, |
| 572 int32 flags) { | 573 int32_t flags) { |
| 573 return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags); | 574 return FactoryGet(std::string(name), minimum, maximum, bucket_count, flags); |
| 574 } | 575 } |
| 575 | 576 |
| 576 HistogramBase* LinearHistogram::FactoryTimeGet(const char* name, | 577 HistogramBase* LinearHistogram::FactoryTimeGet(const char* name, |
| 577 TimeDelta minimum, | 578 TimeDelta minimum, |
| 578 TimeDelta maximum, | 579 TimeDelta maximum, |
| 579 size_t bucket_count, | 580 size_t bucket_count, |
| 580 int32 flags) { | 581 int32_t flags) { |
| 581 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, | 582 return FactoryTimeGet(std::string(name), minimum, maximum, bucket_count, |
| 582 flags); | 583 flags); |
| 583 } | 584 } |
| 584 | 585 |
| 585 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( | 586 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( |
| 586 const std::string& name, | 587 const std::string& name, |
| 587 Sample minimum, | 588 Sample minimum, |
| 588 Sample maximum, | 589 Sample maximum, |
| 589 size_t bucket_count, | 590 size_t bucket_count, |
| 590 int32 flags, | 591 int32_t flags, |
| 591 const DescriptionPair descriptions[]) { | 592 const DescriptionPair descriptions[]) { |
| 592 bool valid_arguments = Histogram::InspectConstructionArguments( | 593 bool valid_arguments = Histogram::InspectConstructionArguments( |
| 593 name, &minimum, &maximum, &bucket_count); | 594 name, &minimum, &maximum, &bucket_count); |
| 594 DCHECK(valid_arguments); | 595 DCHECK(valid_arguments); |
| 595 | 596 |
| 596 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 597 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| 597 if (!histogram) { | 598 if (!histogram) { |
| 598 // To avoid racy destruction at shutdown, the following will be leaked. | 599 // To avoid racy destruction at shutdown, the following will be leaked. |
| 599 BucketRanges* ranges = new BucketRanges(bucket_count + 1); | 600 BucketRanges* ranges = new BucketRanges(bucket_count + 1); |
| 600 InitializeBucketRanges(minimum, maximum, ranges); | 601 InitializeBucketRanges(minimum, maximum, ranges); |
| 601 const BucketRanges* registered_ranges = | 602 const BucketRanges* registered_ranges = |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 ranges->ResetChecksum(); | 679 ranges->ResetChecksum(); |
| 679 } | 680 } |
| 680 | 681 |
| 681 // static | 682 // static |
| 682 HistogramBase* LinearHistogram::DeserializeInfoImpl(PickleIterator* iter) { | 683 HistogramBase* LinearHistogram::DeserializeInfoImpl(PickleIterator* iter) { |
| 683 std::string histogram_name; | 684 std::string histogram_name; |
| 684 int flags; | 685 int flags; |
| 685 int declared_min; | 686 int declared_min; |
| 686 int declared_max; | 687 int declared_max; |
| 687 size_t bucket_count; | 688 size_t bucket_count; |
| 688 uint32 range_checksum; | 689 uint32_t range_checksum; |
| 689 | 690 |
| 690 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | 691 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
| 691 &declared_max, &bucket_count, &range_checksum)) { | 692 &declared_max, &bucket_count, &range_checksum)) { |
| 692 return NULL; | 693 return NULL; |
| 693 } | 694 } |
| 694 | 695 |
| 695 HistogramBase* histogram = LinearHistogram::FactoryGet( | 696 HistogramBase* histogram = LinearHistogram::FactoryGet( |
| 696 histogram_name, declared_min, declared_max, bucket_count, flags); | 697 histogram_name, declared_min, declared_max, bucket_count, flags); |
| 697 if (!ValidateRangeChecksum(*histogram, range_checksum)) { | 698 if (!ValidateRangeChecksum(*histogram, range_checksum)) { |
| 698 // The serialized histogram might be corrupted. | 699 // The serialized histogram might be corrupted. |
| 699 return NULL; | 700 return NULL; |
| 700 } | 701 } |
| 701 return histogram; | 702 return histogram; |
| 702 } | 703 } |
| 703 | 704 |
| 704 //------------------------------------------------------------------------------ | 705 //------------------------------------------------------------------------------ |
| 705 // This section provides implementation for BooleanHistogram. | 706 // This section provides implementation for BooleanHistogram. |
| 706 //------------------------------------------------------------------------------ | 707 //------------------------------------------------------------------------------ |
| 707 | 708 |
| 708 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, | 709 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, |
| 709 int32 flags) { | 710 int32_t flags) { |
| 710 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 711 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| 711 if (!histogram) { | 712 if (!histogram) { |
| 712 // To avoid racy destruction at shutdown, the following will be leaked. | 713 // To avoid racy destruction at shutdown, the following will be leaked. |
| 713 BucketRanges* ranges = new BucketRanges(4); | 714 BucketRanges* ranges = new BucketRanges(4); |
| 714 LinearHistogram::InitializeBucketRanges(1, 2, ranges); | 715 LinearHistogram::InitializeBucketRanges(1, 2, ranges); |
| 715 const BucketRanges* registered_ranges = | 716 const BucketRanges* registered_ranges = |
| 716 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 717 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| 717 | 718 |
| 718 BooleanHistogram* tentative_histogram = | 719 BooleanHistogram* tentative_histogram = |
| 719 new BooleanHistogram(name, registered_ranges); | 720 new BooleanHistogram(name, registered_ranges); |
| 720 | 721 |
| 721 tentative_histogram->SetFlags(flags); | 722 tentative_histogram->SetFlags(flags); |
| 722 histogram = | 723 histogram = |
| 723 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 724 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| 724 } | 725 } |
| 725 | 726 |
| 726 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType()); | 727 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType()); |
| 727 return histogram; | 728 return histogram; |
| 728 } | 729 } |
| 729 | 730 |
| 730 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) { | 731 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32_t flags) { |
| 731 return FactoryGet(std::string(name), flags); | 732 return FactoryGet(std::string(name), flags); |
| 732 } | 733 } |
| 733 | 734 |
| 734 HistogramType BooleanHistogram::GetHistogramType() const { | 735 HistogramType BooleanHistogram::GetHistogramType() const { |
| 735 return BOOLEAN_HISTOGRAM; | 736 return BOOLEAN_HISTOGRAM; |
| 736 } | 737 } |
| 737 | 738 |
| 738 BooleanHistogram::BooleanHistogram(const std::string& name, | 739 BooleanHistogram::BooleanHistogram(const std::string& name, |
| 739 const BucketRanges* ranges) | 740 const BucketRanges* ranges) |
| 740 : LinearHistogram(name, 1, 2, ranges) {} | 741 : LinearHistogram(name, 1, 2, ranges) {} |
| 741 | 742 |
| 742 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { | 743 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { |
| 743 std::string histogram_name; | 744 std::string histogram_name; |
| 744 int flags; | 745 int flags; |
| 745 int declared_min; | 746 int declared_min; |
| 746 int declared_max; | 747 int declared_max; |
| 747 size_t bucket_count; | 748 size_t bucket_count; |
| 748 uint32 range_checksum; | 749 uint32_t range_checksum; |
| 749 | 750 |
| 750 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | 751 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
| 751 &declared_max, &bucket_count, &range_checksum)) { | 752 &declared_max, &bucket_count, &range_checksum)) { |
| 752 return NULL; | 753 return NULL; |
| 753 } | 754 } |
| 754 | 755 |
| 755 HistogramBase* histogram = BooleanHistogram::FactoryGet( | 756 HistogramBase* histogram = BooleanHistogram::FactoryGet( |
| 756 histogram_name, flags); | 757 histogram_name, flags); |
| 757 if (!ValidateRangeChecksum(*histogram, range_checksum)) { | 758 if (!ValidateRangeChecksum(*histogram, range_checksum)) { |
| 758 // The serialized histogram might be corrupted. | 759 // The serialized histogram might be corrupted. |
| 759 return NULL; | 760 return NULL; |
| 760 } | 761 } |
| 761 return histogram; | 762 return histogram; |
| 762 } | 763 } |
| 763 | 764 |
| 764 //------------------------------------------------------------------------------ | 765 //------------------------------------------------------------------------------ |
| 765 // CustomHistogram: | 766 // CustomHistogram: |
| 766 //------------------------------------------------------------------------------ | 767 //------------------------------------------------------------------------------ |
| 767 | 768 |
| 768 HistogramBase* CustomHistogram::FactoryGet( | 769 HistogramBase* CustomHistogram::FactoryGet( |
| 769 const std::string& name, | 770 const std::string& name, |
| 770 const std::vector<Sample>& custom_ranges, | 771 const std::vector<Sample>& custom_ranges, |
| 771 int32 flags) { | 772 int32_t flags) { |
| 772 CHECK(ValidateCustomRanges(custom_ranges)); | 773 CHECK(ValidateCustomRanges(custom_ranges)); |
| 773 | 774 |
| 774 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 775 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| 775 if (!histogram) { | 776 if (!histogram) { |
| 776 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges); | 777 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges); |
| 777 const BucketRanges* registered_ranges = | 778 const BucketRanges* registered_ranges = |
| 778 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 779 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| 779 | 780 |
| 780 // To avoid racy destruction at shutdown, the following will be leaked. | 781 // To avoid racy destruction at shutdown, the following will be leaked. |
| 781 CustomHistogram* tentative_histogram = | 782 CustomHistogram* tentative_histogram = |
| 782 new CustomHistogram(name, registered_ranges); | 783 new CustomHistogram(name, registered_ranges); |
| 783 | 784 |
| 784 tentative_histogram->SetFlags(flags); | 785 tentative_histogram->SetFlags(flags); |
| 785 | 786 |
| 786 histogram = | 787 histogram = |
| 787 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 788 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| 788 } | 789 } |
| 789 | 790 |
| 790 DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM); | 791 DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM); |
| 791 return histogram; | 792 return histogram; |
| 792 } | 793 } |
| 793 | 794 |
| 794 HistogramBase* CustomHistogram::FactoryGet( | 795 HistogramBase* CustomHistogram::FactoryGet( |
| 795 const char* name, | 796 const char* name, |
| 796 const std::vector<Sample>& custom_ranges, | 797 const std::vector<Sample>& custom_ranges, |
| 797 int32 flags) { | 798 int32_t flags) { |
| 798 return FactoryGet(std::string(name), custom_ranges, flags); | 799 return FactoryGet(std::string(name), custom_ranges, flags); |
| 799 } | 800 } |
| 800 | 801 |
| 801 HistogramType CustomHistogram::GetHistogramType() const { | 802 HistogramType CustomHistogram::GetHistogramType() const { |
| 802 return CUSTOM_HISTOGRAM; | 803 return CUSTOM_HISTOGRAM; |
| 803 } | 804 } |
| 804 | 805 |
| 805 // static | 806 // static |
| 806 std::vector<Sample> CustomHistogram::ArrayToCustomRanges( | 807 std::vector<Sample> CustomHistogram::ArrayToCustomRanges( |
| 807 const Sample* values, size_t num_values) { | 808 const Sample* values, size_t num_values) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 return 1; | 842 return 1; |
| 842 } | 843 } |
| 843 | 844 |
| 844 // static | 845 // static |
| 845 HistogramBase* CustomHistogram::DeserializeInfoImpl(PickleIterator* iter) { | 846 HistogramBase* CustomHistogram::DeserializeInfoImpl(PickleIterator* iter) { |
| 846 std::string histogram_name; | 847 std::string histogram_name; |
| 847 int flags; | 848 int flags; |
| 848 int declared_min; | 849 int declared_min; |
| 849 int declared_max; | 850 int declared_max; |
| 850 size_t bucket_count; | 851 size_t bucket_count; |
| 851 uint32 range_checksum; | 852 uint32_t range_checksum; |
| 852 | 853 |
| 853 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | 854 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
| 854 &declared_max, &bucket_count, &range_checksum)) { | 855 &declared_max, &bucket_count, &range_checksum)) { |
| 855 return NULL; | 856 return NULL; |
| 856 } | 857 } |
| 857 | 858 |
| 858 // First and last ranges are not serialized. | 859 // First and last ranges are not serialized. |
| 859 std::vector<Sample> sample_ranges(bucket_count - 1); | 860 std::vector<Sample> sample_ranges(bucket_count - 1); |
| 860 | 861 |
| 861 for (size_t i = 0; i < sample_ranges.size(); ++i) { | 862 for (size_t i = 0; i < sample_ranges.size(); ++i) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 | 899 |
| 899 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); | 900 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); |
| 900 for (size_t i = 0; i < ranges.size(); i++) { | 901 for (size_t i = 0; i < ranges.size(); i++) { |
| 901 bucket_ranges->set_range(i, ranges[i]); | 902 bucket_ranges->set_range(i, ranges[i]); |
| 902 } | 903 } |
| 903 bucket_ranges->ResetChecksum(); | 904 bucket_ranges->ResetChecksum(); |
| 904 return bucket_ranges; | 905 return bucket_ranges; |
| 905 } | 906 } |
| 906 | 907 |
| 907 } // namespace base | 908 } // namespace base |
| OLD | NEW |