Chromium Code Reviews| 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 <math.h> | 12 #include <math.h> |
| 13 | 13 |
| 14 #include <algorithm> | 14 #include <algorithm> |
| 15 #include <string> | 15 #include <string> |
| 16 | 16 |
| 17 #include "base/compiler_specific.h" | 17 #include "base/compiler_specific.h" |
| 18 #include "base/debug/alias.h" | 18 #include "base/debug/alias.h" |
| 19 #include "base/logging.h" | 19 #include "base/logging.h" |
| 20 #include "base/memory/persistent_memory_allocator.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 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 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); |
| 95 ImportPersistentHistograms(); | |
| 94 | 96 |
| 95 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 97 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| 96 if (!histogram) { | 98 if (!histogram) { |
| 97 // To avoid racy destruction at shutdown, the following will be leaked. | 99 // To avoid racy destruction at shutdown, the following will be leaked. |
| 98 BucketRanges* ranges = new BucketRanges(bucket_count + 1); | 100 BucketRanges* ranges = new BucketRanges(bucket_count + 1); |
| 99 InitializeBucketRanges(minimum, maximum, ranges); | 101 InitializeBucketRanges(minimum, maximum, ranges); |
| 100 const BucketRanges* registered_ranges = | 102 const BucketRanges* registered_ranges = |
| 101 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 103 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| 102 | 104 |
| 103 Histogram* tentative_histogram = | 105 PersistentMemoryAllocator::Reference histogram_ref = 0; |
| 104 new Histogram(name, minimum, maximum, registered_ranges); | 106 HistogramBase* tentative_histogram = nullptr; |
| 107 if (allocator_) { | |
| 108 flags |= kIsPersistent; | |
| 109 tentative_histogram = AllocatePersistentHistogram( | |
| 110 GetDefaultPersistentMemoryAllocator(), | |
| 111 HISTOGRAM, | |
| 112 name, | |
| 113 minimum, | |
| 114 maximum, | |
| 115 registered_ranges, | |
| 116 flags, | |
| 117 &histogram_ref); | |
| 118 } | |
| 119 if (!tentative_histogram) { | |
| 120 flags &= ~kIsPersistent; | |
| 121 tentative_histogram = new Histogram( | |
| 122 name, minimum, maximum, registered_ranges); | |
| 123 } | |
| 105 | 124 |
| 106 tentative_histogram->SetFlags(flags); | 125 tentative_histogram->SetFlags(flags); |
| 107 histogram = | 126 histogram = |
| 108 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 127 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| 128 | |
| 129 // Persistent histograms need some follow-up processing. | |
| 130 if (histogram_ref) { | |
| 131 // If the created persistent histogram is canonical then it needs to be | |
| 132 // marked as "iterable" in order to be found by other processes. | |
| 133 if (histogram == tentative_histogram) | |
| 134 GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref); | |
| 135 // If it's not the canonical one then a race condition must have caused | |
| 136 // two to be created. The allocator does not support releasing the | |
| 137 // acquired memory so just change the type to be empty. | |
| 138 else | |
| 139 GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0); | |
| 140 } | |
| 109 } | 141 } |
| 110 | 142 |
| 111 DCHECK_EQ(HISTOGRAM, histogram->GetHistogramType()); | 143 DCHECK_EQ(HISTOGRAM, histogram->GetHistogramType()); |
| 112 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) { | 144 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) { |
| 113 // The construction arguments do not match the existing histogram. This can | 145 // The construction arguments do not match the existing histogram. This can |
| 114 // come about if an extension updates in the middle of a chrome run and has | 146 // come about if an extension updates in the middle of a chrome run and has |
| 115 // changed one of them, or simply by bad code within Chrome itself. We | 147 // changed one of them, or simply by bad code within Chrome itself. We |
| 116 // return NULL here with the expectation that bad code in Chrome will crash | 148 // return NULL here with the expectation that bad code in Chrome will crash |
| 117 // on dereference, but extension/Pepper APIs will guard against NULL and not | 149 // on dereference, but extension/Pepper APIs will guard against NULL and not |
| 118 // crash. | 150 // crash. |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 Sample maximum, | 369 Sample maximum, |
| 338 const BucketRanges* ranges) | 370 const BucketRanges* ranges) |
| 339 : HistogramBase(name), | 371 : HistogramBase(name), |
| 340 bucket_ranges_(ranges), | 372 bucket_ranges_(ranges), |
| 341 declared_min_(minimum), | 373 declared_min_(minimum), |
| 342 declared_max_(maximum) { | 374 declared_max_(maximum) { |
| 343 if (ranges) | 375 if (ranges) |
| 344 samples_.reset(new SampleVector(HashMetricName(name), ranges)); | 376 samples_.reset(new SampleVector(HashMetricName(name), ranges)); |
| 345 } | 377 } |
| 346 | 378 |
| 379 Histogram::Histogram(const std::string& name, | |
| 380 Sample minimum, | |
| 381 Sample maximum, | |
| 382 const BucketRanges* ranges, | |
| 383 HistogramBase::AtomicCount* counts, | |
| 384 size_t counts_size, | |
| 385 HistogramSamples::Metadata* meta) | |
| 386 : HistogramBase(name), | |
| 387 bucket_ranges_(ranges), | |
| 388 declared_min_(minimum), | |
| 389 declared_max_(maximum) { | |
| 390 if (ranges) | |
| 391 samples_.reset(new SampleVector(HashMetricName(name), | |
| 392 counts, counts_size, meta, ranges)); | |
| 393 } | |
| 394 | |
| 347 Histogram::~Histogram() { | 395 Histogram::~Histogram() { |
| 348 } | 396 } |
| 349 | 397 |
| 350 bool Histogram::PrintEmptyBucket(size_t index) const { | 398 bool Histogram::PrintEmptyBucket(size_t index) const { |
| 351 return true; | 399 return true; |
| 352 } | 400 } |
| 353 | 401 |
| 354 // Use the actual bucket widths (like a linear histogram) until the widths get | 402 // Use the actual bucket widths (like a linear histogram) until the widths get |
| 355 // over some transition value, and then use that transition width. Exponentials | 403 // over some transition value, and then use that transition width. Exponentials |
| 356 // get so big so fast (and we don't expect to see a lot of entries in the large | 404 // get so big so fast (and we don't expect to see a lot of entries in the large |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 | 440 |
| 393 if (!ValidateRangeChecksum(*histogram, range_checksum)) { | 441 if (!ValidateRangeChecksum(*histogram, range_checksum)) { |
| 394 // The serialized histogram might be corrupted. | 442 // The serialized histogram might be corrupted. |
| 395 return NULL; | 443 return NULL; |
| 396 } | 444 } |
| 397 return histogram; | 445 return histogram; |
| 398 } | 446 } |
| 399 | 447 |
| 400 scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { | 448 scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { |
| 401 scoped_ptr<SampleVector> samples( | 449 scoped_ptr<SampleVector> samples( |
| 402 new SampleVector(HashMetricName(histogram_name()), bucket_ranges())); | 450 new SampleVector(HashMetricName(histogram_name()), |
| 451 bucket_ranges())); | |
| 403 samples->Add(*samples_); | 452 samples->Add(*samples_); |
| 404 return samples; | 453 return samples; |
| 405 } | 454 } |
| 406 | 455 |
| 407 void Histogram::WriteAsciiImpl(bool graph_it, | 456 void Histogram::WriteAsciiImpl(bool graph_it, |
| 408 const std::string& newline, | 457 const std::string& newline, |
| 409 std::string* output) const { | 458 std::string* output) const { |
| 410 // Get local (stack) copies of all effectively volatile class data so that we | 459 // Get local (stack) copies of all effectively volatile class data so that we |
| 411 // are consistent across our output activities. | 460 // are consistent across our output activities. |
| 412 scoped_ptr<SampleVector> snapshot = SnapshotSampleVector(); | 461 scoped_ptr<SampleVector> snapshot = SnapshotSampleVector(); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 586 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( | 635 HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( |
| 587 const std::string& name, | 636 const std::string& name, |
| 588 Sample minimum, | 637 Sample minimum, |
| 589 Sample maximum, | 638 Sample maximum, |
| 590 size_t bucket_count, | 639 size_t bucket_count, |
| 591 int32 flags, | 640 int32 flags, |
| 592 const DescriptionPair descriptions[]) { | 641 const DescriptionPair descriptions[]) { |
| 593 bool valid_arguments = Histogram::InspectConstructionArguments( | 642 bool valid_arguments = Histogram::InspectConstructionArguments( |
| 594 name, &minimum, &maximum, &bucket_count); | 643 name, &minimum, &maximum, &bucket_count); |
| 595 DCHECK(valid_arguments); | 644 DCHECK(valid_arguments); |
| 645 ImportPersistentHistograms(); | |
| 596 | 646 |
| 597 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 647 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| 598 if (!histogram) { | 648 if (!histogram) { |
| 599 // To avoid racy destruction at shutdown, the following will be leaked. | 649 // To avoid racy destruction at shutdown, the following will be leaked. |
| 600 BucketRanges* ranges = new BucketRanges(bucket_count + 1); | 650 BucketRanges* ranges = new BucketRanges(bucket_count + 1); |
| 601 InitializeBucketRanges(minimum, maximum, ranges); | 651 InitializeBucketRanges(minimum, maximum, ranges); |
| 602 const BucketRanges* registered_ranges = | 652 const BucketRanges* registered_ranges = |
| 603 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 653 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| 604 | 654 |
| 605 LinearHistogram* tentative_histogram = | 655 PersistentMemoryAllocator::Reference histogram_ref = 0; |
| 606 new LinearHistogram(name, minimum, maximum, registered_ranges); | 656 LinearHistogram* tentative_histogram = nullptr; |
| 657 if (allocator_) { | |
| 658 flags |= kIsPersistent; | |
| 659 tentative_histogram = static_cast<LinearHistogram*>( | |
| 660 AllocatePersistentHistogram( | |
| 661 GetDefaultPersistentMemoryAllocator(), | |
| 662 LINEAR_HISTOGRAM, | |
| 663 name, | |
| 664 minimum, | |
| 665 maximum, | |
| 666 registered_ranges, | |
| 667 flags, | |
| 668 &histogram_ref)); | |
| 669 } | |
| 670 if (!tentative_histogram) { | |
| 671 flags &= ~kIsPersistent; | |
| 672 tentative_histogram = new LinearHistogram( | |
| 673 name, minimum, maximum, registered_ranges); | |
| 674 } | |
| 607 | 675 |
| 608 // Set range descriptions. | 676 // Set range descriptions. |
| 609 if (descriptions) { | 677 if (descriptions) { |
| 610 for (int i = 0; descriptions[i].description; ++i) { | 678 for (int i = 0; descriptions[i].description; ++i) { |
| 611 tentative_histogram->bucket_description_[descriptions[i].sample] = | 679 tentative_histogram->bucket_description_[descriptions[i].sample] = |
| 612 descriptions[i].description; | 680 descriptions[i].description; |
| 613 } | 681 } |
| 614 } | 682 } |
| 615 | 683 |
| 616 tentative_histogram->SetFlags(flags); | 684 tentative_histogram->SetFlags(flags); |
| 617 histogram = | 685 histogram = |
| 618 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 686 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| 687 | |
| 688 // Persistent histograms need some follow-up processing. | |
| 689 if (histogram_ref) { | |
| 690 // If the created persistent histogram is canonical then it needs to be | |
| 691 // marked as "iterable" in order to be found by other processes. | |
| 692 if (histogram == tentative_histogram) | |
| 693 GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref); | |
| 694 // If it's not the canonical one then a race condition must have caused | |
| 695 // two to be created. The allocator does not support releasing the | |
| 696 // acquired memory so just change the type to be empty. | |
| 697 else | |
| 698 GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0); | |
| 699 } | |
| 619 } | 700 } |
| 620 | 701 |
| 621 DCHECK_EQ(LINEAR_HISTOGRAM, histogram->GetHistogramType()); | 702 DCHECK_EQ(LINEAR_HISTOGRAM, histogram->GetHistogramType()); |
| 622 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) { | 703 if (!histogram->HasConstructionArguments(minimum, maximum, bucket_count)) { |
| 623 // The construction arguments do not match the existing histogram. This can | 704 // The construction arguments do not match the existing histogram. This can |
| 624 // come about if an extension updates in the middle of a chrome run and has | 705 // come about if an extension updates in the middle of a chrome run and has |
| 625 // changed one of them, or simply by bad code within Chrome itself. We | 706 // changed one of them, or simply by bad code within Chrome itself. We |
| 626 // return NULL here with the expectation that bad code in Chrome will crash | 707 // return NULL here with the expectation that bad code in Chrome will crash |
| 627 // on dereference, but extension/Pepper APIs will guard against NULL and not | 708 // on dereference, but extension/Pepper APIs will guard against NULL and not |
| 628 // crash. | 709 // crash. |
| 629 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments"; | 710 DLOG(ERROR) << "Histogram " << name << " has bad construction arguments"; |
| 630 return NULL; | 711 return NULL; |
| 631 } | 712 } |
| 632 return histogram; | 713 return histogram; |
| 633 } | 714 } |
| 634 | 715 |
| 635 HistogramType LinearHistogram::GetHistogramType() const { | 716 HistogramType LinearHistogram::GetHistogramType() const { |
| 636 return LINEAR_HISTOGRAM; | 717 return LINEAR_HISTOGRAM; |
| 637 } | 718 } |
| 638 | 719 |
| 639 LinearHistogram::LinearHistogram(const std::string& name, | 720 LinearHistogram::LinearHistogram(const std::string& name, |
| 640 Sample minimum, | 721 Sample minimum, |
| 641 Sample maximum, | 722 Sample maximum, |
| 642 const BucketRanges* ranges) | 723 const BucketRanges* ranges) |
| 643 : Histogram(name, minimum, maximum, ranges) { | 724 : Histogram(name, minimum, maximum, ranges) { |
| 644 } | 725 } |
| 645 | 726 |
| 727 LinearHistogram::LinearHistogram(const std::string& name, | |
| 728 Sample minimum, | |
| 729 Sample maximum, | |
| 730 const BucketRanges* ranges, | |
| 731 HistogramBase::AtomicCount* counts, | |
| 732 size_t counts_size, | |
| 733 HistogramSamples::Metadata* meta) | |
| 734 : Histogram(name, | |
| 735 minimum, | |
| 736 maximum, | |
| 737 ranges, | |
| 738 counts, | |
| 739 counts_size, | |
| 740 meta) {} | |
| 741 | |
| 646 double LinearHistogram::GetBucketSize(Count current, size_t i) const { | 742 double LinearHistogram::GetBucketSize(Count current, size_t i) const { |
| 647 DCHECK_GT(ranges(i + 1), ranges(i)); | 743 DCHECK_GT(ranges(i + 1), ranges(i)); |
| 648 // Adjacent buckets with different widths would have "surprisingly" many (few) | 744 // Adjacent buckets with different widths would have "surprisingly" many (few) |
| 649 // samples in a histogram if we didn't normalize this way. | 745 // samples in a histogram if we didn't normalize this way. |
| 650 double denominator = ranges(i + 1) - ranges(i); | 746 double denominator = ranges(i + 1) - ranges(i); |
| 651 return current/denominator; | 747 return current/denominator; |
| 652 } | 748 } |
| 653 | 749 |
| 654 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { | 750 const std::string LinearHistogram::GetAsciiBucketRange(size_t i) const { |
| 655 int range = ranges(i); | 751 int range = ranges(i); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 } | 797 } |
| 702 return histogram; | 798 return histogram; |
| 703 } | 799 } |
| 704 | 800 |
| 705 //------------------------------------------------------------------------------ | 801 //------------------------------------------------------------------------------ |
| 706 // This section provides implementation for BooleanHistogram. | 802 // This section provides implementation for BooleanHistogram. |
| 707 //------------------------------------------------------------------------------ | 803 //------------------------------------------------------------------------------ |
| 708 | 804 |
| 709 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, | 805 HistogramBase* BooleanHistogram::FactoryGet(const std::string& name, |
| 710 int32 flags) { | 806 int32 flags) { |
| 807 ImportPersistentHistograms(); | |
| 808 | |
| 711 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 809 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| 712 if (!histogram) { | 810 if (!histogram) { |
| 713 // To avoid racy destruction at shutdown, the following will be leaked. | 811 // To avoid racy destruction at shutdown, the following will be leaked. |
| 714 BucketRanges* ranges = new BucketRanges(4); | 812 BucketRanges* ranges = new BucketRanges(4); |
| 715 LinearHistogram::InitializeBucketRanges(1, 2, ranges); | 813 LinearHistogram::InitializeBucketRanges(1, 2, ranges); |
| 716 const BucketRanges* registered_ranges = | 814 const BucketRanges* registered_ranges = |
| 717 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 815 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| 718 | 816 |
| 719 BooleanHistogram* tentative_histogram = | 817 PersistentMemoryAllocator::Reference histogram_ref = 0; |
| 720 new BooleanHistogram(name, registered_ranges); | 818 HistogramBase* tentative_histogram = nullptr; |
| 819 if (allocator_) { | |
| 820 flags |= kIsPersistent; | |
| 821 tentative_histogram = AllocatePersistentHistogram( | |
| 822 GetDefaultPersistentMemoryAllocator(), | |
| 823 BOOLEAN_HISTOGRAM, | |
| 824 name, | |
| 825 1, 2, | |
| 826 registered_ranges, | |
| 827 flags, | |
| 828 &histogram_ref); | |
| 829 } | |
| 830 if (!tentative_histogram) { | |
| 831 flags &= ~kIsPersistent; | |
| 832 tentative_histogram = new BooleanHistogram(name, registered_ranges); | |
| 833 } | |
| 721 | 834 |
| 722 tentative_histogram->SetFlags(flags); | 835 tentative_histogram->SetFlags(flags); |
| 723 histogram = | 836 histogram = |
| 724 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 837 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| 838 | |
| 839 // Persistent histograms need some follow-up processing. | |
| 840 if (histogram_ref) { | |
| 841 // If the created persistent histogram is canonical then it needs to be | |
| 842 // marked as "iterable" in order to be found by other processes. | |
| 843 if (histogram == tentative_histogram) | |
| 844 GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref); | |
| 845 // If it's not the canonical one then a race condition must have caused | |
| 846 // two to be created. The allocator does not support releasing the | |
| 847 // acquired memory so just change the type to be empty. | |
| 848 else | |
| 849 GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0); | |
| 850 } | |
|
Alexei Svitkine (slow)
2015/12/04 18:27:36
The code from 817 to 850 is repeated in several pl
bcwhite
2015/12/07 23:27:19
Done.
| |
| 725 } | 851 } |
| 726 | 852 |
| 727 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType()); | 853 DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType()); |
| 728 return histogram; | 854 return histogram; |
| 729 } | 855 } |
| 730 | 856 |
| 731 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) { | 857 HistogramBase* BooleanHistogram::FactoryGet(const char* name, int32 flags) { |
| 732 return FactoryGet(std::string(name), flags); | 858 return FactoryGet(std::string(name), flags); |
| 733 } | 859 } |
| 734 | 860 |
| 735 HistogramType BooleanHistogram::GetHistogramType() const { | 861 HistogramType BooleanHistogram::GetHistogramType() const { |
| 736 return BOOLEAN_HISTOGRAM; | 862 return BOOLEAN_HISTOGRAM; |
| 737 } | 863 } |
| 738 | 864 |
| 739 BooleanHistogram::BooleanHistogram(const std::string& name, | 865 BooleanHistogram::BooleanHistogram(const std::string& name, |
| 740 const BucketRanges* ranges) | 866 const BucketRanges* ranges) |
| 741 : LinearHistogram(name, 1, 2, ranges) {} | 867 : LinearHistogram(name, 1, 2, ranges) {} |
| 742 | 868 |
| 869 BooleanHistogram::BooleanHistogram(const std::string& name, | |
| 870 const BucketRanges* ranges, | |
| 871 HistogramBase::AtomicCount* counts, | |
| 872 HistogramSamples::Metadata* meta) | |
| 873 : LinearHistogram(name, 1, 2, ranges, counts, 2, meta) {} | |
| 874 | |
| 743 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { | 875 HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { |
| 744 std::string histogram_name; | 876 std::string histogram_name; |
| 745 int flags; | 877 int flags; |
| 746 int declared_min; | 878 int declared_min; |
| 747 int declared_max; | 879 int declared_max; |
| 748 size_t bucket_count; | 880 size_t bucket_count; |
| 749 uint32 range_checksum; | 881 uint32 range_checksum; |
| 750 | 882 |
| 751 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | 883 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
| 752 &declared_max, &bucket_count, &range_checksum)) { | 884 &declared_max, &bucket_count, &range_checksum)) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 764 | 896 |
| 765 //------------------------------------------------------------------------------ | 897 //------------------------------------------------------------------------------ |
| 766 // CustomHistogram: | 898 // CustomHistogram: |
| 767 //------------------------------------------------------------------------------ | 899 //------------------------------------------------------------------------------ |
| 768 | 900 |
| 769 HistogramBase* CustomHistogram::FactoryGet( | 901 HistogramBase* CustomHistogram::FactoryGet( |
| 770 const std::string& name, | 902 const std::string& name, |
| 771 const std::vector<Sample>& custom_ranges, | 903 const std::vector<Sample>& custom_ranges, |
| 772 int32 flags) { | 904 int32 flags) { |
| 773 CHECK(ValidateCustomRanges(custom_ranges)); | 905 CHECK(ValidateCustomRanges(custom_ranges)); |
| 906 ImportPersistentHistograms(); | |
| 774 | 907 |
| 775 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); | 908 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); |
| 776 if (!histogram) { | 909 if (!histogram) { |
| 910 // To avoid racy destruction at shutdown, the following will be leaked. | |
| 777 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges); | 911 BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges); |
| 778 const BucketRanges* registered_ranges = | 912 const BucketRanges* registered_ranges = |
| 779 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); | 913 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); |
| 780 | 914 |
| 781 // To avoid racy destruction at shutdown, the following will be leaked. | 915 PersistentMemoryAllocator::Reference histogram_ref = 0; |
| 782 CustomHistogram* tentative_histogram = | 916 HistogramBase* tentative_histogram = nullptr; |
| 783 new CustomHistogram(name, registered_ranges); | 917 if (allocator_) { |
| 918 flags |= kIsPersistent; | |
| 919 tentative_histogram = AllocatePersistentHistogram( | |
| 920 GetDefaultPersistentMemoryAllocator(), | |
| 921 CUSTOM_HISTOGRAM, | |
| 922 name, | |
| 923 registered_ranges->range(1), | |
| 924 registered_ranges->range(registered_ranges->bucket_count() - 1), | |
| 925 registered_ranges, | |
| 926 flags, | |
| 927 &histogram_ref); | |
| 928 } | |
| 929 if (!tentative_histogram) { | |
| 930 flags &= ~kIsPersistent; | |
| 931 tentative_histogram = new CustomHistogram(name, registered_ranges); | |
| 932 } | |
| 784 | 933 |
| 785 tentative_histogram->SetFlags(flags); | 934 tentative_histogram->SetFlags(flags); |
| 786 | |
| 787 histogram = | 935 histogram = |
| 788 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 936 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| 937 | |
| 938 // Persistent histograms need some follow-up processing. | |
| 939 if (histogram_ref) { | |
| 940 // If the created persistent histogram is canonical then it needs to be | |
| 941 // marked as "iterable" in order to be found by other processes. | |
| 942 if (histogram == tentative_histogram) | |
| 943 GetDefaultPersistentMemoryAllocator()->MakeIterable(histogram_ref); | |
| 944 // If it's not the canonical one then a race condition must have caused | |
| 945 // two to be created. The allocator does not support releasing the | |
| 946 // acquired memory so just change the type to be empty. | |
| 947 else | |
| 948 GetDefaultPersistentMemoryAllocator()->SetType(histogram_ref, 0); | |
| 949 } | |
| 789 } | 950 } |
| 790 | 951 |
| 791 DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM); | 952 DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM); |
| 792 return histogram; | 953 return histogram; |
| 793 } | 954 } |
| 794 | 955 |
| 795 HistogramBase* CustomHistogram::FactoryGet( | 956 HistogramBase* CustomHistogram::FactoryGet( |
| 796 const char* name, | 957 const char* name, |
| 797 const std::vector<Sample>& custom_ranges, | 958 const std::vector<Sample>& custom_ranges, |
| 798 int32 flags) { | 959 int32 flags) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 818 return all_values; | 979 return all_values; |
| 819 } | 980 } |
| 820 | 981 |
| 821 CustomHistogram::CustomHistogram(const std::string& name, | 982 CustomHistogram::CustomHistogram(const std::string& name, |
| 822 const BucketRanges* ranges) | 983 const BucketRanges* ranges) |
| 823 : Histogram(name, | 984 : Histogram(name, |
| 824 ranges->range(1), | 985 ranges->range(1), |
| 825 ranges->range(ranges->bucket_count() - 1), | 986 ranges->range(ranges->bucket_count() - 1), |
| 826 ranges) {} | 987 ranges) {} |
| 827 | 988 |
| 989 CustomHistogram::CustomHistogram(const std::string& name, | |
| 990 const BucketRanges* ranges, | |
| 991 HistogramBase::AtomicCount* counts, | |
| 992 size_t counts_size, | |
| 993 HistogramSamples::Metadata* meta) | |
| 994 : Histogram(name, | |
| 995 ranges->range(1), | |
| 996 ranges->range(ranges->bucket_count() - 1), | |
| 997 ranges, | |
| 998 counts, | |
| 999 counts_size, | |
| 1000 meta) {} | |
| 1001 | |
| 828 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { | 1002 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { |
| 829 if (!Histogram::SerializeInfoImpl(pickle)) | 1003 if (!Histogram::SerializeInfoImpl(pickle)) |
| 830 return false; | 1004 return false; |
| 831 | 1005 |
| 832 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't | 1006 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't |
| 833 // write them. | 1007 // write them. |
| 834 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { | 1008 for (size_t i = 1; i < bucket_ranges()->bucket_count(); ++i) { |
| 835 if (!pickle->WriteInt(bucket_ranges()->range(i))) | 1009 if (!pickle->WriteInt(bucket_ranges()->range(i))) |
| 836 return false; | 1010 return false; |
| 837 } | 1011 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 899 | 1073 |
| 900 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); | 1074 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); |
| 901 for (size_t i = 0; i < ranges.size(); i++) { | 1075 for (size_t i = 0; i < ranges.size(); i++) { |
| 902 bucket_ranges->set_range(i, ranges[i]); | 1076 bucket_ranges->set_range(i, ranges[i]); |
| 903 } | 1077 } |
| 904 bucket_ranges->ResetChecksum(); | 1078 bucket_ranges->ResetChecksum(); |
| 905 return bucket_ranges; | 1079 return bucket_ranges; |
| 906 } | 1080 } |
| 907 | 1081 |
| 908 } // namespace base | 1082 } // namespace base |
| OLD | NEW |