histogram_base.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram_base.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <climits>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_string_value_serializer.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram_samples.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/sparse_histogram.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/pickle.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/process_util.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/stringprintf.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string HistogramTypeToString(HistogramType type) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch(type) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case HISTOGRAM:
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "HISTOGRAM";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case LINEAR_HISTOGRAM:
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "LINEAR_HISTOGRAM";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BOOLEAN_HISTOGRAM:
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "BOOLEAN_HISTOGRAM";
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CUSTOM_HISTOGRAM:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CUSTOM_HISTOGRAM";
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPARSE_HISTOGRAM:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SPARSE_HISTOGRAM";
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN";
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* DeserializeHistogramInfo(PickleIterator* iter) {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int type;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!iter->ReadInt(&type))
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case HISTOGRAM:
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return Histogram::DeserializeInfoImpl(iter);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case LINEAR_HISTOGRAM:
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return LinearHistogram::DeserializeInfoImpl(iter);
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case BOOLEAN_HISTOGRAM:
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return BooleanHistogram::DeserializeInfoImpl(iter);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case CUSTOM_HISTOGRAM:
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return CustomHistogram::DeserializeInfoImpl(iter);
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case SPARSE_HISTOGRAM:
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return SparseHistogram::DeserializeInfoImpl(iter);
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return NULL;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeserializeHistogramAndAddSamples(PickleIterator* iter) {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HistogramBase* histogram = DeserializeHistogramInfo(iter);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!histogram)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (histogram->flags() & base::HistogramBase::kIPCSerializationSourceFlag) {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Single process mode, histogram observed and not copied: "
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << histogram->histogram_name();
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  histogram->AddSamplesFromPickle(iter);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const HistogramBase::Sample HistogramBase::kSampleType_MAX = INT_MAX;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistogramBase::HistogramBase(const std::string& name)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : histogram_name_(name),
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_(kNoFlags) {}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistogramBase::~HistogramBase() {}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistogramBase::SetFlags(int32 flags) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flags_ |= flags;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistogramBase::ClearFlags(int32 flags) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flags_ &= ~flags;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistogramBase::AddTime(const TimeDelta& time) {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Add(static_cast<Sample>(time.InMilliseconds()));
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistogramBase::AddBoolean(bool value) {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Add(value ? 1 : 0);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HistogramBase::SerializeInfo(Pickle* pickle) const {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!pickle->WriteInt(GetHistogramType()))
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return SerializeInfoImpl(pickle);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int HistogramBase::FindCorruption(const HistogramSamples& samples) const {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Not supported by default.
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NO_INCONSISTENCIES;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistogramBase::WriteJSON(std::string* output) const {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Count count;
112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  int64 sum;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ListValue> buckets(new ListValue());
114b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  GetCountAndBucketData(&count, &sum, buckets.get());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DictionaryValue> parameters(new DictionaryValue());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetParameters(parameters.get());
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JSONStringValueSerializer serializer(output);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue root;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root.SetString("name", histogram_name());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root.SetInteger("count", count);
122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  root.SetDouble("sum", sum);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root.SetInteger("flags", flags());
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root.Set("params", parameters.release());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root.Set("buckets", buckets.release());
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root.SetInteger("pid", GetCurrentProcId());
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  serializer.Serialize(root);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void HistogramBase::WriteAsciiBucketGraph(double current_size,
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          double max_size,
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          std::string* output) const {
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int k_line_length = 72;  // Maximal horizontal width of graph.
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int x_count = static_cast<int>(k_line_length * (current_size / max_size)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 + 0.5);
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int x_remainder = k_line_length - x_count;
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (0 < x_count--)
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    output->append("-");
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  output->append("O");
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (0 < x_remainder--)
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    output->append(" ");
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string HistogramBase::GetSimpleAsciiBucketRange(
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Sample sample) const {
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string result;
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (kHexRangePrintingFlag & flags())
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StringAppendF(&result, "%#x", sample);
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StringAppendF(&result, "%d", sample);
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return result;
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void HistogramBase::WriteAsciiBucketValue(Count current,
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          double scaled_sum,
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          std::string* output) const {
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StringAppendF(output, " (%d = %3.1f%%)", current, current/scaled_sum);
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
162