summaryrefslogtreecommitdiff
path: root/chromium/base/metrics/histogram_samples.h
blob: 93f6d21c8aabd34eed61dd9c20d2e030cabada8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// 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.

#ifndef BASE_METRICS_HISTOGRAM_SAMPLES_H_
#define BASE_METRICS_HISTOGRAM_SAMPLES_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>

#include "base/atomicops.h"
#include "base/macros.h"
#include "base/metrics/histogram_base.h"

namespace base {

class Pickle;
class PickleIterator;
class SampleCountIterator;

// HistogramSamples is a container storing all samples of a histogram. All
// elements must be of a fixed width to ensure 32/64-bit interoperability.
// If this structure changes, bump the version number for kTypeIdHistogram
// in persistent_histogram_allocator.cc.
class BASE_EXPORT HistogramSamples {
 public:
  struct Metadata {
    // Expected size for 32/64-bit check.
    static constexpr size_t kExpectedInstanceSize = 24;

    // Initialized when the sample-set is first created with a value provided
    // by the caller. It is generally used to identify the sample-set across
    // threads and processes, though not necessarily uniquely as it is possible
    // to have multiple sample-sets representing subsets of the data.
    uint64_t id;

    // The sum of all the entries, effectivly the sum(sample * count) for
    // all samples. Despite being atomic, no guarantees are made on the
    // accuracy of this value; there may be races during histogram
    // accumulation and snapshotting that we choose to accept. It should
    // be treated as approximate.
#ifdef ARCH_CPU_64_BITS
    subtle::Atomic64 sum;
#else
    // 32-bit systems don't have atomic 64-bit operations. Use a basic type
    // and don't worry about "shearing".
    int64_t sum;
#endif

    // A "redundant" count helps identify memory corruption. It redundantly
    // stores the total number of samples accumulated in the histogram. We
    // can compare this count to the sum of the counts (TotalCount() function),
    // and detect problems. Note, depending on the implementation of different
    // histogram types, there might be races during histogram accumulation
    // and snapshotting that we choose to accept. In this case, the tallies
    // might mismatch even when no memory corruption has happened.
    HistogramBase::AtomicCount redundant_count;

    // 4 bytes of padding to explicitly extend this structure to a multiple of
    // 64-bits. This is required to ensure the structure is the same size on
    // both 32-bit and 64-bit builds.
    char padding[4];
  };

  // Because sturctures held in persistent memory must be POD, there can be no
  // default constructor to clear the fields. This derived class exists just
  // to clear them when being allocated on the heap.
  struct LocalMetadata : Metadata {
    LocalMetadata() {
      id = 0;
      sum = 0;
      redundant_count = 0;
    }
  };

  explicit HistogramSamples(uint64_t id);
  HistogramSamples(uint64_t id, Metadata* meta);
  virtual ~HistogramSamples();

  virtual void Accumulate(HistogramBase::Sample value,
                          HistogramBase::Count count) = 0;
  virtual HistogramBase::Count GetCount(HistogramBase::Sample value) const = 0;
  virtual HistogramBase::Count TotalCount() const = 0;

  virtual void Add(const HistogramSamples& other);

  // Add from serialized samples.
  virtual bool AddFromPickle(PickleIterator* iter);

  virtual void Subtract(const HistogramSamples& other);

  virtual std::unique_ptr<SampleCountIterator> Iterator() const = 0;
  virtual bool Serialize(Pickle* pickle) const;

  // Accessor fuctions.
  uint64_t id() const { return meta_->id; }
  int64_t sum() const {
#ifdef ARCH_CPU_64_BITS
    return subtle::NoBarrier_Load(&meta_->sum);
#else
    return meta_->sum;
#endif
  }
  HistogramBase::Count redundant_count() const {
    return subtle::NoBarrier_Load(&meta_->redundant_count);
  }

 protected:
  // Based on |op| type, add or subtract sample counts data from the iterator.
  enum Operator { ADD, SUBTRACT };
  virtual bool AddSubtractImpl(SampleCountIterator* iter, Operator op) = 0;

  void IncreaseSum(int64_t diff);
  void IncreaseRedundantCount(HistogramBase::Count diff);

 private:
  // In order to support histograms shared through an external memory segment,
  // meta values may be the local storage or external storage depending on the
  // wishes of the derived class.
  LocalMetadata local_meta_;
  Metadata* meta_;

  DISALLOW_COPY_AND_ASSIGN(HistogramSamples);
};

class BASE_EXPORT SampleCountIterator {
 public:
  virtual ~SampleCountIterator();

  virtual bool Done() const = 0;
  virtual void Next() = 0;

  // Get the sample and count at current position.
  // |min| |max| and |count| can be NULL if the value is not of interest.
  // Requires: !Done();
  virtual void Get(HistogramBase::Sample* min,
                   HistogramBase::Sample* max,
                   HistogramBase::Count* count) const = 0;

  // Get the index of current histogram bucket.
  // For histograms that don't use predefined buckets, it returns false.
  // Requires: !Done();
  virtual bool GetBucketIndex(size_t* index) const;
};

}  // namespace base

#endif  // BASE_METRICS_HISTOGRAM_SAMPLES_H_