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
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 ROOT_RNTupleMetrics
17#define ROOT_RNTupleMetrics
18
19#include <ROOT/RConfig.hxx>
20#include <string_view>
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 <type_traits>
34#include <vector>
35#include <utility>
36
37namespace ROOT {
38namespace Experimental {
39namespace Detail {
40
41class RNTupleMetrics;
42
43// clang-format off
44/**
45\class ROOT::Experimental::Detail::RNTuplePerfCounter
46\ingroup NTuple
47\brief A performance counter with a name and a unit, which can be activated on demand
48
49Derived classes decide on the counter type and implement printing of the value.
50*/
51// clang-format on
53private:
54 /// Symbol to split name, unit, description, and value when printing
55 static constexpr char kFieldSeperator = '|';
56
57 std::string fName;
58 std::string fUnit;
59 std::string fDescription;
60 bool fIsEnabled = false;
61
62public:
63 RNTuplePerfCounter(const std::string &name, const std::string &unit, const std::string &desc)
64 : fName(name), fUnit(unit), fDescription(desc) {}
65 virtual ~RNTuplePerfCounter();
66 void Enable() { fIsEnabled = true; }
67 bool IsEnabled() const { return fIsEnabled; }
68 const std::string &GetName() const { return fName; }
69 const std::string &GetDescription() const { return fDescription; }
70 const std::string &GetUnit() const { return fUnit; }
71
72 virtual std::int64_t GetValueAsInt() const = 0;
73 virtual std::string GetValueAsString() const = 0;
74 std::string ToString() const;
75};
76
77
78// clang-format off
79/**
80\class ROOT::Experimental::Detail::RNTuplePlainCounter
81\ingroup NTuple
82\brief A non thread-safe integral performance counter
83*/
84// clang-format on
86private:
87 std::int64_t fCounter = 0;
88
89public:
90 RNTuplePlainCounter(const std::string &name, const std::string &unit, const std::string &desc)
91 : RNTuplePerfCounter(name, unit, desc)
92 {
93 }
94
97 R__ALWAYS_INLINE void Add(int64_t delta) { fCounter += delta; }
98 R__ALWAYS_INLINE int64_t GetValue() const { return fCounter; }
99 R__ALWAYS_INLINE void SetValue(int64_t val) { fCounter = val; }
100 std::int64_t GetValueAsInt() const override { return fCounter; }
101 std::string GetValueAsString() const override { return std::to_string(fCounter); }
102};
103
104
105// clang-format off
106/**
107\class ROOT::Experimental::Detail::RNTupleAtomicCounter
108\ingroup NTuple
109\brief A thread-safe integral performance counter
110*/
111// clang-format on
113private:
114 std::atomic<std::int64_t> fCounter{0};
115
116public:
117 RNTupleAtomicCounter(const std::string &name, const std::string &unit, const std::string &desc)
118 : RNTuplePerfCounter(name, unit, desc) { }
119
121 void Inc() {
122 if (R__unlikely(IsEnabled()))
123 ++fCounter;
124 }
125
127 void Dec() {
128 if (R__unlikely(IsEnabled()))
129 --fCounter;
130 }
131
133 void Add(int64_t delta) {
134 if (R__unlikely(IsEnabled()))
135 fCounter += delta;
136 }
137
139 int64_t XAdd(int64_t delta) {
140 if (R__unlikely(IsEnabled()))
141 return fCounter.fetch_add(delta);
142 return 0;
143 }
144
146 int64_t GetValue() const {
147 if (R__unlikely(IsEnabled()))
148 return fCounter.load();
149 return 0;
150 }
151
153 void SetValue(int64_t val) {
154 if (R__unlikely(IsEnabled()))
155 fCounter.store(val);
156 }
157
158 std::int64_t GetValueAsInt() const override { return GetValue(); }
159 std::string GetValueAsString() const override { return std::to_string(GetValue()); }
160};
161
162
163// clang-format off
164/**
165\class ROOT::Experimental::Detail::RNTupleCalcPerf
166\ingroup NTuple
167\brief A metric element that computes its floating point value from other counters.
168*/
169// clang-format on
171public:
172 using MetricFunc_t = std::function<std::pair<bool, double>(const RNTupleMetrics &)>;
173
174private:
177
178public:
179 RNTupleCalcPerf(const std::string &name, const std::string &unit, const std::string &desc,
181 : RNTuplePerfCounter(name, unit, desc), fMetrics(metrics), fFunc(std::move(func))
182 {
183 }
184
185 double GetValue() const {
186 auto ret = fFunc(fMetrics);
187 if (ret.first)
188 return ret.second;
189 return std::numeric_limits<double>::quiet_NaN();
190 }
191
192 std::int64_t GetValueAsInt() const override {
193 return static_cast<std::int64_t>(GetValue());
194 }
195
196 std::string GetValueAsString() const override {
197 return std::to_string(GetValue());
198 }
199};
200
201// clang-format off
202/**
203\class ROOT::Experimental::Detail::RNTupleTickCounter
204\ingroup NTuple
205\brief A counter for CPU ticks.
206
207Whether this counter is thread-safe depends on BaseCounterT, see RNTuplePlainCounter and RNTupleAtomicCounter.
208
209When printing, the value is converted from ticks to nanoseconds.
210*/
211// clang-format on
212template <typename BaseCounterT>
214public:
215 RNTupleTickCounter(const std::string &name, const std::string &unit, const std::string &desc)
216 : BaseCounterT(name, unit, desc)
217 {
218 R__ASSERT(unit == "ns");
219 }
220
221 std::int64_t GetValueAsInt() const final {
222 auto ticks = BaseCounterT::GetValue();
223 return std::uint64_t((double(ticks) / double(CLOCKS_PER_SEC)) * (1000. * 1000. * 1000.));
224 }
225
227 return std::to_string(GetValueAsInt());
228 }
229};
230
231
232// clang-format off
233/**
234\class ROOT::Experimental::Detail::RNTupleTimer
235\ingroup NTuple
236\brief Record wall time and CPU time between construction and destruction
237
238Uses RAII as a stop watch. Only the wall time counter is used to determine whether the timer is active.
239*/
240// clang-format on
241template <typename WallTimeT, typename CpuTimeT>
243private:
244 using Clock_t = std::chrono::steady_clock;
245
248 /// Wall clock time
249 Clock_t::time_point fStartTime;
250 /// CPU time
251 clock_t fStartTicks = 0;
252
253public:
256 {
257 if (!fCtrWallTime.IsEnabled())
258 return;
259 fStartTime = Clock_t::now();
260 fStartTicks = clock();
261 }
262
264 if (!fCtrWallTime.IsEnabled())
265 return;
266 auto wallTimeNs = std::chrono::duration_cast<std::chrono::nanoseconds>(Clock_t::now() - fStartTime);
267 fCtrWallTime.Add(wallTimeNs.count());
269 }
270
273};
274
277
278
279// clang-format off
280/**
281\class ROOT::Experimental::Detail::RNTupleMetrics
282\ingroup NTuple
283\brief A collection of Counter objects with a name, a unit, and a description.
284
285The class owns the counters.
286*/
287// clang-format on
289private:
290 /// Symbol to split metrics name from counter / sub metrics name
291 static constexpr char kNamespaceSeperator = '.';
292
293 std::vector<std::unique_ptr<RNTuplePerfCounter>> fCounters;
294 std::vector<RNTupleMetrics *> fObservedMetrics;
295 std::string fName;
296 bool fIsEnabled = false;
297
298 bool Contains(const std::string &name) const;
299
300public:
301 explicit RNTupleMetrics(const std::string &name) : fName(name) {}
306 ~RNTupleMetrics() = default;
307
308 // TODO(jblomer): return a reference
309 template <typename CounterPtrT, class... Args>
310 CounterPtrT MakeCounter(const std::string &name, Args&&... args)
311 {
313 auto counter = std::make_unique<std::remove_pointer_t<CounterPtrT>>(name, std::forward<Args>(args)...);
314 auto ptrCounter = counter.get();
315 fCounters.emplace_back(std::move(counter));
316 return ptrCounter;
317 }
318
319 /// Searches counters registered in this object only. Returns nullptr if `name` is not found.
320 const RNTuplePerfCounter *GetLocalCounter(std::string_view name) const;
321 /// Searches this object and all the observed sub metrics. `name` must start with the prefix used
322 /// by this RNTupleMetrics instance. Returns nullptr if `name` is not found.
323 const RNTuplePerfCounter *GetCounter(std::string_view name) const;
324
326
327 void Print(std::ostream &output, const std::string &prefix = "") const;
328 void Enable();
329 bool IsEnabled() const { return fIsEnabled; }
330};
331
332} // namespace Detail
333} // namespace Experimental
334} // namespace ROOT
335
336#endif
#define R__ALWAYS_INLINE
Definition RConfig.hxx:560
#define R__unlikely(expr)
Definition RConfig.hxx:594
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
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.
RNTupleMetrics & operator=(const RNTupleMetrics &other)=delete
void ObserveMetrics(RNTupleMetrics &observee)
RNTupleMetrics & operator=(RNTupleMetrics &&other)=default
const RNTuplePerfCounter * GetLocalCounter(std::string_view name) const
Searches counters registered in this object only. Returns nullptr if name is not found.
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)
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()