1 |
|
|
/** |
2 |
|
|
* This file is part of the CernVM File System. |
3 |
|
|
*/ |
4 |
|
|
|
5 |
|
|
#ifndef CVMFS_STATISTICS_H_ |
6 |
|
|
#define CVMFS_STATISTICS_H_ |
7 |
|
|
|
8 |
|
|
#include <pthread.h> |
9 |
|
|
#include <stdint.h> |
10 |
|
|
|
11 |
|
|
#include <map> |
12 |
|
|
#include <string> |
13 |
|
|
#include <vector> |
14 |
|
|
|
15 |
|
|
#include "atomic.h" |
16 |
|
|
|
17 |
|
|
#ifdef CVMFS_NAMESPACE_GUARD |
18 |
|
|
namespace CVMFS_NAMESPACE_GUARD { |
19 |
|
|
#endif |
20 |
|
|
|
21 |
|
|
|
22 |
|
|
namespace perf { |
23 |
|
|
|
24 |
|
|
/** |
25 |
|
|
* A wrapper around an atomic 64bit signed integer. |
26 |
|
|
*/ |
27 |
|
|
class Counter { |
28 |
|
|
public: |
29 |
|
10520 |
Counter() { atomic_init64(&counter_); } |
30 |
|
97833 |
void Inc() { atomic_inc64(&counter_); } |
31 |
|
66 |
void Dec() { atomic_dec64(&counter_); } |
32 |
|
50 |
int64_t Get() { return atomic_read64(&counter_); } |
33 |
|
476 |
void Set(const int64_t val) { atomic_write64(&counter_, val); } |
34 |
|
1453 |
int64_t Xadd(const int64_t delta) { return atomic_xadd64(&counter_, delta); } |
35 |
|
|
|
36 |
|
|
std::string Print(); |
37 |
|
|
std::string PrintK(); |
38 |
|
|
std::string PrintKi(); |
39 |
|
|
std::string PrintM(); |
40 |
|
|
std::string PrintMi(); |
41 |
|
|
std::string PrintRatio(Counter divider); |
42 |
|
|
std::string ToString(); |
43 |
|
|
|
44 |
|
|
private: |
45 |
|
|
atomic_int64 counter_; |
46 |
|
|
}; |
47 |
|
|
|
48 |
|
|
// perf::Func(Counter) is more clear to read in the code |
49 |
|
64 |
inline void Dec(class Counter *counter) { counter->Dec(); } |
50 |
|
97832 |
inline void Inc(class Counter *counter) { counter->Inc(); } |
51 |
|
1452 |
inline int64_t Xadd(class Counter *counter, const int64_t delta) { |
52 |
|
1452 |
return counter->Xadd(delta); |
53 |
|
|
} |
54 |
|
|
|
55 |
|
|
|
56 |
|
|
/** |
57 |
|
|
* A collection of Counter objects with a name and a description. Counters in |
58 |
|
|
* a Statistics class have a name and a description. Thread-safe. |
59 |
|
|
*/ |
60 |
|
|
class Statistics { |
61 |
|
|
public: |
62 |
|
|
enum PrintOptions { |
63 |
|
|
kPrintSimple = 0, |
64 |
|
|
kPrintHeader |
65 |
|
|
}; |
66 |
|
|
|
67 |
|
|
Statistics(); |
68 |
|
|
~Statistics(); |
69 |
|
|
Statistics *Fork(); |
70 |
|
|
Counter *Register(const std::string &name, const std::string &desc); |
71 |
|
|
Counter *Lookup(const std::string &name) const; |
72 |
|
|
std::string LookupDesc(const std::string &name); |
73 |
|
|
std::string PrintList(const PrintOptions print_options); |
74 |
|
|
|
75 |
|
|
private: |
76 |
|
|
Statistics(const Statistics &other); |
77 |
|
|
Statistics& operator=(const Statistics &other); |
78 |
|
10440 |
struct CounterInfo { |
79 |
|
10518 |
explicit CounterInfo(const std::string &desc) : desc(desc) { |
80 |
|
10518 |
atomic_init32(&refcnt); |
81 |
|
10518 |
atomic_inc32(&refcnt); |
82 |
|
10518 |
} |
83 |
|
|
atomic_int32 refcnt; |
84 |
|
|
Counter counter; |
85 |
|
|
std::string desc; |
86 |
|
|
}; |
87 |
|
|
std::map<std::string, CounterInfo *> counters_; |
88 |
|
|
mutable pthread_mutex_t *lock_; |
89 |
|
|
}; |
90 |
|
|
|
91 |
|
|
|
92 |
|
|
/** |
93 |
|
|
* Allows multiple instance of the same class to use the same Statistics |
94 |
|
|
* instance. The "name_major" part is used to contruct counter names in the |
95 |
|
|
* form name_major.<provided name> |
96 |
|
|
*/ |
97 |
|
1993 |
class StatisticsTemplate { |
98 |
|
|
public: |
99 |
|
553 |
StatisticsTemplate(const std::string &name_major, Statistics *statistics) |
100 |
|
553 |
: name_major_(name_major), statistics_(statistics) |
101 |
|
553 |
{ } |
102 |
|
198 |
StatisticsTemplate(const std::string &name_sub, |
103 |
|
|
const StatisticsTemplate &statistics) |
104 |
|
|
: name_major_(statistics.name_major_ + "." + name_sub) |
105 |
|
198 |
, statistics_(statistics.statistics_) |
106 |
|
198 |
{ } |
107 |
|
|
|
108 |
|
5861 |
Counter *RegisterTemplated(const std::string &name_minor, |
109 |
|
|
const std::string &desc) |
110 |
|
|
{ |
111 |
|
5861 |
return statistics_->Register(name_major_ + "." + name_minor, desc); |
112 |
|
|
} |
113 |
|
|
|
114 |
|
|
Statistics *statistics() { return statistics_; } |
115 |
|
|
|
116 |
|
|
private: |
117 |
|
|
std::string name_major_; |
118 |
|
|
Statistics *statistics_; |
119 |
|
|
}; |
120 |
|
|
|
121 |
|
|
|
122 |
|
|
/** |
123 |
|
|
* Keeps track of events over time. Can be used to query the number of events |
124 |
|
|
* between now and a point in time in the past. The time range should be |
125 |
|
|
* smaller than capacity_s seconds. Uses a monotonic clock. Not thread-safe. |
126 |
|
|
*/ |
127 |
|
2007 |
class Recorder { |
128 |
|
|
public: |
129 |
|
|
Recorder(uint32_t resolution_s, uint32_t capacity_s); |
130 |
|
|
|
131 |
|
|
void Tick(); |
132 |
|
|
void TickAt(uint64_t timestamp); |
133 |
|
|
uint64_t GetNoTicks(uint32_t retrospect_s) const; |
134 |
|
|
|
135 |
|
13 |
uint32_t capacity_s() const { return capacity_s_; } |
136 |
|
|
uint32_t resolution_s() const { return resolution_s_; } |
137 |
|
|
|
138 |
|
|
private: |
139 |
|
|
/** |
140 |
|
|
* Records number of ticks (events) per unit of resolution. A ring buffer. |
141 |
|
|
* Entries older than capacity_s get overwritten by new events. |
142 |
|
|
*/ |
143 |
|
|
std::vector<uint32_t> bins_; |
144 |
|
|
|
145 |
|
|
/** |
146 |
|
|
* When the most recent tick occured. |
147 |
|
|
*/ |
148 |
|
|
uint64_t last_timestamp_; |
149 |
|
|
|
150 |
|
|
/** |
151 |
|
|
* Time window in seconds that the recorder is supposed to remember. |
152 |
|
|
*/ |
153 |
|
|
uint32_t capacity_s_; |
154 |
|
|
|
155 |
|
|
/** |
156 |
|
|
* Size of the bins for the tick counters. |
157 |
|
|
*/ |
158 |
|
|
uint32_t resolution_s_; |
159 |
|
|
|
160 |
|
|
/** |
161 |
|
|
* Shorthand for bins_.size(), constant during lifetime of the recorder. |
162 |
|
|
*/ |
163 |
|
|
unsigned no_bins_; |
164 |
|
|
}; |
165 |
|
|
|
166 |
|
|
|
167 |
|
|
/** |
168 |
|
|
* Writes to multiple recorders. Recorders with coarsed-grained resolution and |
169 |
|
|
* a large capacity are combined with precise recorders with shorter capacity. |
170 |
|
|
* Preferred recorders should be added first because GetNoTicks will use the |
171 |
|
|
* first recorder with a capacity >= retrospect_s (or the last recorder). |
172 |
|
|
*/ |
173 |
|
222 |
class MultiRecorder { |
174 |
|
|
public: |
175 |
|
|
void Tick(); |
176 |
|
|
void TickAt(uint64_t timestamp); |
177 |
|
|
uint64_t GetNoTicks(uint32_t retrospect_s) const; |
178 |
|
|
|
179 |
|
|
void AddRecorder(uint32_t resolution_s, uint32_t capacity_s); |
180 |
|
|
|
181 |
|
|
private: |
182 |
|
|
std::vector<Recorder> recorders_; |
183 |
|
|
}; |
184 |
|
|
|
185 |
|
|
} // namespace perf |
186 |
|
|
|
187 |
|
|
#ifdef CVMFS_NAMESPACE_GUARD |
188 |
|
|
} // namespace CVMFS_NAMESPACE_GUARD |
189 |
|
|
#endif |
190 |
|
|
|
191 |
|
|
#endif // CVMFS_STATISTICS_H_ |