diff options
Diffstat (limited to 'base/metrics/histogram.cc')
-rw-r--r-- | base/metrics/histogram.cc | 276 |
1 files changed, 1 insertions, 275 deletions
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc index 923ac9c..e176e8f 100644 --- a/base/metrics/histogram.cc +++ b/base/metrics/histogram.cc @@ -14,8 +14,8 @@ #include <algorithm> #include <string> -#include "base/debug/leak_annotations.h" #include "base/logging.h" +#include "base/metrics/statistics_recorder.h" #include "base/pickle.h" #include "base/stringprintf.h" #include "base/synchronization/lock.h" @@ -74,13 +74,6 @@ typedef Histogram::Count Count; // static const size_t Histogram::kBucketCount_MAX = 16384u; -// Collect the number of histograms created. -static uint32 number_of_histograms_ = 0; -// Collect the number of vectors saved because of caching ranges. -static uint32 number_of_vectors_saved_ = 0; -// Collect the number of ranges_ elements saved because of caching ranges. -static size_t saved_ranges_size_ = 0; - Histogram* Histogram::FactoryGet(const std::string& name, Sample minimum, Sample maximum, @@ -1037,265 +1030,6 @@ double CustomHistogram::GetBucketSize(Count current, size_t i) const { return 1; } -//------------------------------------------------------------------------------ -// The next section handles global (central) support for all histograms, as well -// as startup/teardown of this service. -//------------------------------------------------------------------------------ - -// This singleton instance should be started during the single threaded portion -// of main(), and hence it is not thread safe. It initializes globals to -// provide support for all future calls. -StatisticsRecorder::StatisticsRecorder() { - DCHECK(!histograms_); - if (lock_ == NULL) { - // This will leak on purpose. It's the only way to make sure we won't race - // against the static uninitialization of the module while one of our - // static methods relying on the lock get called at an inappropriate time - // during the termination phase. Since it's a static data member, we will - // leak one per process, which would be similar to the instance allocated - // during static initialization and released only on process termination. - lock_ = new base::Lock; - } - base::AutoLock auto_lock(*lock_); - histograms_ = new HistogramMap; - ranges_ = new RangesMap; -} - -StatisticsRecorder::~StatisticsRecorder() { - DCHECK(histograms_ && lock_); - - if (dump_on_exit_) { - std::string output; - WriteGraph("", &output); - DLOG(INFO) << output; - } - // Clean up. - HistogramMap* histograms = NULL; - { - base::AutoLock auto_lock(*lock_); - histograms = histograms_; - histograms_ = NULL; - } - RangesMap* ranges = NULL; - { - base::AutoLock auto_lock(*lock_); - ranges = ranges_; - ranges_ = NULL; - } - // We are going to leak the histograms and the ranges. - delete histograms; - delete ranges; - // We don't delete lock_ on purpose to avoid having to properly protect - // against it going away after we checked for NULL in the static methods. -} - -// static -bool StatisticsRecorder::IsActive() { - if (lock_ == NULL) - return false; - base::AutoLock auto_lock(*lock_); - return NULL != histograms_; -} - -Histogram* StatisticsRecorder::RegisterOrDeleteDuplicate(Histogram* histogram) { - // As per crbug.com/79322 the histograms are intentionally leaked, so we need - // to annotate them. Because ANNOTATE_LEAKING_OBJECT_PTR may be used only once - // for an object, the duplicates should not be annotated. - // Callers are responsible for not calling RegisterOrDeleteDuplicate(ptr) - // twice if (lock_ == NULL) || (!histograms_). - DCHECK(histogram->HasValidRangeChecksum()); - if (lock_ == NULL) { - ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 - return histogram; - } - base::AutoLock auto_lock(*lock_); - if (!histograms_) { - ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 - return histogram; - } - const std::string name = histogram->histogram_name(); - HistogramMap::iterator it = histograms_->find(name); - // Avoid overwriting a previous registration. - if (histograms_->end() == it) { - (*histograms_)[name] = histogram; - ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 - RegisterOrDeleteDuplicateRanges(histogram); - ++number_of_histograms_; - } else { - delete histogram; // We already have one by this name. - histogram = it->second; - } - return histogram; -} - -// static -void StatisticsRecorder::RegisterOrDeleteDuplicateRanges(Histogram* histogram) { - DCHECK(histogram); - CachedRanges* histogram_ranges = histogram->cached_ranges(); - DCHECK(histogram_ranges); - uint32 checksum = histogram->range_checksum(); - histogram_ranges->SetRangeChecksum(checksum); - - RangesMap::iterator ranges_it = ranges_->find(checksum); - if (ranges_->end() == ranges_it) { - // Register the new CachedRanges. - std::list<CachedRanges*>* checksum_matching_list( - new std::list<CachedRanges*>()); - checksum_matching_list->push_front(histogram_ranges); - (*ranges_)[checksum] = checksum_matching_list; - return; - } - - // Use the registered CachedRanges if the registered CachedRanges has same - // ranges_ as |histogram|'s CachedRanges. - std::list<CachedRanges*>* checksum_matching_list = ranges_it->second; - std::list<CachedRanges*>::iterator checksum_matching_list_it; - for (checksum_matching_list_it = checksum_matching_list->begin(); - checksum_matching_list_it != checksum_matching_list->end(); - ++checksum_matching_list_it) { - CachedRanges* existing_histogram_ranges = *checksum_matching_list_it; - DCHECK(existing_histogram_ranges); - if (existing_histogram_ranges->Equals(histogram_ranges)) { - histogram->set_cached_ranges(existing_histogram_ranges); - ++number_of_vectors_saved_; - saved_ranges_size_ += histogram_ranges->size(); - delete histogram_ranges; - return; - } - } - - // We haven't found a CachedRanges which has the same ranges. Register the - // new CachedRanges. - DCHECK(checksum_matching_list_it == checksum_matching_list->end()); - checksum_matching_list->push_front(histogram_ranges); -} - -// static -void StatisticsRecorder::CollectHistogramStats(const std::string& suffix) { - static int uma_upload_attempt = 0; - ++uma_upload_attempt; - if (uma_upload_attempt == 1) { - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.Count.FirstUpload." + suffix, - number_of_histograms_); - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.RangesSaved.FirstUpload." + suffix, - number_of_vectors_saved_); - UMA_HISTOGRAM_COUNTS( - "Histogram.SharedRange.ElementsSaved.FirstUpload." + suffix, - static_cast<int>(saved_ranges_size_)); - number_of_histograms_ = 0; - number_of_vectors_saved_ = 0; - saved_ranges_size_ = 0; - return; - } - if (uma_upload_attempt == 2) { - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.Count.SecondUpload." + suffix, - number_of_histograms_); - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.RangesSaved.SecondUpload." + suffix, - number_of_vectors_saved_); - UMA_HISTOGRAM_COUNTS( - "Histogram.SharedRange.ElementsSaved.SecondUpload." + suffix, - static_cast<int>(saved_ranges_size_)); - number_of_histograms_ = 0; - number_of_vectors_saved_ = 0; - saved_ranges_size_ = 0; - return; - } - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.Count.RestOfUploads." + suffix, - number_of_histograms_); - UMA_HISTOGRAM_COUNTS_10000( - "Histogram.SharedRange.RangesSaved.RestOfUploads." + suffix, - number_of_vectors_saved_); - UMA_HISTOGRAM_COUNTS( - "Histogram.SharedRange.ElementsSaved.RestOfUploads." + suffix, - static_cast<int>(saved_ranges_size_)); -} - -// static -void StatisticsRecorder::WriteHTMLGraph(const std::string& query, - std::string* output) { - if (!IsActive()) - return; - - Histograms snapshot; - GetSnapshot(query, &snapshot); - for (Histograms::iterator it = snapshot.begin(); - it != snapshot.end(); - ++it) { - (*it)->WriteHTMLGraph(output); - output->append("<br><hr><br>"); - } -} - -// static -void StatisticsRecorder::WriteGraph(const std::string& query, - std::string* output) { - if (!IsActive()) - return; - if (query.length()) - StringAppendF(output, "Collections of histograms for %s\n", query.c_str()); - else - output->append("Collections of all histograms\n"); - - Histograms snapshot; - GetSnapshot(query, &snapshot); - for (Histograms::iterator it = snapshot.begin(); - it != snapshot.end(); - ++it) { - (*it)->WriteAscii(true, "\n", output); - output->append("\n"); - } -} - -// static -void StatisticsRecorder::GetHistograms(Histograms* output) { - if (lock_ == NULL) - return; - base::AutoLock auto_lock(*lock_); - if (!histograms_) - return; - for (HistogramMap::iterator it = histograms_->begin(); - histograms_->end() != it; - ++it) { - DCHECK_EQ(it->first, it->second->histogram_name()); - output->push_back(it->second); - } -} - -bool StatisticsRecorder::FindHistogram(const std::string& name, - Histogram** histogram) { - if (lock_ == NULL) - return false; - base::AutoLock auto_lock(*lock_); - if (!histograms_) - return false; - HistogramMap::iterator it = histograms_->find(name); - if (histograms_->end() == it) - return false; - *histogram = it->second; - return true; -} - -// private static -void StatisticsRecorder::GetSnapshot(const std::string& query, - Histograms* snapshot) { - if (lock_ == NULL) - return; - base::AutoLock auto_lock(*lock_); - if (!histograms_) - return; - for (HistogramMap::iterator it = histograms_->begin(); - histograms_->end() != it; - ++it) { - if (it->first.find(query) != std::string::npos) - snapshot->push_back(it->second); - } -} - CachedRanges::CachedRanges(size_t bucket_count, int initial_value) : ranges_(bucket_count, initial_value), range_checksum_(0) { @@ -1322,12 +1056,4 @@ bool CachedRanges::Equals(CachedRanges* other) const { return true; } -// static -StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; -// static -StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; -// static -base::Lock* StatisticsRecorder::lock_ = NULL; -// static -bool StatisticsRecorder::dump_on_exit_ = false; } // namespace base |