Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleMetrics.hxx
Go to the documentation of this file.
1/// \file ROOT/RNTupleMetrics.hxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2019-08-27
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#ifndef ROOT7_RNTupleMetrics
17#define ROOT7_RNTupleMetrics
18
19#include <ROOT/RConfig.hxx>
20#include <ROOT/RStringView.hxx>
21
22#include <TError.h>
23
24#include <atomic>
25#include <chrono>
26#include <cstdint>
27#include <ctime> // for CPU time measurement with clock()
28#include <functional>
29#include <limits>
30#include <memory>
31#include <ostream>
32#include <string>
33#include <vector>
34#include <utility>
35
36namespace ROOT {
37namespace Experimental {
38namespace Detail {
39
40class RNTupleMetrics;
41
42// clang-format off
43/**
44\class ROOT::Experimental::Detail::RNTuplePerfCounter
45\ingroup NTuple
46\brief A performance counter with a name and a unit, which can be activated on demand
47
48Derived classes decide on the counter type and implement printing of the value.
49*/
50// clang-format on
52private:
53 /// Symbol to split name, unit, description, and value when printing
54 static constexpr char kFieldSeperator = '|';
55
56 std::string fName;
57 std::string fUnit;
58 std::string fDescription;
59 bool fIsEnabled = false;
60
61public:
62 RNTuplePerfCounter(const std::string &name, const std::string &unit, const std::string &desc)
63 : fName(name), fUnit(unit), fDescription(desc) {}
64 virtual ~RNTuplePerfCounter();
65 void Enable() { fIsEnabled = true; }
66 bool IsEnabled() const { return fIsEnabled; }
67 std::string GetName() const { return fName; }
68 std::string GetDescription() const { return fDescription; }
69 std::string GetUnit() const { return fUnit; }
70
71 virtual std::int64_t GetValueAsInt() const = 0;
72 virtual std::string GetValueAsString() const = 0;
73 std::string ToString() const;
74};
75
76
77// clang-format off
78/**
79\class ROOT::Experimental::Detail::RNTuplePlainCounter
80\ingroup NTuple
81\brief A non thread-safe integral performance counter
82*/
83// clang-format on
85private:
86 std::int64_t fCounter = 0;
87
88public:
89 RNTuplePlainCounter(const std::string &name, const std::string &unit, const std::string &desc)
90 : RNTuplePerfCounter(name, unit, desc)
91 {
92 }
93
96 R__ALWAYS_INLINE void Add(int64_t delta) { fCounter += delta; }
97 R__ALWAYS_INLINE int64_t GetValue() const { return fCounter; }
98 R__ALWAYS_INLINE void SetValue(int64_t val) { fCounter = val; }
99 std::int64_t GetValueAsInt() const override { return fCounter; }
100 std::string GetValueAsString() const override { return std::to_string(fCounter); }
101};
102
103
104// clang-format off
105/**
106\class ROOT::Experimental::Detail::RNTupleAtomicCounter
107\ingroup NTuple
108\brief A thread-safe integral performance counter
109*/
110// clang-format on
112private:
113 std::atomic<std::int64_t> fCounter{0};
114
115public:
116 RNTupleAtomicCounter(const std::string &name, const std::string &unit, const std::string &desc)
117 : RNTuplePerfCounter(name, unit, desc) { }
118
120 void Inc() {
121 if (R__unlikely(IsEnabled()))
122 ++fCounter;
123 }
124
126 void Dec() {
127 if (R__unlikely(IsEnabled()))
128 --fCounter;
129 }
130
132 void Add(int64_t delta) {
133 if (R__unlikely(IsEnabled()))
134 fCounter += delta;
135 }
136
138 int64_t XAdd(int64_t delta) {
139 if (R__unlikely(IsEnabled()))
140 return fCounter.fetch_add(delta);
141 return 0;
142 }
143
145 int64_t GetValue() const {
146 if (R__unlikely(IsEnabled()))
147 return fCounter.load();
148 return 0;
149 }
150
152 void SetValue(int64_t val) {
153 if (R__unlikely(IsEnabled()))
154 fCounter.store(val);
155 }
156
157 std::int64_t GetValueAsInt() const override { return GetValue(); }
158 std::string GetValueAsString() const override { return std::to_string(GetValue()); }
159};
160
161
162// clang-format off
163/**
164\class ROOT::Experimental::Detail::RNTupleCalcPerf
165\ingroup NTuple
166\brief A metric element that computes its floating point value from other counters.
167*/
168// clang-format on
170public:
171 using MetricFunc_t = std::function<std::pair<bool, double>(const RNTupleMetrics &)>;
172
173private:
176
177public:
178 RNTupleCalcPerf(const std::string &name, const std::string &unit, const std::string &desc,
179 RNTupleMetrics &metrics, MetricFunc_t &&func)
180 : RNTuplePerfCounter(name, unit, desc), fMetrics(metrics), fFunc(std::move(func))
181 {
182 }
183
184 double GetValue() const {
185 auto ret = fFunc(fMetrics);
186 if (ret.first)
187 return ret.second;
188 return std::numeric_limits<double>::quiet_NaN();
189 }
190
191 std::int64_t GetValueAsInt() const override {
192 return static_cast<std::int64_t>(GetValue());
193 }
194
195 std::string GetValueAsString() const override {
196 return std::to_string(GetValue());
197 }
198};
199
200// clang-format off
201/**
202\class ROOT::Experimental::Detail::RNTupleTickCounter
203\ingroup NTuple
204\brief An either thread-safe or non thread safe counter for CPU ticks
205
206On print, the value is converted from ticks to ns.
207*/
208// clang-format on
209template <typename BaseCounterT>
211public:
212 RNTupleTickCounter(const std::string &name, const std::string &unit, const std::string &desc)
213 : BaseCounterT(name, unit, desc)
214 {
215 R__ASSERT(unit == "ns");
216 }
217
218 std::int64_t GetValueAsInt() const final {
219 auto ticks = BaseCounterT::GetValue();
220 return std::uint64_t((double(ticks) / double(CLOCKS_PER_SEC)) * (1000. * 1000. * 1000.));
221 }
222
223 std::string GetValueAsString() const final {
224 return std::to_string(GetValueAsInt());
225 }
226};
227
228
229// clang-format off
230/**
231\class ROOT::Experimental::Detail::RNTupleTimer
232\ingroup NTuple
233\brief Record wall time and CPU time between construction and destruction
234
235Uses RAII as a stop watch. Only the wall time counter is used to determine whether the timer is active.
236*/
237// clang-format on
238template <typename WallTimeT, typename CpuTimeT>
240private:
241 using Clock_t = std::chrono::steady_clock;
242
243 WallTimeT &fCtrWallTime;
244 CpuTimeT &fCtrCpuTicks;
245 /// Wall clock time
246 Clock_t::time_point fStartTime;
247 /// CPU time
248 clock_t fStartTicks = 0;
249
250public:
251 RNTupleTimer(WallTimeT &ctrWallTime, CpuTimeT &ctrCpuTicks)
252 : fCtrWallTime(ctrWallTime), fCtrCpuTicks(ctrCpuTicks)
253 {
254 if (!fCtrWallTime.IsEnabled())
255 return;
256 fStartTime = Clock_t::now();
257 fStartTicks = clock();
258 }
259
261 if (!fCtrWallTime.IsEnabled())
262 return;
263 auto wallTimeNs = std::chrono::duration_cast<std::chrono::nanoseconds>(Clock_t::now() - fStartTime);
264 fCtrWallTime.Add(wallTimeNs.count());
265 fCtrCpuTicks.Add(clock() - fStartTicks);
266 }
267
268 RNTupleTimer(const RNTupleTimer &other) = delete;
269 RNTupleTimer &operator =(const RNTupleTimer &other) = delete;
270};
271
274
275
276// clang-format off
277/**
278\class ROOT::Experimental::Detail::RNTupleMetrics
279\ingroup NTuple
280\brief A collection of Counter objects with a name, a unit, and a description.
281
282The class owns the counters; on registration of a new
283*/
284// clang-format on
286private:
287 /// Symbol to split metrics name from counter / sub metrics name
288 static constexpr char kNamespaceSeperator = '.';
289
290 std::vector<std::unique_ptr<RNTuplePerfCounter>> fCounters;
291 std::vector<RNTupleMetrics *> fObservedMetrics;
292 std::string fName;
293 bool fIsEnabled = false;
294
295 bool Contains(const std::string &name) const;
296
297public:
298 explicit RNTupleMetrics(const std::string &name) : fName(name) {}
299 RNTupleMetrics(const RNTupleMetrics &other) = delete;
300 RNTupleMetrics & operator=(const RNTupleMetrics &other) = delete;
301 RNTupleMetrics(RNTupleMetrics &&other) = default;
303 ~RNTupleMetrics() = default;
304
305 // TODO(jblomer): return a reference
306 template <typename CounterPtrT, class... Args>
307 CounterPtrT MakeCounter(const std::string &name, Args&&... args)
308 {
310 auto counter = std::make_unique<std::remove_pointer_t<CounterPtrT>>(name, std::forward<Args>(args)...);
311 auto ptrCounter = counter.get();
312 fCounters.emplace_back(std::move(counter));
313 return ptrCounter;
314 }
315
316 /// Searches this object and all the observed sub metrics. Returns nullptr if name is not found.
317 const RNTuplePerfCounter *GetCounter(std::string_view name) const;
318
319 void ObserveMetrics(RNTupleMetrics &observee);
320
321 void Print(std::ostream &output, const std::string &prefix = "") const;
322 void Enable();
323 bool IsEnabled() const { return fIsEnabled; }
324};
325
326} // namespace Detail
327} // namespace Experimental
328} // namespace ROOT
329
330#endif
#define R__ALWAYS_INLINE
Definition RConfig.hxx:574
#define R__unlikely(expr)
Definition RConfig.hxx:608
#define R__ASSERT(e)
Definition TError.h:120
char name[80]
Definition TGX11.cxx:110
A thread-safe integral performance counter.
R__ALWAYS_INLINE void SetValue(int64_t val)
R__ALWAYS_INLINE int64_t XAdd(int64_t delta)
RNTupleAtomicCounter(const std::string &name, const std::string &unit, const std::string &desc)
R__ALWAYS_INLINE void Add(int64_t delta)
A metric element that computes its floating point value from other counters.
std::int64_t GetValueAsInt() const override
std::function< std::pair< bool, double >(const RNTupleMetrics &)> MetricFunc_t
std::string GetValueAsString() const override
RNTupleCalcPerf(const std::string &name, const std::string &unit, const std::string &desc, RNTupleMetrics &metrics, MetricFunc_t &&func)
A collection of Counter objects with a name, a unit, and a description.
const RNTuplePerfCounter * GetCounter(std::string_view name) const
Searches this object and all the observed sub metrics. Returns nullptr if name is not found.
RNTupleMetrics & operator=(const RNTupleMetrics &other)=delete
void ObserveMetrics(RNTupleMetrics &observee)
RNTupleMetrics & operator=(RNTupleMetrics &&other)=default
std::vector< std::unique_ptr< RNTuplePerfCounter > > fCounters
RNTupleMetrics(RNTupleMetrics &&other)=default
CounterPtrT MakeCounter(const std::string &name, Args &&... args)
bool Contains(const std::string &name) const
std::vector< RNTupleMetrics * > fObservedMetrics
void Print(std::ostream &output, const std::string &prefix="") const
RNTupleMetrics(const RNTupleMetrics &other)=delete
static constexpr char kNamespaceSeperator
Symbol to split metrics name from counter / sub metrics name.
A performance counter with a name and a unit, which can be activated on demand.
virtual std::string GetValueAsString() const =0
static constexpr char kFieldSeperator
Symbol to split name, unit, description, and value when printing.
virtual std::int64_t GetValueAsInt() const =0
RNTuplePerfCounter(const std::string &name, const std::string &unit, const std::string &desc)
A non thread-safe integral performance counter.
RNTuplePlainCounter(const std::string &name, const std::string &unit, const std::string &desc)
R__ALWAYS_INLINE int64_t GetValue() const
R__ALWAYS_INLINE void SetValue(int64_t val)
R__ALWAYS_INLINE void Add(int64_t delta)
An either thread-safe or non thread safe counter for CPU ticks.
RNTupleTickCounter(const std::string &name, const std::string &unit, const std::string &desc)
Record wall time and CPU time between construction and destruction.
Clock_t::time_point fStartTime
Wall clock time.
RNTupleTimer(WallTimeT &ctrWallTime, CpuTimeT &ctrCpuTicks)
RNTupleTimer(const RNTupleTimer &other)=delete
RNTupleTimer & operator=(const RNTupleTimer &other)=delete
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
static void output(int code)
Definition gifencode.c:226