Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleMetrics.cxx
Go to the documentation of this file.
1/// \file RNTupleMetrics.cxx
2/// \author Jakob Blomer <jblomer@cern.ch>
3/// \date 2019-08-27
4/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
5/// is welcome!
6
7/*************************************************************************
8 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
9 * All rights reserved. *
10 * *
11 * For the licensing terms see $ROOTSYS/LICENSE. *
12 * For the list of contributors see $ROOTSYS/README/CREDITS. *
13 *************************************************************************/
14
16
17#include <ROOT/RError.hxx>
18#include <ROOT/RField.hxx>
19#include <ROOT/RLogger.hxx>
20#include <ROOT/RNTupleModel.hxx>
21#include <ROOT/RNTupleUtils.hxx>
23
24#include <TFile.h>
25#include <TFileMerger.h>
26#include <TMemFile.h>
27#include <TSystem.h>
28
29#include <cstdint>
30#include <mutex>
31#include <ostream>
32#include <vector>
33
34namespace {
35
36std::mutex &GetMetricsExportMutex()
37{
38 static std::mutex mutex;
39 return mutex;
40}
41
42thread_local bool gSuppressMetricsExport = false;
43
44struct RSuppressMetricsRaii {
45 RSuppressMetricsRaii() { gSuppressMetricsExport = true; }
46 RSuppressMetricsRaii(const RSuppressMetricsRaii &other) = delete;
47 RSuppressMetricsRaii &operator=(const RSuppressMetricsRaii &other) = delete;
49};
50
51} // anonymous namespace
52
56
58{
59 return fName + kFieldSeperator + fUnit + kFieldSeperator + fDescription + kFieldSeperator + GetValueAsString();
60}
61
63{
64 return GetLocalCounter(name) != nullptr;
65}
66
69{
70 for (const auto &c : fCounters) {
71 if (c->GetName() == name)
72 return c.get();
73 }
74 return nullptr;
75}
76
79{
80 std::string prefix = fName + ".";
81 if (name.compare(0, prefix.length(), std::string_view(prefix)) != 0)
82 return nullptr;
83
84 auto innerName = name.substr(prefix.length());
85 if (auto counter = GetLocalCounter(innerName))
86 return counter;
87
88 for (auto m : fObservedMetrics) {
89 auto counter = m->GetCounter(innerName);
90 if (counter != nullptr)
91 return counter;
92 }
93
94 return nullptr;
95}
96
97void ROOT::Experimental::Detail::RNTupleMetrics::Print(std::ostream &output, const std::string &prefix) const
98{
99 if (!fIsEnabled) {
100 output << fName << " metrics disabled!\n";
101 return;
102 }
103
104 for (const auto &c : fCounters) {
105 output << prefix << fName << kNamespaceSeperator << c->ToString() << '\n';
106 }
107 for (const auto c : fObservedMetrics) {
108 c->Print(output, prefix + fName + ".");
109 }
110}
111
113{
114 for (auto &c: fCounters)
115 c->Enable();
116 fIsEnabled = true;
117 for (auto m: fObservedMetrics)
118 m->Enable();
119}
120
125
127{
129 return {};
130
131 if (const char *env = gSystem->Getenv("ROOT_EXPERIMENTAL_EXPORT_RNTUPLE_METRICS"); env && *env)
132 return env;
133
134 return {};
135}
136
138{
139 if (!fIsEnabled || fExportPath.empty())
140 return;
141
142 try {
143 ExportToRootFile();
144 } catch (const RException &e) {
145 R__LOG_ERROR(ROOT::Internal::NTupleLog()) << "cannot export metrics: " << e.what();
146 }
147}
148
150 std::vector<std::pair<std::string, const RNTuplePerfCounter *>> &counters, const std::string &prefix) const
151{
152 constexpr char kSeparator = '_';
153
154 R__ASSERT(!fName.empty());
155
156 std::string qualifiedName = prefix;
157 if (!qualifiedName.empty())
158 qualifiedName += kSeparator;
159 qualifiedName += fName;
160
161 for (const auto &counter : fCounters)
162 counters.emplace_back(qualifiedName + kSeparator + counter->GetName(), counter.get());
163
164 for (const auto *observed : fObservedMetrics)
165 observed->CollectCounters(counters, qualifiedName);
166}
167
169{
170 R__ASSERT(!fExportPath.empty());
171 R__ASSERT(!fNTupleName.empty());
172
173 std::vector<std::pair<std::string, const RNTuplePerfCounter *>> counters;
174 CollectCounters(counters);
175 R__ASSERT(!counters.empty());
176
177 // Avoid inifinite recursion (an RNTupleWriter is created to print the metrics)
178 RSuppressMetricsRaii suppressGuard;
179
180 auto model = ROOT::RNTupleModel::Create();
181 for (const auto &[fullyQualifiedName, counter] : counters) {
182 R__ASSERT(counter);
183 if (const auto *calc = dynamic_cast<const RNTupleCalcPerf *>(counter)) {
184 *model->MakeField<double>(fullyQualifiedName) = calc->GetValue();
185 } else {
186 *model->MakeField<std::int64_t>(fullyQualifiedName) = counter->GetValueAsInt();
187 }
188 }
189
190 TMemFile memoryFile(fNTupleName.c_str(), "RECREATE");
191 {
192 auto writer = ROOT::RNTupleWriter::Append(std::move(model), fNTupleName, memoryFile);
193 writer->Fill();
194 writer->CommitDataset();
195 }
196
197 std::lock_guard<std::mutex> lock(GetMetricsExportMutex());
198
200 merger.SetMergeOptions(std::string_view("rntuple.MergingMode=Union"));
201
202 if (!merger.OutputFile(fExportPath.c_str(), "UPDATE")) {
203 R__LOG_ERROR(ROOT::Internal::NTupleLog()) << "cannot open metrics export file '" << fExportPath << "'";
204 return;
205 }
206
207 if (!merger.AddFile(&memoryFile) || !merger.PartialMerge(TFileMerger::kAll | TFileMerger::kIncremental)) {
209 << "cannot merge metrics for '" << fNTupleName << "' into '" << fExportPath << "'";
210 }
211}
#define R__LOG_ERROR(...)
Definition RLogger.hxx:356
#define c(i)
Definition RSha256.hxx:101
#define e(i)
Definition RSha256.hxx:103
ReduceNLLOutput counters
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:130
char name[80]
Definition TGX11.cxx:142
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
A metric element that computes its floating point value from other counters.
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.
void ObserveMetrics(RNTupleMetrics &observee)
const RNTuplePerfCounter * GetLocalCounter(std::string_view name) const
Searches counters registered in this object only. Returns nullptr if name is not found.
void CollectCounters(std::vector< std::pair< std::string, const RNTuplePerfCounter * > > &counters, const std::string &prefix="") const
Retrieves each counter of the observed metrics down to the class instances which own the counters and...
bool Contains(const std::string &name) const
void Print(std::ostream &output, const std::string &prefix="") const
A performance counter with a name and a unit, which can be activated on demand.
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
static std::unique_ptr< RNTupleModel > Create()
static std::unique_ptr< RNTupleWriter > Append(std::unique_ptr< ROOT::RNTupleModel > model, std::string_view ntupleName, TDirectory &fileOrDirectory, const ROOT::RNTupleWriteOptions &options=ROOT::RNTupleWriteOptions())
Creates an RNTupleWriter that writes into an existing TFile or TDirectory, without overwriting its co...
This class provides file copy and merging services.
Definition TFileMerger.h:30
@ kAll
Merge all type of objects (default)
Definition TFileMerger.h:87
@ kIncremental
Merge the input file with the content of the output file (if already existing).
Definition TFileMerger.h:82
A TMemFile is like a normal TFile except that it reads and writes only from memory.
Definition TMemFile.h:27
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1680
ROOT::RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
TMarker m
Definition textangle.C:8