summaryrefslogtreecommitdiffstats
path: root/base/histogram.cc
diff options
context:
space:
mode:
authorjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-25 06:10:17 +0000
committerjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-25 06:10:17 +0000
commit55e57d4d2326bd98d6e14c92ba055754ef77b0e6 (patch)
tree29f456dcb43fd5754104fe4e302df13532262c83 /base/histogram.cc
parentf78d965fa1ef193595740604508d7d94fde0ef84 (diff)
downloadchromium_src-55e57d4d2326bd98d6e14c92ba055754ef77b0e6.zip
chromium_src-55e57d4d2326bd98d6e14c92ba055754ef77b0e6.tar.gz
chromium_src-55e57d4d2326bd98d6e14c92ba055754ef77b0e6.tar.bz2
Initial support for Renderer Side Histograms
Patch contributed by Raman Tenneti see also patch number 21038 Review URL: http://codereview.chromium.org/27034 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10330 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/histogram.cc')
-rw-r--r--base/histogram.cc200
1 files changed, 174 insertions, 26 deletions
diff --git a/base/histogram.cc b/base/histogram.cc
index 79e9497..3234eb9 100644
--- a/base/histogram.cc
+++ b/base/histogram.cc
@@ -53,17 +53,16 @@ Histogram::Histogram(const char* name, TimeDelta minimum,
Histogram::~Histogram() {
if (registered_)
- StatisticsRecorder::UnRegister(*this);
+ StatisticsRecorder::UnRegister(this);
// Just to make sure most derived class did this properly...
DCHECK(ValidateBucketRanges());
}
-
// Hooks to override stats counter methods. This ensures that we gather all
// input the stats counter sees.
void Histogram::Add(int value) {
if (!registered_)
- registered_ = StatisticsRecorder::Register(*this);
+ registered_ = StatisticsRecorder::Register(this);
if (value >= kSampleType_MAX)
value = kSampleType_MAX - 1;
StatsRate::Add(value);
@@ -75,6 +74,10 @@ void Histogram::Add(int value) {
Accumulate(value, 1, index);
}
+void Histogram::AddSampleSet(const SampleSet& sample) {
+ sample_.Add(sample);
+}
+
// The following methods provide a graphical histogram display.
void Histogram::WriteHTMLGraph(std::string* output) const {
// TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc.
@@ -105,7 +108,7 @@ void Histogram::WriteAscii(bool graph_it, const std::string& newline,
while (0 == snapshot.counts(largest_non_empty_bucket)) {
if (0 == largest_non_empty_bucket)
break; // All buckets are empty.
- largest_non_empty_bucket--;
+ --largest_non_empty_bucket;
}
// Calculate largest print width needed for any of our bucket range displays.
@@ -121,7 +124,7 @@ void Histogram::WriteAscii(bool graph_it, const std::string& newline,
int64 remaining = sample_count;
int64 past = 0;
// Output the actual histogram graph.
- for (size_t i = 0; i < bucket_count(); i++) {
+ for (size_t i = 0; i < bucket_count(); ++i) {
Count current = snapshot.counts(i);
if (!current && !PrintEmptyBucket(i))
continue;
@@ -129,7 +132,7 @@ void Histogram::WriteAscii(bool graph_it, const std::string& newline,
StringAppendF(output, "%#*s ", print_width, GetAsciiBucketRange(i).c_str());
if (0 == current && i < bucket_count() - 1 && 0 == snapshot.counts(i + 1)) {
while (i < bucket_count() - 1 && 0 == snapshot.counts(i + 1))
- i++;
+ ++i;
output->append("... ");
output->append(newline);
continue; // No reason to plot emptiness.
@@ -169,7 +172,7 @@ void Histogram::Initialize() {
ranges_[bucket_count_] = kSampleType_MAX;
InitializeBucketRange();
DCHECK(ValidateBucketRanges());
- registered_ = StatisticsRecorder::Register(*this);
+ registered_ = StatisticsRecorder::Register(this);
}
// Calculate what range of values are held in each bucket.
@@ -199,7 +202,7 @@ void Histogram::InitializeBucketRange() {
if (next > current)
current = next;
else
- current++; // Just do a narrow bucket, and keep trying.
+ ++current; // Just do a narrow bucket, and keep trying.
SetBucketRange(bucket_index, current);
}
@@ -277,7 +280,7 @@ void Histogram::SetBucketRange(size_t i, Sample value) {
double Histogram::GetPeakBucketSize(const SampleSet& snapshot) const {
double max = 0;
- for (size_t i = 0; i < bucket_count() ; i++) {
+ for (size_t i = 0; i < bucket_count() ; ++i) {
double current_size = GetBucketSize(snapshot.counts(i), i);
if (current_size > max)
max = current_size;
@@ -349,6 +352,100 @@ void Histogram::WriteAsciiBucketGraph(double current_size, double max_size,
output->append(" ");
}
+// static
+std::string Histogram::SerializeHistogramInfo(const Histogram& histogram,
+ const SampleSet& snapshot) {
+ 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());
+
+ snapshot.Serialize(&pickle);
+ return std::string(static_cast<const char*>(pickle.data()), pickle.size());
+}
+
+// static
+void Histogram::DeserializeHistogramList(
+ const std::vector<std::string>& histograms) {
+ for (std::vector<std::string>::const_iterator it = histograms.begin();
+ it < histograms.end();
+ ++it) {
+ DeserializeHistogramInfo(*it);
+ }
+}
+
+// static
+bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) {
+ if (histogram_info.empty()) {
+ return false;
+ }
+
+ Pickle pickle(histogram_info.data(),
+ static_cast<int>(histogram_info.size()));
+ void* iter = NULL;
+ size_t bucket_count;
+ int declared_min;
+ int declared_max;
+ int histogram_type;
+ int flags;
+ std::string histogram_name;
+ SampleSet sample;
+
+ if (!pickle.ReadString(&iter, &histogram_name) ||
+ !pickle.ReadInt(&iter, &declared_min) ||
+ !pickle.ReadInt(&iter, &declared_max) ||
+ !pickle.ReadSize(&iter, &bucket_count) ||
+ !pickle.ReadInt(&iter, &histogram_type) ||
+ !pickle.ReadInt(&iter, &flags) ||
+ !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) {
+ LOG(ERROR) << "Picke error decoding Histogram: " << histogram_name;
+ return false;
+ }
+
+ Histogram* render_histogram =
+ StatisticsRecorder::GetHistogram(histogram_name);
+
+ 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 = reinterpret_cast<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);
+ }
+
+ DCHECK(declared_min == render_histogram->declared_min());
+ DCHECK(declared_max == render_histogram->declared_max());
+ DCHECK(bucket_count == render_histogram->bucket_count());
+ DCHECK(histogram_type == render_histogram->histogram_type());
+
+ if (render_histogram->flags() & kRendererHistogramFlag) {
+ 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
//------------------------------------------------------------------------------
@@ -383,7 +480,7 @@ Count Histogram::SampleSet::TotalCount() const {
Count total = 0;
for (Counts::const_iterator it = counts_.begin();
it != counts_.end();
- it++) {
+ ++it) {
total += *it;
}
return total;
@@ -393,7 +490,7 @@ void Histogram::SampleSet::Add(const SampleSet& other) {
DCHECK(counts_.size() == other.counts_.size());
sum_ += other.sum_;
square_sum_ += other.square_sum_;
- for (size_t index = 0; index < counts_.size(); index++)
+ for (size_t index = 0; index < counts_.size(); ++index)
counts_[index] += other.counts_[index];
}
@@ -404,19 +501,57 @@ void Histogram::SampleSet::Subtract(const SampleSet& other) {
// calculated). As a result, we don't currently CHCEK() for positive values.
sum_ -= other.sum_;
square_sum_ -= other.square_sum_;
- for (size_t index = 0; index < counts_.size(); index++) {
+ for (size_t index = 0; index < counts_.size(); ++index) {
counts_[index] -= other.counts_[index];
DCHECK(counts_[index] >= 0);
}
}
+bool Histogram::SampleSet::Serialize(Pickle* pickle) const {
+ pickle->WriteInt64(sum_);
+ pickle->WriteInt64(square_sum_);
+ pickle->WriteSize(counts_.size());
+
+ for (size_t index = 0; index < counts_.size(); ++index) {
+ pickle->WriteInt(counts_[index]);
+ }
+
+ return true;
+}
+
+bool Histogram::SampleSet::Deserialize(void** iter, const Pickle& pickle) {
+ DCHECK(counts_.size() == 0);
+ DCHECK(sum_ == 0);
+ DCHECK(square_sum_ == 0);
+
+ size_t counts_size;
+
+ if (!pickle.ReadInt64(iter, &sum_) ||
+ !pickle.ReadInt64(iter, &square_sum_) ||
+ !pickle.ReadSize(iter, &counts_size)) {
+ return false;
+ }
+
+ if (counts_size <= 0)
+ return false;
+
+ counts_.resize(counts_size, 0);
+ for (size_t index = 0; index < counts_size; ++index) {
+ if (!pickle.ReadInt(iter, &counts_[index])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
//------------------------------------------------------------------------------
// LinearHistogram: This histogram uses a traditional set of evenly spaced
// buckets.
//------------------------------------------------------------------------------
-LinearHistogram::LinearHistogram(const char* name,
- Sample minimum, Sample maximum, size_t bucket_count)
+LinearHistogram::LinearHistogram(const char* name, Sample minimum,
+ Sample maximum, size_t bucket_count)
: Histogram(name, minimum >= 1 ? minimum : 1, maximum, bucket_count) {
InitializeBucketRange();
DCHECK(ValidateBucketRanges());
@@ -457,7 +592,7 @@ void LinearHistogram::InitializeBucketRange() {
double min = declared_min();
double max = declared_max();
size_t i;
- for (i = 1; i < bucket_count(); i++) {
+ for (i = 1; i < bucket_count(); ++i) {
double linear_range = (min * (bucket_count() -1 - i) + max * (i - 1)) /
(bucket_count() - 2);
SetBucketRange(i, static_cast<int> (linear_range + 0.5));
@@ -548,30 +683,30 @@ bool StatisticsRecorder::WasStarted() {
}
// static
-bool StatisticsRecorder::Register(const Histogram& histogram) {
+bool StatisticsRecorder::Register(Histogram* histogram) {
if (!histograms_)
return false;
- const std::string name = histogram.histogram_name();
+ const std::string name = histogram->histogram_name();
AutoLock auto_lock(*lock_);
DCHECK(histograms_->end() == histograms_->find(name)) << name << " is already"
"registered as a histogram. Check for duplicate use of the name, or a "
"race where a static initializer could be run by several threads.";
- (*histograms_)[name] = &histogram;
+ (*histograms_)[name] = histogram;
return true;
}
// static
-void StatisticsRecorder::UnRegister(const Histogram& histogram) {
+void StatisticsRecorder::UnRegister(Histogram* histogram) {
if (!histograms_)
return;
- const std::string name = histogram.histogram_name();
+ 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);
+ histogram->WriteAscii(true, "\n", &output);
LOG(INFO) << output;
}
}
@@ -593,7 +728,7 @@ void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
GetSnapshot(query, &snapshot);
for (Histograms::iterator it = snapshot.begin();
it != snapshot.end();
- it++) {
+ ++it) {
(*it)->WriteHTMLGraph(output);
output->append("<br><hr><br>");
}
@@ -602,7 +737,7 @@ void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
// static
void StatisticsRecorder::WriteGraph(const std::string& query,
- std::string* output) {
+ std::string* output) {
if (!histograms_)
return;
if (query.length())
@@ -614,7 +749,7 @@ void StatisticsRecorder::WriteGraph(const std::string& query,
GetSnapshot(query, &snapshot);
for (Histograms::iterator it = snapshot.begin();
it != snapshot.end();
- it++) {
+ ++it) {
(*it)->WriteAscii(true, "\n", output);
output->append("\n");
}
@@ -627,18 +762,31 @@ void StatisticsRecorder::GetHistograms(Histograms* output) {
AutoLock auto_lock(*lock_);
for (HistogramMap::iterator it = histograms_->begin();
histograms_->end() != it;
- it++) {
+ ++it) {
output->push_back(it->second);
}
}
+Histogram* StatisticsRecorder::GetHistogram(const std::string& query) {
+ if (!histograms_)
+ return NULL;
+ 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;
+ }
+ return NULL;
+}
+
// private static
void StatisticsRecorder::GetSnapshot(const std::string& query,
Histograms* snapshot) {
AutoLock auto_lock(*lock_);
for (HistogramMap::iterator it = histograms_->begin();
histograms_->end() != it;
- it++) {
+ ++it) {
if (it->first.find(query) != std::string::npos)
snapshot->push_back(it->second);
}