195 lines
5.9 KiB
C++
195 lines
5.9 KiB
C++
// Copyright (c) 2012 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 "base/metrics/sparse_histogram.h"
|
|
|
|
#include <utility>
|
|
|
|
#include "base/metrics/metrics_hashes.h"
|
|
#include "base/metrics/sample_map.h"
|
|
#include "base/metrics/statistics_recorder.h"
|
|
#include "base/pickle.h"
|
|
#include "base/strings/stringprintf.h"
|
|
#include "base/synchronization/lock.h"
|
|
|
|
namespace base {
|
|
|
|
typedef HistogramBase::Count Count;
|
|
typedef HistogramBase::Sample Sample;
|
|
|
|
// static
|
|
HistogramBase* SparseHistogram::FactoryGet(const std::string& name,
|
|
int32_t flags) {
|
|
HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
|
|
|
|
if (!histogram) {
|
|
// To avoid racy destruction at shutdown, the following will be leaked.
|
|
HistogramBase* tentative_histogram = new SparseHistogram(name);
|
|
tentative_histogram->SetFlags(flags);
|
|
histogram =
|
|
StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram);
|
|
}
|
|
DCHECK_EQ(SPARSE_HISTOGRAM, histogram->GetHistogramType());
|
|
return histogram;
|
|
}
|
|
|
|
SparseHistogram::~SparseHistogram() {}
|
|
|
|
uint64_t SparseHistogram::name_hash() const {
|
|
return samples_.id();
|
|
}
|
|
|
|
HistogramType SparseHistogram::GetHistogramType() const {
|
|
return SPARSE_HISTOGRAM;
|
|
}
|
|
|
|
bool SparseHistogram::HasConstructionArguments(
|
|
Sample /* expected_minimum */,
|
|
Sample /* expected_maximum */,
|
|
size_t /* expected_bucket_count */) const {
|
|
// SparseHistogram never has min/max/bucket_count limit.
|
|
return false;
|
|
}
|
|
|
|
void SparseHistogram::Add(Sample value) {
|
|
AddCount(value, 1);
|
|
}
|
|
|
|
void SparseHistogram::AddCount(Sample value, int count) {
|
|
if (count <= 0) {
|
|
NOTREACHED();
|
|
return;
|
|
}
|
|
{
|
|
base::AutoLock auto_lock(lock_);
|
|
samples_.Accumulate(value, count);
|
|
}
|
|
|
|
FindAndRunCallback(value);
|
|
}
|
|
|
|
scoped_ptr<HistogramSamples> SparseHistogram::SnapshotSamples() const {
|
|
scoped_ptr<SampleMap> snapshot(new SampleMap(name_hash()));
|
|
|
|
base::AutoLock auto_lock(lock_);
|
|
snapshot->Add(samples_);
|
|
return std::move(snapshot);
|
|
}
|
|
|
|
void SparseHistogram::AddSamples(const HistogramSamples& samples) {
|
|
base::AutoLock auto_lock(lock_);
|
|
samples_.Add(samples);
|
|
}
|
|
|
|
bool SparseHistogram::AddSamplesFromPickle(PickleIterator* iter) {
|
|
base::AutoLock auto_lock(lock_);
|
|
return samples_.AddFromPickle(iter);
|
|
}
|
|
|
|
void SparseHistogram::WriteHTMLGraph(std::string* output) const {
|
|
output->append("<PRE>");
|
|
WriteAsciiImpl(true, "<br>", output);
|
|
output->append("</PRE>");
|
|
}
|
|
|
|
void SparseHistogram::WriteAscii(std::string* output) const {
|
|
WriteAsciiImpl(true, "\n", output);
|
|
}
|
|
|
|
bool SparseHistogram::SerializeInfoImpl(Pickle* pickle) const {
|
|
return pickle->WriteString(histogram_name()) && pickle->WriteInt(flags());
|
|
}
|
|
|
|
SparseHistogram::SparseHistogram(const std::string& name)
|
|
: HistogramBase(name),
|
|
samples_(HashMetricName(name)) {}
|
|
|
|
HistogramBase* SparseHistogram::DeserializeInfoImpl(PickleIterator* iter) {
|
|
std::string histogram_name;
|
|
int flags;
|
|
if (!iter->ReadString(&histogram_name) || !iter->ReadInt(&flags)) {
|
|
DLOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name;
|
|
return NULL;
|
|
}
|
|
|
|
DCHECK(flags & HistogramBase::kIPCSerializationSourceFlag);
|
|
flags &= ~HistogramBase::kIPCSerializationSourceFlag;
|
|
|
|
return SparseHistogram::FactoryGet(histogram_name, flags);
|
|
}
|
|
|
|
void SparseHistogram::GetParameters(DictionaryValue* /* params */) const {
|
|
// TODO(kaiwang): Implement. (See HistogramBase::WriteJSON.)
|
|
}
|
|
|
|
void SparseHistogram::GetCountAndBucketData(Count* /* count */,
|
|
int64_t* /* sum */,
|
|
ListValue* /* buckets */) const {
|
|
// TODO(kaiwang): Implement. (See HistogramBase::WriteJSON.)
|
|
}
|
|
|
|
void SparseHistogram::WriteAsciiImpl(bool graph_it,
|
|
const std::string& newline,
|
|
std::string* output) const {
|
|
// Get a local copy of the data so we are consistent.
|
|
scoped_ptr<HistogramSamples> snapshot = SnapshotSamples();
|
|
Count total_count = snapshot->TotalCount();
|
|
double scaled_total_count = total_count / 100.0;
|
|
|
|
WriteAsciiHeader(total_count, output);
|
|
output->append(newline);
|
|
|
|
// Determine how wide the largest bucket range is (how many digits to print),
|
|
// so that we'll be able to right-align starts for the graphical bars.
|
|
// Determine which bucket has the largest sample count so that we can
|
|
// normalize the graphical bar-width relative to that sample count.
|
|
Count largest_count = 0;
|
|
Sample largest_sample = 0;
|
|
scoped_ptr<SampleCountIterator> it = snapshot->Iterator();
|
|
while (!it->Done()) {
|
|
Sample min;
|
|
Sample max;
|
|
Count count;
|
|
it->Get(&min, &max, &count);
|
|
if (min > largest_sample)
|
|
largest_sample = min;
|
|
if (count > largest_count)
|
|
largest_count = count;
|
|
it->Next();
|
|
}
|
|
size_t print_width = GetSimpleAsciiBucketRange(largest_sample).size() + 1;
|
|
|
|
// iterate over each item and display them
|
|
it = snapshot->Iterator();
|
|
while (!it->Done()) {
|
|
Sample min;
|
|
Sample max;
|
|
Count count;
|
|
it->Get(&min, &max, &count);
|
|
|
|
// value is min, so display it
|
|
std::string range = GetSimpleAsciiBucketRange(min);
|
|
output->append(range);
|
|
for (size_t j = 0; range.size() + j < print_width + 1; ++j)
|
|
output->push_back(' ');
|
|
|
|
if (graph_it)
|
|
WriteAsciiBucketGraph(count, largest_count, output);
|
|
WriteAsciiBucketValue(count, scaled_total_count, output);
|
|
output->append(newline);
|
|
it->Next();
|
|
}
|
|
}
|
|
|
|
void SparseHistogram::WriteAsciiHeader(const Count total_count,
|
|
std::string* output) const {
|
|
StringAppendF(output,
|
|
"Histogram: %s recorded %d samples",
|
|
histogram_name().c_str(),
|
|
total_count);
|
|
if (flags() & ~kHexRangePrintingFlag)
|
|
StringAppendF(output, " (flags = 0x%x)", flags() & ~kHexRangePrintingFlag);
|
|
}
|
|
|
|
} // namespace base
|