| Index: base/histogram.cc
|
| ===================================================================
|
| --- base/histogram.cc (revision 33932)
|
| +++ base/histogram.cc (working copy)
|
| @@ -23,7 +23,42 @@
|
| // static
|
| const int Histogram::kHexRangePrintingFlag = 0x8000;
|
|
|
| -Histogram::Histogram(const char* name, Sample minimum,
|
| +scoped_refptr<Histogram> Histogram::HistogramFactoryGet(
|
| + const std::string& name, Sample minimum, Sample maximum,
|
| + size_t bucket_count) {
|
| + scoped_refptr<Histogram> histogram(NULL);
|
| +
|
| + // Defensive code.
|
| + if (minimum <= 0)
|
| + minimum = 1;
|
| + if (maximum >= kSampleType_MAX)
|
| + maximum = kSampleType_MAX - 1;
|
| +
|
| + if (StatisticsRecorder::FindHistogram(name, &histogram)) {
|
| + DCHECK(histogram.get() != NULL);
|
| + } else {
|
| + histogram = new Histogram(name, minimum, maximum, bucket_count);
|
| + scoped_refptr<Histogram> registered_histogram(NULL);
|
| + StatisticsRecorder::FindHistogram(name, ®istered_histogram);
|
| + // Allow a NULL return to mean that the StatisticsRecorder was not started.
|
| + if (registered_histogram.get() != NULL &&
|
| + registered_histogram.get() != histogram.get())
|
| + histogram = registered_histogram;
|
| + }
|
| +
|
| + DCHECK(HISTOGRAM == histogram->histogram_type());
|
| + DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count));
|
| + return histogram;
|
| +}
|
| +
|
| +scoped_refptr<Histogram> Histogram::HistogramFactoryGet(
|
| + const std::string& name, base::TimeDelta minimum, base::TimeDelta maximum,
|
| + size_t bucket_count) {
|
| + return HistogramFactoryGet(name,
|
| + minimum.InMilliseconds(), maximum.InMilliseconds(), bucket_count);
|
| +}
|
| +
|
| +Histogram::Histogram(const std::string& name, Sample minimum,
|
| Sample maximum, size_t bucket_count)
|
| : histogram_name_(name),
|
| declared_min_(minimum),
|
| @@ -31,12 +66,11 @@
|
| bucket_count_(bucket_count),
|
| flags_(0),
|
| ranges_(bucket_count + 1, 0),
|
| - sample_(),
|
| - registered_(false) {
|
| + sample_() {
|
| Initialize();
|
| }
|
|
|
| -Histogram::Histogram(const char* name, TimeDelta minimum,
|
| +Histogram::Histogram(const std::string& name, TimeDelta minimum,
|
| TimeDelta maximum, size_t bucket_count)
|
| : histogram_name_(name),
|
| declared_min_(static_cast<int> (minimum.InMilliseconds())),
|
| @@ -44,21 +78,23 @@
|
| bucket_count_(bucket_count),
|
| flags_(0),
|
| ranges_(bucket_count + 1, 0),
|
| - sample_(),
|
| - registered_(false) {
|
| + sample_() {
|
| Initialize();
|
| }
|
|
|
| Histogram::~Histogram() {
|
| - if (registered_)
|
| - StatisticsRecorder::UnRegister(this);
|
| + DCHECK(!(kPlannedLeakFlag & flags_));
|
| + if (StatisticsRecorder::dump_on_exit()) {
|
| + std::string output;
|
| + WriteAscii(true, "\n", &output);
|
| + LOG(INFO) << output;
|
| + }
|
| +
|
| // Just to make sure most derived class did this properly...
|
| DCHECK(ValidateBucketRanges());
|
| }
|
|
|
| void Histogram::Add(int value) {
|
| - if (!registered_)
|
| - registered_ = StatisticsRecorder::Register(this);
|
| if (value >= kSampleType_MAX)
|
| value = kSampleType_MAX - 1;
|
| if (value < 0)
|
| @@ -170,7 +206,7 @@
|
| ranges_[bucket_count_] = kSampleType_MAX;
|
| InitializeBucketRange();
|
| DCHECK(ValidateBucketRanges());
|
| - registered_ = StatisticsRecorder::Register(this);
|
| + StatisticsRecorder::Register(this);
|
| }
|
|
|
| // Calculate what range of values are held in each bucket.
|
| @@ -353,14 +389,15 @@
|
| // static
|
| std::string Histogram::SerializeHistogramInfo(const Histogram& histogram,
|
| const SampleSet& snapshot) {
|
| + DCHECK(histogram.histogram_type() != NOT_VALID_IN_RENDERER);
|
| +
|
| Pickle pickle;
|
| -
|
| pickle.WriteString(histogram.histogram_name());
|
| pickle.WriteInt(histogram.declared_min());
|
| pickle.WriteInt(histogram.declared_max());
|
| pickle.WriteSize(histogram.bucket_count());
|
| pickle.WriteInt(histogram.histogram_type());
|
| - pickle.WriteInt(histogram.flags());
|
| + pickle.WriteInt(histogram.flags() & ~kIPCSerializationSourceFlag);
|
|
|
| snapshot.Serialize(&pickle);
|
| return std::string(static_cast<const char*>(pickle.data()), pickle.size());
|
| @@ -394,27 +431,27 @@
|
| return false;
|
| }
|
|
|
| - Histogram* render_histogram =
|
| - StatisticsRecorder::GetHistogram(histogram_name);
|
| + DCHECK(histogram_type != NOT_VALID_IN_RENDERER);
|
|
|
| - if (render_histogram == NULL) {
|
| - if (histogram_type == EXPONENTIAL) {
|
| - render_histogram = new Histogram(histogram_name.c_str(),
|
| - declared_min,
|
| - declared_max,
|
| - bucket_count);
|
| - } else if (histogram_type == LINEAR) {
|
| - render_histogram = new LinearHistogram(histogram_name.c_str(),
|
| - declared_min,
|
| - declared_max,
|
| - bucket_count);
|
| - } else {
|
| - LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " <<
|
| - histogram_type;
|
| - return false;
|
| - }
|
| - DCHECK(!(flags & kRendererHistogramFlag));
|
| - render_histogram->SetFlags(flags | kRendererHistogramFlag);
|
| + scoped_refptr<Histogram> render_histogram(NULL);
|
| +
|
| + if (histogram_type == HISTOGRAM) {
|
| + render_histogram = Histogram::HistogramFactoryGet(
|
| + histogram_name, declared_min, declared_max, bucket_count);
|
| + } else if (histogram_type == LINEAR_HISTOGRAM) {
|
| + render_histogram = LinearHistogram::LinearHistogramFactoryGet(
|
| + histogram_name, declared_min, declared_max, bucket_count);
|
| + } else if (histogram_type == BOOLEAN_HISTOGRAM) {
|
| + render_histogram = BooleanHistogram::BooleanHistogramFactoryGet(
|
| + histogram_name);
|
| + } else if (histogram_type == THREAD_SAFE_HISTOGRAM) {
|
| + render_histogram =
|
| + ThreadSafeHistogram::ThreadSafeHistogramFactoryGet(
|
| + histogram_name, declared_min, declared_max, bucket_count);
|
| + } else {
|
| + LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " <<
|
| + histogram_type;
|
| + return false;
|
| }
|
|
|
| DCHECK(declared_min == render_histogram->declared_min());
|
| @@ -422,17 +459,16 @@
|
| DCHECK(bucket_count == render_histogram->bucket_count());
|
| DCHECK(histogram_type == render_histogram->histogram_type());
|
|
|
| - if (render_histogram->flags() & kRendererHistogramFlag) {
|
| + if (render_histogram->flags() & kIPCSerializationSourceFlag) {
|
| + DLOG(INFO) << "Single process mode, histogram observed and not copied: " <<
|
| + histogram_name;
|
| + } else {
|
| render_histogram->AddSampleSet(sample);
|
| - } else {
|
| - DLOG(INFO) << "Single thread mode, histogram observed and not copied: " <<
|
| - histogram_name;
|
| }
|
|
|
| return true;
|
| }
|
|
|
| -
|
| //------------------------------------------------------------------------------
|
| // Methods for the Histogram::SampleSet class
|
| //------------------------------------------------------------------------------
|
| @@ -537,14 +573,48 @@
|
| // buckets.
|
| //------------------------------------------------------------------------------
|
|
|
| -LinearHistogram::LinearHistogram(const char* name, Sample minimum,
|
| +scoped_refptr<Histogram> LinearHistogram::LinearHistogramFactoryGet(
|
| + const std::string& name, Sample minimum, Sample maximum,
|
| + size_t bucket_count) {
|
| + scoped_refptr<Histogram> histogram(NULL);
|
| +
|
| + if (minimum <= 0)
|
| + minimum = 1;
|
| + if (maximum >= kSampleType_MAX)
|
| + maximum = kSampleType_MAX - 1;
|
| +
|
| + if (StatisticsRecorder::FindHistogram(name, &histogram)) {
|
| + DCHECK(histogram.get() != NULL);
|
| + } else {
|
| + histogram = new LinearHistogram(name, minimum, maximum, bucket_count);
|
| + scoped_refptr<Histogram> registered_histogram(NULL);
|
| + StatisticsRecorder::FindHistogram(name, ®istered_histogram);
|
| + if (registered_histogram.get() != NULL &&
|
| + registered_histogram.get() != histogram.get())
|
| + histogram = registered_histogram;
|
| + }
|
| +
|
| + DCHECK(LINEAR_HISTOGRAM == histogram->histogram_type());
|
| + DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count));
|
| +
|
| + return histogram;
|
| +}
|
| +
|
| +scoped_refptr<Histogram> LinearHistogram::LinearHistogramFactoryGet(
|
| + const std::string& name, base::TimeDelta minimum, base::TimeDelta maximum,
|
| + size_t bucket_count) {
|
| + return LinearHistogramFactoryGet(name, minimum.InMilliseconds(),
|
| + maximum.InMilliseconds(), bucket_count);
|
| +}
|
| +
|
| +LinearHistogram::LinearHistogram(const std::string& name, Sample minimum,
|
| Sample maximum, size_t bucket_count)
|
| : Histogram(name, minimum >= 1 ? minimum : 1, maximum, bucket_count) {
|
| InitializeBucketRange();
|
| DCHECK(ValidateBucketRanges());
|
| }
|
|
|
| -LinearHistogram::LinearHistogram(const char* name,
|
| +LinearHistogram::LinearHistogram(const std::string& name,
|
| TimeDelta minimum, TimeDelta maximum, size_t bucket_count)
|
| : Histogram(name, minimum >= TimeDelta::FromMilliseconds(1) ?
|
| minimum : TimeDelta::FromMilliseconds(1),
|
| @@ -595,11 +665,61 @@
|
| }
|
|
|
| //------------------------------------------------------------------------------
|
| +// This section provides implementation for BooleanHistogram.
|
| +//------------------------------------------------------------------------------
|
| +
|
| +scoped_refptr<Histogram> BooleanHistogram::BooleanHistogramFactoryGet(
|
| + const std::string& name) {
|
| + scoped_refptr<Histogram> histogram(NULL);
|
| +
|
| + if (StatisticsRecorder::FindHistogram(name, &histogram)) {
|
| + DCHECK(histogram.get() != NULL);
|
| + } else {
|
| + histogram = new BooleanHistogram(name);
|
| + scoped_refptr<Histogram> registered_histogram(NULL);
|
| + StatisticsRecorder::FindHistogram(name, ®istered_histogram);
|
| + if (registered_histogram.get() != NULL &&
|
| + registered_histogram.get() != histogram.get())
|
| + histogram = registered_histogram;
|
| + }
|
| +
|
| + DCHECK(BOOLEAN_HISTOGRAM == histogram->histogram_type());
|
| +
|
| + return histogram;
|
| +}
|
| +
|
| +//------------------------------------------------------------------------------
|
| // This section provides implementation for ThreadSafeHistogram.
|
| //------------------------------------------------------------------------------
|
|
|
| -ThreadSafeHistogram::ThreadSafeHistogram(const char* name, Sample minimum,
|
| - Sample maximum, size_t bucket_count)
|
| +scoped_refptr<Histogram> ThreadSafeHistogram::ThreadSafeHistogramFactoryGet(
|
| + const std::string& name, Sample minimum, Sample maximum,
|
| + size_t bucket_count) {
|
| + scoped_refptr<Histogram> histogram(NULL);
|
| +
|
| + if (minimum <= 0)
|
| + minimum = 1;
|
| + if (maximum >= kSampleType_MAX)
|
| + maximum = kSampleType_MAX - 1;
|
| +
|
| + if (StatisticsRecorder::FindHistogram(name, &histogram)) {
|
| + DCHECK(histogram.get() != NULL);
|
| + } else {
|
| + histogram = new ThreadSafeHistogram(name, minimum, maximum, bucket_count);
|
| + scoped_refptr<Histogram> registered_histogram(NULL);
|
| + StatisticsRecorder::FindHistogram(name, ®istered_histogram);
|
| + if (registered_histogram.get() != NULL &&
|
| + registered_histogram.get() != histogram.get())
|
| + histogram = registered_histogram;
|
| + }
|
| +
|
| + DCHECK(THREAD_SAFE_HISTOGRAM == histogram->histogram_type());
|
| + DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count));
|
| + return histogram;
|
| +}
|
| +
|
| +ThreadSafeHistogram::ThreadSafeHistogram(const std::string& name,
|
| + Sample minimum, Sample maximum, size_t bucket_count)
|
| : Histogram(name, minimum, maximum, bucket_count),
|
| lock_() {
|
| }
|
| @@ -657,37 +777,25 @@
|
| return NULL != histograms_;
|
| }
|
|
|
| +// Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a
|
| +// reference, and we are called while in the Histogram constructor. In that
|
| +// scenario, a ref_ptr would have incremented the ref count when the histogram
|
| +// was passed to us, decremented it when we returned, and the instance would be
|
| +// destroyed before assignment (when value was returned by new).
|
| // static
|
| -bool StatisticsRecorder::Register(Histogram* histogram) {
|
| +void StatisticsRecorder::Register(Histogram* histogram) {
|
| if (!histograms_)
|
| - return false;
|
| + return;
|
| const std::string name = histogram->histogram_name();
|
| AutoLock auto_lock(*lock_);
|
|
|
| - if (histograms_->end() != histograms_->find(name)) {
|
| - // Check to be sure it is compatible.... and if not, then do a CHECK()
|
| - return false; // This name is already registered.
|
| - }
|
| + DCHECK(histograms_->end() == histograms_->find(name));
|
| +
|
| (*histograms_)[name] = histogram;
|
| - return true;
|
| + return;
|
| }
|
|
|
| // static
|
| -void StatisticsRecorder::UnRegister(Histogram* histogram) {
|
| - if (!histograms_)
|
| - return;
|
| - const std::string name = histogram->histogram_name();
|
| - AutoLock auto_lock(*lock_);
|
| - DCHECK(histograms_->end() != histograms_->find(name));
|
| - histograms_->erase(name);
|
| - if (dump_on_exit_) {
|
| - std::string output;
|
| - histogram->WriteAscii(true, "\n", &output);
|
| - LOG(INFO) << output;
|
| - }
|
| -}
|
| -
|
| -// static
|
| void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
|
| std::string* output) {
|
| if (!histograms_)
|
| @@ -743,19 +851,33 @@
|
| }
|
| }
|
|
|
| -Histogram* StatisticsRecorder::GetHistogram(const std::string& query) {
|
| +// static
|
| +void StatisticsRecorder::GetHistogramsForRenderer(Histograms* output) {
|
| if (!histograms_)
|
| - return NULL;
|
| + return;
|
| AutoLock auto_lock(*lock_);
|
| for (HistogramMap::iterator it = histograms_->begin();
|
| histograms_->end() != it;
|
| ++it) {
|
| - if (it->first.find(query) != std::string::npos)
|
| - return it->second;
|
| + scoped_refptr<Histogram> histogram = it->second;
|
| + if (!(histogram->flags() & kIPCSerializationSourceFlag))
|
| + histogram->SetFlags(kIPCSerializationSourceFlag);
|
| + output->push_back(histogram);
|
| }
|
| - return NULL;
|
| }
|
|
|
| +bool StatisticsRecorder::FindHistogram(const std::string& name,
|
| + scoped_refptr<Histogram>* histogram) {
|
| + if (!histograms_)
|
| + return false;
|
| + AutoLock auto_lock(*lock_);
|
| + 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) {
|
|
|