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
This commit is contained in:
1
AUTHORS
1
AUTHORS
@ -27,3 +27,4 @@ Mohamed Mansour <m0.interactive@gmail.com>
|
||||
Joshua Roesslein <jroesslein@gmail.com>
|
||||
Yong Shin <sy3620@gmail.com>
|
||||
Laszlo Radanyi <bekkra@gmail.com>
|
||||
Raman Tenneti <raman.tenneti@gmail.com>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/lock.h"
|
||||
#include "base/pickle.h"
|
||||
#include "base/scoped_ptr.h"
|
||||
#include "base/stats_counters.h"
|
||||
|
||||
@ -118,6 +119,11 @@
|
||||
|
||||
static const int kUmaTargetedHistogramFlag = 0x1;
|
||||
|
||||
// This indicates the histogram is shadow copy of renderer histrogram
|
||||
// constructed by unpick method and updated regularly from renderer upload
|
||||
// of histograms.
|
||||
static const int kRendererHistogramFlag = 1 << 4;
|
||||
|
||||
#define UMA_HISTOGRAM_TIMES(name, sample) do { \
|
||||
static Histogram counter((name), base::TimeDelta::FromMilliseconds(1), \
|
||||
base::TimeDelta::FromSeconds(10), 50); \
|
||||
@ -183,6 +189,11 @@ class Histogram : public StatsRate {
|
||||
|
||||
static const int kHexRangePrintingFlag;
|
||||
|
||||
enum BucketLayout {
|
||||
EXPONENTIAL,
|
||||
LINEAR
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Statistic values, developed over the life of the histogram.
|
||||
|
||||
@ -206,6 +217,9 @@ class Histogram : public StatsRate {
|
||||
void Add(const SampleSet& other);
|
||||
void Subtract(const SampleSet& other);
|
||||
|
||||
bool Serialize(Pickle* pickle) const;
|
||||
bool Deserialize(void** iter, const Pickle& pickle);
|
||||
|
||||
protected:
|
||||
// Actual histogram data is stored in buckets, showing the count of values
|
||||
// that fit into each bucket.
|
||||
@ -228,6 +242,8 @@ class Histogram : public StatsRate {
|
||||
// input the stats counter sees.
|
||||
virtual void Add(int value);
|
||||
|
||||
void AddSampleSet(const SampleSet& sample);
|
||||
|
||||
// The following methods provide graphical histogram displays.
|
||||
void WriteHTMLGraph(std::string* output) const;
|
||||
void WriteAscii(bool graph_it, const std::string& newline,
|
||||
@ -240,6 +256,26 @@ class Histogram : public StatsRate {
|
||||
void ClearFlags(int flags) { flags_ &= ~flags; }
|
||||
int flags() const { return flags_; }
|
||||
|
||||
virtual BucketLayout histogram_type() const { return EXPONENTIAL; }
|
||||
|
||||
// Convenience methods for serializing/deserializing the histograms.
|
||||
// Histograms from Renderer process are serialized and sent to the browser.
|
||||
// Browser process reconstructs the histogram from the pickled version
|
||||
// accumulates the browser-side shadow copy of histograms (that mirror
|
||||
// histograms created in the renderer).
|
||||
|
||||
// Serialize the given snapshot of a Histogram into a String. Uses
|
||||
// Pickle class to flatten the object.
|
||||
static std::string SerializeHistogramInfo(const Histogram& histogram,
|
||||
const SampleSet& snapshot);
|
||||
// The following method accepts a list of pickled histograms and
|
||||
// builds a histogram and updates shadow copy of histogram data in the
|
||||
// browser process.
|
||||
static void DeserializeHistogramList(
|
||||
const std::vector<std::string>& histograms);
|
||||
static bool DeserializeHistogramInfo(const std::string& state);
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Accessors for serialization and testing.
|
||||
//----------------------------------------------------------------------------
|
||||
@ -344,7 +380,7 @@ class Histogram : public StatsRate {
|
||||
// Indicate if successfully registered.
|
||||
bool registered_;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(Histogram);
|
||||
DISALLOW_COPY_AND_ASSIGN(Histogram);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -358,15 +394,18 @@ class LinearHistogram : public Histogram {
|
||||
const char* description; // Null means end of a list of pairs.
|
||||
};
|
||||
LinearHistogram(const char* name, Sample minimum,
|
||||
Sample maximum, size_t bucket_count);
|
||||
Sample maximum, size_t bucket_count);
|
||||
|
||||
LinearHistogram(const char* name, base::TimeDelta minimum,
|
||||
base::TimeDelta maximum, size_t bucket_count);
|
||||
base::TimeDelta maximum, size_t bucket_count);
|
||||
~LinearHistogram() {}
|
||||
|
||||
// Store a list of number/text values for use in rendering the histogram.
|
||||
// The last element in the array has a null in its "description" slot.
|
||||
void SetRangeDescriptions(const DescriptionPair descriptions[]);
|
||||
|
||||
virtual BucketLayout histogram_type() const { return LINEAR; }
|
||||
|
||||
protected:
|
||||
// Initialize ranges_ mapping.
|
||||
virtual void InitializeBucketRange();
|
||||
@ -389,7 +428,7 @@ class LinearHistogram : public Histogram {
|
||||
typedef std::map<Sample, std::string> BucketDescriptionMap;
|
||||
BucketDescriptionMap bucket_description_;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(LinearHistogram);
|
||||
DISALLOW_COPY_AND_ASSIGN(LinearHistogram);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -404,7 +443,7 @@ class BooleanHistogram : public LinearHistogram {
|
||||
virtual void AddBoolean(bool value) { Add(value ? 1 : 0); }
|
||||
|
||||
private:
|
||||
DISALLOW_EVIL_CONSTRUCTORS(BooleanHistogram);
|
||||
DISALLOW_COPY_AND_ASSIGN(BooleanHistogram);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -428,7 +467,7 @@ class ThreadSafeHistogram : public Histogram {
|
||||
private:
|
||||
Lock lock_;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(ThreadSafeHistogram);
|
||||
DISALLOW_COPY_AND_ASSIGN(ThreadSafeHistogram);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -438,7 +477,7 @@ class ThreadSafeHistogram : public Histogram {
|
||||
|
||||
class StatisticsRecorder {
|
||||
public:
|
||||
typedef std::vector<const Histogram*> Histograms;
|
||||
typedef std::vector<Histogram*> Histograms;
|
||||
|
||||
StatisticsRecorder();
|
||||
|
||||
@ -449,9 +488,9 @@ class StatisticsRecorder {
|
||||
|
||||
// Register, or add a new histogram to the collection of statistics.
|
||||
// Return true if registered.
|
||||
static bool Register(const Histogram& histogram);
|
||||
static bool Register(Histogram* histogram);
|
||||
// Unregister, or remove, a histogram from the collection of statistics.
|
||||
static void UnRegister(const Histogram& histogram);
|
||||
static void UnRegister(Histogram* histogram);
|
||||
|
||||
// Methods for printing histograms. Only histograms which have query as
|
||||
// a substring are written to output (an empty string will process all
|
||||
@ -462,11 +501,9 @@ class StatisticsRecorder {
|
||||
// Method for extracting histograms which were marked for use by UMA.
|
||||
static void GetHistograms(Histograms* output);
|
||||
|
||||
static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; }
|
||||
static Histogram* GetHistogram(const std::string& query);
|
||||
|
||||
private:
|
||||
typedef std::map<std::string, const Histogram*> HistogramMap;
|
||||
// We keep all registered histograms in a map, from name to histogram.
|
||||
static void set_dump_on_exit(bool enable) { dump_on_exit_ = enable; }
|
||||
|
||||
// GetSnapshot copies some of the pointers to registered histograms into the
|
||||
// caller supplied vector (Histograms). Only histograms with names matching
|
||||
@ -474,14 +511,20 @@ class StatisticsRecorder {
|
||||
// pointer to be copied.
|
||||
static void GetSnapshot(const std::string& query, Histograms* snapshot);
|
||||
|
||||
|
||||
private:
|
||||
// We keep all registered histograms in a map, from name to histogram.
|
||||
typedef std::map<std::string, Histogram*> HistogramMap;
|
||||
|
||||
static HistogramMap* histograms_;
|
||||
|
||||
// lock protects access to the above map.
|
||||
static Lock* lock_;
|
||||
|
||||
// Dump all known histograms to log.
|
||||
static bool dump_on_exit_;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(StatisticsRecorder);
|
||||
DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
|
||||
};
|
||||
|
||||
#endif // BASE_HISTOGRAM_H__
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "base/file_version_info.h"
|
||||
#include "base/histogram.h"
|
||||
#include "base/platform_thread.h"
|
||||
#include "base/stats_table.h"
|
||||
#include "base/string_piece.h"
|
||||
#include "base/string_util.h"
|
||||
@ -21,11 +22,13 @@
|
||||
#include "chrome/browser/net/dns_global.h"
|
||||
#include "chrome/browser/profile.h"
|
||||
#include "chrome/browser/profile_manager.h"
|
||||
#include "chrome/browser/renderer_host/render_process_host.h"
|
||||
#include "chrome/browser/renderer_host/render_view_host.h"
|
||||
#include "chrome/common/jstemplate_builder.h"
|
||||
#include "chrome/common/l10n_util.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
#include "chrome/common/pref_service.h"
|
||||
#include "chrome/common/render_messages.h"
|
||||
#include "chrome/common/resource_bundle.h"
|
||||
#include "chrome/renderer/about_handler.h"
|
||||
#include "googleurl/src/gurl.h"
|
||||
@ -292,7 +295,7 @@ std::string BrowserAboutHandler::AboutVersion() {
|
||||
|
||||
// static
|
||||
std::string BrowserAboutHandler::AboutCredits() {
|
||||
static const std::string credits_html =
|
||||
static const std::string credits_html =
|
||||
ResourceBundle::GetSharedInstance().GetDataResource(
|
||||
IDR_CREDITS_HTML);
|
||||
|
||||
@ -301,7 +304,7 @@ std::string BrowserAboutHandler::AboutCredits() {
|
||||
|
||||
// static
|
||||
std::string BrowserAboutHandler::AboutTerms() {
|
||||
static const std::string terms_html =
|
||||
static const std::string terms_html =
|
||||
ResourceBundle::GetSharedInstance().GetDataResource(
|
||||
IDR_TERMS_HTML);
|
||||
|
||||
@ -344,6 +347,15 @@ std::string BrowserAboutHandler::AboutPlugins() {
|
||||
// static
|
||||
std::string BrowserAboutHandler::AboutHistograms(const std::string& query) {
|
||||
std::string data;
|
||||
for (RenderProcessHost::iterator it = RenderProcessHost::begin();
|
||||
it != RenderProcessHost::end(); ++it) {
|
||||
it->second->Send(new ViewMsg_GetRendererHistograms());
|
||||
}
|
||||
|
||||
// TODO(raman): Delay page layout until we get respnoses
|
||||
// back from renderers, and not have to use a fixed size delay.
|
||||
PlatformThread::Sleep(1000);
|
||||
|
||||
StatisticsRecorder::WriteHTMLGraph(query, &data);
|
||||
return data;
|
||||
}
|
||||
|
@ -1755,9 +1755,21 @@ void MetricsService::RecordCurrentState(PrefService* pref) {
|
||||
RecordPluginChanges(pref);
|
||||
}
|
||||
|
||||
void MetricsService::CollectRendererHistograms() {
|
||||
for (RenderProcessHost::iterator it = RenderProcessHost::begin();
|
||||
it != RenderProcessHost::end(); ++it) {
|
||||
it->second->Send(new ViewMsg_GetRendererHistograms());
|
||||
}
|
||||
}
|
||||
|
||||
void MetricsService::RecordCurrentHistograms() {
|
||||
DCHECK(current_log_);
|
||||
|
||||
CollectRendererHistograms();
|
||||
|
||||
// TODO(raman): Delay the metrics collection activities until we get all the
|
||||
// updates from the renderers, or we time out (1 second? 3 seconds?).
|
||||
|
||||
StatisticsRecorder::Histograms histograms;
|
||||
StatisticsRecorder::GetHistograms(&histograms);
|
||||
for (StatisticsRecorder::Histograms::iterator it = histograms.begin();
|
||||
|
@ -342,9 +342,14 @@ class MetricsService : public NotificationObserver,
|
||||
// buffered plugin stability statistics.
|
||||
void RecordCurrentState(PrefService* pref);
|
||||
|
||||
// Requests all renderers to send their histograms back for
|
||||
// collecting stats from renderers.
|
||||
void CollectRendererHistograms();
|
||||
|
||||
// Record complete list of histograms into the current log.
|
||||
// Called when we close a log.
|
||||
void RecordCurrentHistograms();
|
||||
|
||||
// Record a specific histogram .
|
||||
void RecordHistogram(const Histogram& histogram);
|
||||
|
||||
|
@ -139,7 +139,7 @@ ResourceMessageFilter::~ResourceMessageFilter() {
|
||||
void ResourceMessageFilter::OnFilterAdded(IPC::Channel* channel) {
|
||||
channel_ = channel;
|
||||
|
||||
// Add the observers to intercept
|
||||
// Add the observers to intercept.
|
||||
NotificationService::current()->AddObserver(
|
||||
this,
|
||||
NotificationType::SPELLCHECKER_REINITIALIZED,
|
||||
@ -197,6 +197,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) {
|
||||
OnOpenChannelToPlugin)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_SpellCheck, OnSpellCheck)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_RendererHistograms,
|
||||
OnRendererHistograms)
|
||||
IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_PaintRect,
|
||||
render_widget_helper_->DidReceivePaintMsg(message))
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsAsync,
|
||||
@ -412,7 +414,7 @@ void ResourceMessageFilter::OnPluginSyncMessage(const FilePath& plugin_path,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_WIN) // This hack is Windows-specific.
|
||||
#if defined(OS_WIN) // This hack is Windows-specific.
|
||||
void ResourceMessageFilter::OnLoadFont(LOGFONT font) {
|
||||
// If renderer is running in a sandbox, GetTextMetrics
|
||||
// can sometimes fail. If a font has not been loaded
|
||||
@ -500,7 +502,7 @@ void ResourceMessageFilter::OnClipboardWriteObjects(
|
||||
// on the UI thread. We'll copy the relevant data and get a handle to any
|
||||
// shared memory so it doesn't go away when we resume the renderer, and post
|
||||
// a task to perform the write on the UI thread.
|
||||
Clipboard::ObjectMap* long_living_objects = new Clipboard::ObjectMap(objects);
|
||||
Clipboard::ObjectMap* long_living_objects = new Clipboard::ObjectMap(objects);
|
||||
|
||||
// We pass the render_handle_ to assist the clipboard with using shared
|
||||
// memory objects. render_handle_ is a handle to the process that would
|
||||
@ -639,7 +641,7 @@ void ResourceMessageFilter::OnResourceTypeStats(
|
||||
}
|
||||
|
||||
void ResourceMessageFilter::OnResolveProxy(const GURL& url,
|
||||
IPC::Message* reply_msg) {
|
||||
IPC::Message* reply_msg) {
|
||||
resolve_proxy_msg_helper_.Start(url, reply_msg);
|
||||
}
|
||||
|
||||
@ -764,7 +766,7 @@ ClipboardService* ResourceMessageFilter::GetClipboardService() {
|
||||
// the spellcheck dictionaries into the browser process, and all renderers ask
|
||||
// the browsers to do SpellChecking.
|
||||
//
|
||||
// This filter should not try to initialize the spellchecker. It is up to the
|
||||
// This filter should not try to initialize the spellchecker. It is up to the
|
||||
// profile to initialize it when required, and send it here. If |spellchecker_|
|
||||
// is made NULL, it corresponds to spellchecker turned off - i.e., all
|
||||
// spellings are correct.
|
||||
@ -787,7 +789,7 @@ void ResourceMessageFilter::OnSpellCheck(const std::wstring& word,
|
||||
return;
|
||||
}
|
||||
|
||||
void ResourceMessageFilter::Observe(NotificationType type,
|
||||
void ResourceMessageFilter::Observe(NotificationType type,
|
||||
const NotificationSource &source,
|
||||
const NotificationDetails &details) {
|
||||
if (type == NotificationType::SPELLCHECKER_REINITIALIZED) {
|
||||
@ -801,9 +803,14 @@ void ResourceMessageFilter::OnDnsPrefetch(
|
||||
chrome_browser_net::DnsPrefetchList(hostnames);
|
||||
}
|
||||
|
||||
void ResourceMessageFilter::OnRendererHistograms(
|
||||
const std::vector<std::string>& histograms) {
|
||||
Histogram::DeserializeHistogramList(histograms);
|
||||
}
|
||||
|
||||
void ResourceMessageFilter::OnCreateAudioStream(
|
||||
const IPC::Message& msg, int stream_id,
|
||||
const ViewHostMsg_Audio_CreateStream& params) {
|
||||
const IPC::Message& msg, int stream_id,
|
||||
const ViewHostMsg_Audio_CreateStream& params) {
|
||||
// TODO(hclam): call to AudioRendererHost::CreateStream and send a message to
|
||||
// renderer to notify the result.
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
#ifndef CHROME_BROWSER_RENDERER_HOST_RESOURCE_MSG_FILTER_H_
|
||||
#define CHROME_BROWSER_RENDERER_HOST_RESOURCE_MSG_FILTER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/clipboard.h"
|
||||
#include "base/file_path.h"
|
||||
#include "base/gfx/rect.h"
|
||||
@ -146,6 +149,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
|
||||
void OnSpellCheck(const std::wstring& word,
|
||||
IPC::Message* reply_msg);
|
||||
void OnDnsPrefetch(const std::vector<std::string>& hostnames);
|
||||
void OnRendererHistograms(const std::vector<std::string>& histogram_info);
|
||||
void OnReceiveContextMenuMsg(const IPC::Message& msg);
|
||||
// Clipboard messages
|
||||
void OnClipboardWriteObjects(const Clipboard::ObjectMap& objects);
|
||||
|
@ -330,6 +330,7 @@
|
||||
A7C613C10F30D7E4008CEE5D /* mock_render_process_host.cc in Sources */ = {isa = PBXBuildFile; fileRef = A7C613BF0F30D7E4008CEE5D /* mock_render_process_host.cc */; };
|
||||
A7C6146F0F30DA1D008CEE5D /* ipc_test_sink.cc in Sources */ = {isa = PBXBuildFile; fileRef = A7C6146D0F30DA1D008CEE5D /* ipc_test_sink.cc */; };
|
||||
A7CBAD390F322A7E00360BF5 /* shell_dialogs_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = A7CBAD370F322A7E00360BF5 /* shell_dialogs_mac.mm */; };
|
||||
AB3B4B2B0F549D9E0009E2BF /* renderer_histogram_snapshots.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB3B4B290F549D9E0009E2BF /* renderer_histogram_snapshots.cc */; };
|
||||
AB8963000F4E0901009CFFAC /* audio_renderer_impl.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB8962FA0F4E087E009CFFAC /* audio_renderer_impl.cc */; };
|
||||
AB8963010F4E0907009CFFAC /* data_source_impl.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB8962FC0F4E087E009CFFAC /* data_source_impl.cc */; };
|
||||
AB8963020F4E090D009CFFAC /* video_renderer_impl.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB8962FE0F4E087E009CFFAC /* video_renderer_impl.cc */; };
|
||||
@ -2523,6 +2524,8 @@
|
||||
A7C6146E0F30DA1D008CEE5D /* ipc_test_sink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipc_test_sink.h; sourceTree = "<group>"; };
|
||||
A7CBAD370F322A7E00360BF5 /* shell_dialogs_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = shell_dialogs_mac.mm; sourceTree = "<group>"; };
|
||||
A9C335E39D39A7DE087850FC /* url_pattern_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = url_pattern_unittest.cc; path = extensions/url_pattern_unittest.cc; sourceTree = "<group>"; };
|
||||
AB3B4B290F549D9E0009E2BF /* renderer_histogram_snapshots.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = renderer_histogram_snapshots.cc; sourceTree = "<group>"; };
|
||||
AB3B4B2A0F549D9E0009E2BF /* renderer_histogram_snapshots.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = renderer_histogram_snapshots.h; sourceTree = "<group>"; };
|
||||
AB8962FA0F4E087E009CFFAC /* audio_renderer_impl.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = audio_renderer_impl.cc; path = media/audio_renderer_impl.cc; sourceTree = "<group>"; };
|
||||
AB8962FB0F4E087E009CFFAC /* audio_renderer_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = audio_renderer_impl.h; path = media/audio_renderer_impl.h; sourceTree = "<group>"; };
|
||||
AB8962FC0F4E087E009CFFAC /* data_source_impl.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = data_source_impl.cc; path = media/data_source_impl.cc; sourceTree = "<group>"; };
|
||||
@ -3107,6 +3110,8 @@
|
||||
4D640CD60EAE868600EBCFC0 /* render_widget.h */,
|
||||
4D640CD70EAE868600EBCFC0 /* render_widget_unittest.cc */,
|
||||
4D640CD80EAE868600EBCFC0 /* renderer_glue.cc */,
|
||||
AB3B4B290F549D9E0009E2BF /* renderer_histogram_snapshots.cc */,
|
||||
AB3B4B2A0F549D9E0009E2BF /* renderer_histogram_snapshots.h */,
|
||||
4D640CD90EAE868600EBCFC0 /* renderer_main.cc */,
|
||||
B51F6D110F37C4DC00152D66 /* renderer_main_platform_delegate.h */,
|
||||
B51F6D130F37C4DC00152D66 /* renderer_main_platform_delegate_mac.mm */,
|
||||
@ -5433,9 +5438,10 @@
|
||||
3380A6A10F2E91F9004EF74F /* render_process.cc in Sources */,
|
||||
3380A69D0F2E91D4004EF74F /* render_thread.cc in Sources */,
|
||||
A7A20E650F3A1E1C00F62B4D /* render_view.cc in Sources */,
|
||||
B503E0F00F0175FD00547DC6 /* user_script_slave.cc in Sources */,
|
||||
AB3B4B2B0F549D9E0009E2BF /* renderer_histogram_snapshots.cc in Sources */,
|
||||
B51F6D2E0F37D04200152D66 /* renderer_main.cc in Sources */,
|
||||
B51F6D150F37C4DC00152D66 /* renderer_main_platform_delegate_mac.mm in Sources */,
|
||||
B503E0F00F0175FD00547DC6 /* user_script_slave.cc in Sources */,
|
||||
AB8963020F4E090D009CFFAC /* video_renderer_impl.cc in Sources */,
|
||||
4D640CF50EAE86EF00EBCFC0 /* visitedlink_slave.cc in Sources */,
|
||||
);
|
||||
|
@ -460,6 +460,9 @@ IPC_BEGIN_MESSAGES(View)
|
||||
// resource types.
|
||||
IPC_MESSAGE_CONTROL0(ViewMsg_GetCacheResourceStats)
|
||||
|
||||
// Asks the renderer to send back Histograms.
|
||||
IPC_MESSAGE_CONTROL0(ViewMsg_GetRendererHistograms)
|
||||
|
||||
// Notifies the renderer about ui theme changes
|
||||
IPC_MESSAGE_ROUTED0(ViewMsg_ThemeChanged)
|
||||
|
||||
@ -1027,6 +1030,9 @@ IPC_BEGIN_MESSAGES(ViewHost)
|
||||
IPC_MESSAGE_ROUTED1(ViewHostMsg_UserMetricsRecordAction,
|
||||
std::wstring /* action */)
|
||||
|
||||
// Send back histograms as vector of pickled-histogram strings.
|
||||
IPC_MESSAGE_CONTROL1(ViewHostMsg_RendererHistograms, std::vector<std::string>)
|
||||
|
||||
// Request for a DNS prefetch of the names in the array.
|
||||
// NameList is typedef'ed std::vector<std::string>
|
||||
IPC_MESSAGE_CONTROL1(ViewHostMsg_DnsPrefetch,
|
||||
|
@ -59,7 +59,8 @@ RenderThread::RenderThread(const std::wstring& channel_name)
|
||||
MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kStackSize)),
|
||||
visited_link_slave_(NULL),
|
||||
user_script_slave_(NULL),
|
||||
render_dns_master_(NULL) {
|
||||
render_dns_master_(NULL),
|
||||
renderer_histogram_snapshots_(NULL) {
|
||||
SetChannelName(channel_name);
|
||||
}
|
||||
|
||||
@ -83,6 +84,10 @@ void RenderThread::Resolve(const char* name, size_t length) {
|
||||
return render_dns_master_->Resolve(name, length);
|
||||
}
|
||||
|
||||
void RenderThread::SendHistograms() {
|
||||
return renderer_histogram_snapshots_->SendHistograms();
|
||||
}
|
||||
|
||||
void RenderThread::Init() {
|
||||
ChildThread::Init();
|
||||
notification_service_.reset(new NotificationService);
|
||||
@ -97,6 +102,7 @@ void RenderThread::Init() {
|
||||
visited_link_slave_ = new VisitedLinkSlave();
|
||||
user_script_slave_ = new UserScriptSlave();
|
||||
render_dns_master_.reset(new RenderDnsMaster());
|
||||
renderer_histogram_snapshots_.reset(new RendererHistogramSnapshots());
|
||||
}
|
||||
|
||||
void RenderThread::CleanUp() {
|
||||
@ -140,6 +146,8 @@ void RenderThread::OnControlMessageReceived(const IPC::Message& msg) {
|
||||
// is there a new non-windows message I should add here?
|
||||
IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)
|
||||
IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)
|
||||
IPC_MESSAGE_HANDLER(ViewMsg_GetRendererHistograms,
|
||||
OnGetRendererHistograms)
|
||||
IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,
|
||||
OnGetCacheResourceStats)
|
||||
IPC_MESSAGE_HANDLER(ViewMsg_PluginMessage, OnPluginMessage)
|
||||
@ -212,6 +220,10 @@ void RenderThread::OnGetCacheResourceStats() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenderThread::OnGetRendererHistograms() {
|
||||
SendHistograms();
|
||||
}
|
||||
|
||||
void RenderThread::InformHostOfCacheStats() {
|
||||
#if defined(OS_WIN) || defined(OS_LINUX)
|
||||
CacheManager::UsageStats stats;
|
||||
|
@ -12,10 +12,12 @@
|
||||
#include "base/task.h"
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/common/child_thread.h"
|
||||
#include "chrome/renderer/renderer_histogram_snapshots.h"
|
||||
|
||||
class FilePath;
|
||||
class NotificationService;
|
||||
class RenderDnsMaster;
|
||||
class RendererHistogram;
|
||||
class SkBitmap;
|
||||
class UserScriptSlave;
|
||||
class VisitedLinkSlave;
|
||||
@ -86,6 +88,9 @@ class RenderThread : public RenderThreadBase,
|
||||
// Do DNS prefetch resolution of a hostname.
|
||||
void Resolve(const char* name, size_t length);
|
||||
|
||||
// Send all the Histogram data to browser.
|
||||
void SendHistograms();
|
||||
|
||||
// Invokes InformHostOfCacheStats after a short delay. Used to move this
|
||||
// bookkeeping operation off the critical latency path.
|
||||
void InformHostOfCacheStatsLater();
|
||||
@ -113,6 +118,9 @@ class RenderThread : public RenderThreadBase,
|
||||
size_t capacity);
|
||||
void OnGetCacheResourceStats();
|
||||
|
||||
// Send all histograms to browser.
|
||||
void OnGetRendererHistograms();
|
||||
|
||||
// Gather usage statistics from the in-memory cache and inform our host.
|
||||
// These functions should be call periodically so that the host can make
|
||||
// decisions about how to allocation resources using current information.
|
||||
@ -124,6 +132,8 @@ class RenderThread : public RenderThreadBase,
|
||||
|
||||
scoped_ptr<RenderDnsMaster> render_dns_master_;
|
||||
|
||||
scoped_ptr<RendererHistogramSnapshots> renderer_histogram_snapshots_;
|
||||
|
||||
scoped_ptr<ScopedRunnableMethodFactory<RenderThread> > cache_stats_factory_;
|
||||
|
||||
scoped_ptr<NotificationService> notification_service_;
|
||||
|
@ -83,6 +83,8 @@ input_files = ChromeFileList([
|
||||
'render_widget.cc',
|
||||
'render_widget.h',
|
||||
'renderer_glue.cc',
|
||||
'renderer_histogram_snapshots.cc',
|
||||
'renderer_histogram_snapshots.h',
|
||||
'renderer_main.cc',
|
||||
'renderer_resources.h',
|
||||
'user_script_slave.cc',
|
||||
|
@ -297,6 +297,14 @@
|
||||
RelativePath=".\renderer_glue.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\renderer_histogram_snapshots.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\renderer_histogram_snapshots.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\renderer_main.cc"
|
||||
>
|
||||
|
94
chrome/renderer/renderer_histogram_snapshots.cc
Normal file
94
chrome/renderer/renderer_histogram_snapshots.cc
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "chrome/renderer/renderer_histogram_snapshots.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "base/histogram.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/pickle.h"
|
||||
#include "chrome/common/render_messages.h"
|
||||
#include "chrome/renderer/render_process.h"
|
||||
#include "chrome/renderer/render_thread.h"
|
||||
|
||||
// TODO(raman): Before renderer shuts down send final snapshot lists.
|
||||
|
||||
RendererHistogramSnapshots::RendererHistogramSnapshots()
|
||||
: ALLOW_THIS_IN_INITIALIZER_LIST(
|
||||
renderer_histogram_snapshots_factory_(this)) {
|
||||
}
|
||||
|
||||
// Send data quickly!
|
||||
void RendererHistogramSnapshots::SendHistograms() {
|
||||
RenderThread::current()->message_loop()->PostTask(FROM_HERE,
|
||||
renderer_histogram_snapshots_factory_.NewRunnableMethod(
|
||||
&RendererHistogramSnapshots::UploadAllHistrograms));
|
||||
}
|
||||
|
||||
void RendererHistogramSnapshots::UploadAllHistrograms() {
|
||||
StatisticsRecorder::Histograms histograms;
|
||||
StatisticsRecorder::GetHistograms(&histograms);
|
||||
|
||||
HistogramPickledList pickled_histograms;
|
||||
|
||||
for (StatisticsRecorder::Histograms::iterator it = histograms.begin();
|
||||
histograms.end() != it;
|
||||
it++) {
|
||||
UploadHistrogram(**it, &pickled_histograms);
|
||||
}
|
||||
// Send the handle over synchronous IPC.
|
||||
if (pickled_histograms.size() > 0) {
|
||||
RenderThread::current()->Send(
|
||||
new ViewHostMsg_RendererHistograms(pickled_histograms));
|
||||
}
|
||||
}
|
||||
|
||||
// Extract snapshot data and then send it off the the Browser process
|
||||
// to save it.
|
||||
void RendererHistogramSnapshots::UploadHistrogram(
|
||||
const Histogram& histogram,
|
||||
HistogramPickledList* pickled_histograms) {
|
||||
|
||||
// Get up-to-date snapshot of sample stats.
|
||||
Histogram::SampleSet snapshot;
|
||||
histogram.SnapshotSample(&snapshot);
|
||||
const std::string& histogram_name = histogram.histogram_name();
|
||||
|
||||
// Find the already sent stats, or create an empty set.
|
||||
LoggedSampleMap::iterator it = logged_samples_.find(histogram_name);
|
||||
Histogram::SampleSet* already_logged;
|
||||
if (logged_samples_.end() == it) {
|
||||
// Add new entry.
|
||||
already_logged = &logged_samples_[histogram.histogram_name()];
|
||||
already_logged->Resize(histogram); // Complete initialization.
|
||||
} else {
|
||||
already_logged = &(it->second);
|
||||
// Deduct any stats we've already logged from our snapshot.
|
||||
snapshot.Subtract(*already_logged);
|
||||
}
|
||||
|
||||
// Snapshot now contains only a delta to what we've already_logged.
|
||||
|
||||
if (snapshot.TotalCount() > 0) {
|
||||
UploadHistogramDelta(histogram, snapshot, pickled_histograms);
|
||||
// Add new data into our running total.
|
||||
already_logged->Add(snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererHistogramSnapshots::UploadHistogramDelta(
|
||||
const Histogram& histogram,
|
||||
const Histogram::SampleSet& snapshot,
|
||||
HistogramPickledList* pickled_histograms) {
|
||||
|
||||
DCHECK(0 != snapshot.TotalCount());
|
||||
snapshot.CheckSize(histogram);
|
||||
|
||||
std::string histogram_info =
|
||||
Histogram::SerializeHistogramInfo(histogram, snapshot);
|
||||
pickled_histograms->push_back(histogram_info);
|
||||
}
|
||||
|
54
chrome/renderer/renderer_histogram_snapshots.h
Normal file
54
chrome/renderer/renderer_histogram_snapshots.h
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CHROME_RENDERER_HISTOGRAM_SNAPSHOTS_H_
|
||||
#define CHROME_RENDERER_HISTOGRAM_SNAPSHOTS_H_
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/histogram.h"
|
||||
#include "base/process.h"
|
||||
#include "base/scoped_ptr.h"
|
||||
#include "base/task.h"
|
||||
|
||||
class RendererHistogramSnapshots {
|
||||
public:
|
||||
RendererHistogramSnapshots();
|
||||
|
||||
~RendererHistogramSnapshots() {}
|
||||
|
||||
// Send the histogram data.
|
||||
void SendHistograms();
|
||||
|
||||
// Maintain a map of histogram names to the sample stats we've sent.
|
||||
typedef std::map<std::string, Histogram::SampleSet> LoggedSampleMap;
|
||||
typedef std::vector<std::string> HistogramPickledList;
|
||||
|
||||
private:
|
||||
// Extract snapshot data and then send it off the the Browser process.
|
||||
// Send only a delta to what we have already sent.
|
||||
void UploadAllHistrograms();
|
||||
void UploadHistrogram(const Histogram& histogram,
|
||||
HistogramPickledList* histograms);
|
||||
void UploadHistogramDelta(const Histogram& histogram,
|
||||
const Histogram::SampleSet& snapshot,
|
||||
HistogramPickledList* histograms);
|
||||
|
||||
ScopedRunnableMethodFactory<RendererHistogramSnapshots>
|
||||
renderer_histogram_snapshots_factory_;
|
||||
|
||||
// For histograms, record what we've already logged (as a sample for each
|
||||
// histogram) so that we can send only the delta with the next log.
|
||||
LoggedSampleMap logged_samples_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RendererHistogramSnapshots);
|
||||
};
|
||||
|
||||
#endif // CHROME_RENDERER_HISTOGRAM_SNAPSHOTS_H_
|
||||
|
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/histogram.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/platform_thread.h"
|
||||
@ -89,6 +90,13 @@ int RendererMain(const MainFunctionParams& parameters) {
|
||||
|
||||
HandleRendererErrorTestParameters(parsed_command_line);
|
||||
|
||||
// Initialize histogram statistics gathering system.
|
||||
// Don't create StatisticsRecorde in the single process mode.
|
||||
scoped_ptr<StatisticsRecorder> statistics;
|
||||
if (!StatisticsRecorder::WasStarted()) {
|
||||
statistics.reset(new StatisticsRecorder());
|
||||
}
|
||||
|
||||
{
|
||||
RenderProcess render_process;
|
||||
bool run_loop = true;
|
||||
|
Reference in New Issue
Block a user