CMS 3D CMS Logo

FastTimerServiceClient.cc
Go to the documentation of this file.
1 // C++ headers
2 #include <string>
3 #include <cstring>
4 
5 // boost headers
6 #include <boost/regex.hpp>
7 
8 // Root headers
9 #include <TH1F.h>
10 
11 // CMSSW headers
25 
26 struct MEPSet {
29  int nbins;
30  double xmin;
31  double xmax;
32 };
33 
35 public:
36  explicit FastTimerServiceClient(edm::ParameterSet const &);
37  ~FastTimerServiceClient() override;
38 
39  static void fillDescriptions(edm::ConfigurationDescriptions & descriptions);
40  static void fillLumiMePSetDescription(edm::ParameterSetDescription & pset);
41  static void fillPUMePSetDescription(edm::ParameterSetDescription & pset);
42 
43 private:
45 
46  void dqmEndLuminosityBlock(DQMStore::IBooker & booker, DQMStore::IGetter & getter, edm::LuminosityBlock const &, edm::EventSetup const&) override;
47  void dqmEndJob(DQMStore::IBooker & booker, DQMStore::IGetter & getter) override;
48 
49  void fillSummaryPlots( DQMStore::IBooker & booker, DQMStore::IGetter & getter);
50  void fillProcessSummaryPlots( DQMStore::IBooker & booker, DQMStore::IGetter & getter, std::string const & path);
51  void fillPathSummaryPlots( DQMStore::IBooker & booker, DQMStore::IGetter & getter, double events, std::string const & path);
52  void fillPlotsVsLumi(DQMStore::IBooker & booker, DQMStore::IGetter & getter, std::string const & current_path, std::string const & suffix, MEPSet pset);
53 
54  static MEPSet getHistoPSet(const edm::ParameterSet& pset);
55 
59 
63 
64 };
65 
66 
68  m_dqm_path( config.getUntrackedParameter<std::string>( "dqmPath" ) )
69  , doPlotsVsScalLumi_ ( config.getParameter<bool>( "doPlotsVsScalLumi" ) )
70  , doPlotsVsPixelLumi_( config.getParameter<bool>( "doPlotsVsPixelLumi" ) )
71  , doPlotsVsPU_ ( config.getParameter<bool>( "doPlotsVsPU" ) )
72  , scalLumiMEPSet_ ( doPlotsVsScalLumi_ ? getHistoPSet(config.getParameter<edm::ParameterSet>("scalLumiME") ) : MEPSet{} )
73  , pixelLumiMEPSet_( doPlotsVsPixelLumi_ ? getHistoPSet(config.getParameter<edm::ParameterSet>("pixelLumiME")) : MEPSet{} )
74  , puMEPSet_ ( doPlotsVsPU_ ? getHistoPSet(config.getParameter<edm::ParameterSet>("puME") ) : MEPSet{} )
75 {
76 }
77 
79 
80 void
82 {
83  fillSummaryPlots(booker, getter);
84 }
85 
86 void
88 {
89  fillSummaryPlots(booker, getter);
90 }
91 
92 void
94 {
95  if (getter.get(m_dqm_path + "/event time_real")) {
96  // the plots are directly in the configured folder
97  fillProcessSummaryPlots(booker, getter, m_dqm_path);
98  } else {
99  static const boost::regex running_n_processes(".*/Running [0-9]+ processes");
100 
102  std::vector<std::string> subdirs = getter.getSubdirs();
103  for (auto const & subdir: subdirs) {
104 
105  // the plots are in a per-number-of-processes folder
106  if (boost::regex_match(subdir, running_n_processes)) {
107 
108  booker.setCurrentFolder(subdir);
109  if ( getter.get(subdir + "/event time_real") )
110  fillProcessSummaryPlots(booker, getter, subdir);
111 
112  std::vector<std::string> subsubdirs = getter.getSubdirs();
113  for (auto const & subsubdir: subsubdirs) {
114  if ( getter.get(subsubdir + "/event time_real") )
115  fillProcessSummaryPlots(booker, getter, subsubdir);
116  }
117 
118  }
119  } // loop on subdirs
120  }
121 }
122 
123 
124 
125 void
127 
128  MonitorElement * me = getter.get(current_path + "/event time_real");
129  if (me == nullptr)
130  // no FastTimerService DQM information
131  return;
132 
133  if ( doPlotsVsScalLumi_ )
134  fillPlotsVsLumi( booker,getter, current_path, "VsScalLumi", scalLumiMEPSet_ );
135  if ( doPlotsVsPixelLumi_ )
136  fillPlotsVsLumi( booker,getter, current_path, "VsPixelLumi", pixelLumiMEPSet_ );
137  if ( doPlotsVsPU_ )
138  fillPlotsVsLumi( booker,getter, current_path, "VsPU", puMEPSet_ );
139 
140  // getter.setCurrentFolder(current_path);
141 
142  double events = me->getTH1F()->GetEntries();
143 
144  // look for per-process directories
145  static const boost::regex process_name(".*/process .*");
146 
147  booker.setCurrentFolder(current_path); // ?!?!?
148  std::vector<std::string> subdirs = getter.getSubdirs();
149  for (auto const & subdir: subdirs) {
150 
151  if (boost::regex_match(subdir, process_name)) {
152 
153  getter.setCurrentFolder(subdir);
154  // look for per-path plots inside each per-process directory
155  std::vector<std::string> subsubdirs = getter.getSubdirs();
156  for (auto const & subsubdir: subsubdirs) {
157  if ( getter.get(subsubdir + "/path time_real") ) {
158  fillPathSummaryPlots(booker, getter, events, subdir);
159  break;
160  }
161  }
162 
163  }
164  } // loop on subdir
165 
166 }
167 
168 void
170  // note: the following checks need to be kept separate, as any of these histograms might be missing
171 
172  booker.setCurrentFolder(current_path);
173  std::vector<std::string> subsubdirs = getter.getSubdirs();
174  size_t npaths = subsubdirs.size();
175 
176  MonitorElement* paths_time = booker.book1D("paths_time_real", "Total (real) time spent in each path", npaths, -0.5, double(npaths)-0.5);
177  MonitorElement* paths_thread = booker.book1D("paths_time_thread","Total (thread) time spent in each path", npaths, -0.5, double(npaths)-0.5);
178  MonitorElement* paths_allocated = booker.book1D("paths_allocated", "Total allocated memory in each path", npaths, -0.5, double(npaths)-0.5);
179  MonitorElement* paths_deallocated = booker.book1D("paths_deallocated","Total deallocated in each path", npaths, -0.5, double(npaths)-0.5);
180 
181  MonitorElement * me;
182  double mean = -1.;
183 
184  // extract the list of Paths and EndPaths from the summary plots
185  int ibin = 1;
186  for (auto const & subsubdir: subsubdirs) {
187 
188  std::string test = "/path ";
189  if ( subsubdir.find(test)==std::string::npos ) continue;
190 
191  static const boost::regex prefix(current_path + "/path ");
192  std::string path = boost::regex_replace(subsubdir,prefix,"");
193 
194  paths_time ->getTH1F()->GetXaxis()->SetBinLabel(ibin,path.c_str());
195  paths_thread ->getTH1F()->GetXaxis()->SetBinLabel(ibin,path.c_str());
196  paths_allocated ->getTH1F()->GetXaxis()->SetBinLabel(ibin,path.c_str());
197  paths_deallocated->getTH1F()->GetXaxis()->SetBinLabel(ibin,path.c_str());
198 
199 
200  if ( (me = getter.get(subsubdir + "/path time_real")) ) {
201  mean = me->getMean();
202  paths_time->getTH1F()->SetBinContent(ibin,mean);
203  }
204  if ( (me = getter.get(subsubdir + "/path time_thread")) ) {
205  mean = me->getMean();
206  paths_thread->getTH1F()->SetBinContent(ibin,mean);
207  }
208  if ( (me = getter.get(subsubdir + "/path allocated")) ) {
209  mean = me->getMean();
210  paths_allocated->getTH1F()->SetBinContent(ibin,mean);
211  }
212 
213  if ( (me = getter.get(subsubdir + "/path deallocated")) ) {
214  mean = me->getMean();
215  paths_deallocated->getTH1F()->SetBinContent(ibin,mean);
216  }
217 
218  ibin++;
219  }
220 
221 
222  for (auto const & subsubdir: subsubdirs) {
223  // for each path, fill histograms with
224  // - the average time spent in each module (total time spent in that module, averaged over all events)
225  // - the running time spent in each module (total time spent in that module, averaged over the events where that module actually ran)
226  // - the "efficiency" of each module (number of time a module succeded divided by the number of times the has run)
227 
228  getter.setCurrentFolder(subsubdir);
229  std::vector<std::string> allmenames = getter.getMEs();
230  if ( allmenames.empty() ) continue;
231 
232  MonitorElement * me_counter = getter.get( subsubdir + "/module_counter" );
233  MonitorElement * me_real_total = getter.get( subsubdir + "/module_time_real_total" );
234  MonitorElement * me_thread_total = getter.get( subsubdir + "/module_time_thread_total" );
235 
236  if (me_counter == nullptr or me_real_total == nullptr)
237  continue;
238 
239  TH1D * counter = me_counter ->getTH1D();
240  TH1D * real_total = me_real_total->getTH1D();
241  TH1D * thread_total = me_thread_total->getTH1D();
242  uint32_t bins = counter->GetXaxis()->GetNbins() - 1;
243  double min = counter->GetXaxis()->GetXmin();
244  double max = counter->GetXaxis()->GetXmax() - 1;
245 
246  TH1F * real_average;
247  TH1F * real_running;
248  TH1F * thread_average;
249  TH1F * thread_running;
250  TH1F * efficiency;
251  MonitorElement * me;
252 
253  booker.setCurrentFolder(subsubdir);
254  me = getter.get( "module_time_real_average" );
255  if (me) {
256  real_average = me->getTH1F();
257  assert( me->getTH1F()->GetXaxis()->GetXmin() == min );
258  assert( me->getTH1F()->GetXaxis()->GetXmax() == max );
259  real_average->Reset();
260  } else {
261  real_average = booker.book1D("module_time_real_average", "module real average timing", bins, min, max)->getTH1F();
262  real_average->SetYTitle("average processing (real) time [ms]");
263  for (uint32_t i = 1; i <= bins; ++i) {
264  const char * module = counter->GetXaxis()->GetBinLabel(i);
265  real_average->GetXaxis()->SetBinLabel(i, module);
266  }
267  }
268 
269  me = getter.get( "module_time_thread_average" );
270  if (me) {
271  thread_average = me->getTH1F();
272  assert( me->getTH1F()->GetXaxis()->GetXmin() == min );
273  assert( me->getTH1F()->GetXaxis()->GetXmax() == max );
274  thread_average->Reset();
275  } else {
276  thread_average = booker.book1D("module_time_thread_average", "module thread average timing", bins, min, max)->getTH1F();
277  thread_average->SetYTitle("average processing (thread) time [ms]");
278  for (uint32_t i = 1; i <= bins; ++i) {
279  const char * module = counter->GetXaxis()->GetBinLabel(i);
280  thread_average->GetXaxis()->SetBinLabel(i, module);
281  }
282  }
283 
284  me = getter.get( "module_time_real_running" );
285  if (me) {
286  real_running = me->getTH1F();
287  assert( me->getTH1F()->GetXaxis()->GetXmin() == min );
288  assert( me->getTH1F()->GetXaxis()->GetXmax() == max );
289  real_running->Reset();
290  } else {
291  real_running = booker.book1D("module_time_real_running", "module real running timing", bins, min, max)->getTH1F();
292  real_running->SetYTitle("running processing (real) time [ms]");
293  for (uint32_t i = 1; i <= bins; ++i) {
294  const char * module = counter->GetXaxis()->GetBinLabel(i);
295  real_running->GetXaxis()->SetBinLabel(i, module);
296  }
297  }
298 
299  me = getter.get( "module_time_thread_running" );
300  if (me) {
301  thread_running = me->getTH1F();
302  assert( me->getTH1F()->GetXaxis()->GetXmin() == min );
303  assert( me->getTH1F()->GetXaxis()->GetXmax() == max );
304  thread_running->Reset();
305  } else {
306  thread_running = booker.book1D("module_time_thread_running", "module thread running timing", bins, min, max)->getTH1F();
307  thread_running->SetYTitle("running processing (thread) time [ms]");
308  for (uint32_t i = 1; i <= bins; ++i) {
309  const char * module = counter->GetXaxis()->GetBinLabel(i);
310  thread_running->GetXaxis()->SetBinLabel(i, module);
311  }
312  }
313 
314  me = getter.get( "module_efficiency" );
315  if (me) {
316  efficiency = me->getTH1F();
317  assert( me->getTH1F()->GetXaxis()->GetXmin() == min );
318  assert( me->getTH1F()->GetXaxis()->GetXmax() == max );
319  efficiency->Reset();
320  } else {
321  efficiency = booker.book1D("module_efficiency", "module efficiency", bins, min, max)->getTH1F();
322  efficiency->SetYTitle("filter efficiency");
323  efficiency->SetMaximum(1.05);
324  for (uint32_t i = 1; i <= bins; ++i) {
325  const char * module = counter->GetXaxis()->GetBinLabel(i);
326  efficiency->GetXaxis()->SetBinLabel(i, module);
327  }
328  }
329 
330 
331  for (uint32_t i = 1; i <= bins; ++i) {
332  double n = counter ->GetBinContent(i);
333  double p = counter ->GetBinContent(i+1);
334  if (n)
335  efficiency->SetBinContent(i, p / n);
336 
337  // real timing
338  double t = real_total->GetBinContent(i);
339  real_average->SetBinContent(i, t / events);
340  if (n)
341  real_running->SetBinContent(i, t / n);
342 
343  // thread timing
344  t = thread_total->GetBinContent(i);
345  thread_average->SetBinContent(i, t / events);
346  if (n)
347  thread_running->SetBinContent(i, t / n);
348  }
349 
350  // vs lumi
351  if ( doPlotsVsScalLumi_ )
352  fillPlotsVsLumi( booker,getter, subsubdir, "VsScalLumi", scalLumiMEPSet_ );
353  if ( doPlotsVsPixelLumi_ )
354  fillPlotsVsLumi( booker,getter, subsubdir, "VsPixelLumi", pixelLumiMEPSet_ );
355  if ( doPlotsVsPU_ )
356  fillPlotsVsLumi( booker,getter, subsubdir, "VsPU", puMEPSet_ );
357 
358  }
359 
360 }
361 
363 void
365 
366  std::vector<std::string> menames;
367 
368  static const boost::regex byls(".*byls");
369  static const boost::regex test(suffix);
370  // get all MEs in the current_path
371  getter.setCurrentFolder(current_path);
372  std::vector<std::string> allmenames = getter.getMEs();
373  for (auto const & m : allmenames) {
374  // get only MEs vs LS
375  if (boost::regex_match(m, byls))
376  menames.push_back(m);
377  }
378  // if no MEs available, return
379  if ( menames.empty() )
380  return;
381 
382  // get info for getting the lumi VS LS histogram
383  std::string folder = pset.folder;
384  std::string name = pset.name;
385  int nbins = pset.nbins;
386  double xmin = pset.xmin;
387  double xmax = pset.xmax;
388 
389  // get lumi/PU VS LS ME
390  getter.setCurrentFolder(folder);
391  MonitorElement* lumiVsLS = getter.get(folder+"/"+name);
392  // if no ME available, return
393  if ( !lumiVsLS ) {
394  edm::LogWarning("FastTimerServiceClient") << "no " << name << " ME is available in " << folder << std::endl;
395  return;
396  }
397 
398  // get range and binning for new MEs x-axis
399  size_t size = lumiVsLS->getTProfile()->GetXaxis()->GetNbins();
400  std::string xtitle = lumiVsLS->getTProfile()->GetYaxis()->GetTitle();
401 
402  std::vector<double> lumi;
403  std::vector<int> LS;
404  for ( size_t ibin=1; ibin <= size; ++ibin ) {
405  // avoid to store points w/ no info
406  if ( lumiVsLS->getTProfile()->GetBinContent(ibin) == 0. ) continue;
407 
408  lumi.push_back( lumiVsLS->getTProfile()->GetBinContent(ibin) );
409  LS.push_back ( lumiVsLS->getTProfile()->GetXaxis()->GetBinCenter(ibin) );
410  }
411 
412  booker.setCurrentFolder(current_path);
413  getter.setCurrentFolder(current_path);
414  for (auto const& m : menames) {
415  std::string label = m;
416  label.erase(label.find("_byls"));
417 
418  MonitorElement* me = getter.get(current_path + "/" + m);
419  float ymin = 0.;
421  std::string ytitle = me->getTProfile()->GetYaxis()->GetTitle();
422 
423  MonitorElement* meVsLumi = getter.get( current_path + "/" + label + "_" + suffix );
424  if (meVsLumi) {
425  assert( meVsLumi->getTProfile()->GetXaxis()->GetXmin() == xmin );
426  assert( meVsLumi->getTProfile()->GetXaxis()->GetXmax() == xmax );
427  meVsLumi->Reset(); // do I have to do it ?!?!?
428  } else {
429  meVsLumi = booker.bookProfile(label + "_" + suffix, label + "_" + suffix, nbins, xmin, xmax, ymin, ymax);
430  // TProfile* meVsLumi_p = meVsLumi->getTProfile();
431  meVsLumi->getTProfile()->GetXaxis()->SetTitle(xtitle.c_str());
432  meVsLumi->getTProfile()->GetYaxis()->SetTitle(ytitle.c_str());
433  }
434  for ( size_t ils=0; ils < LS.size(); ++ils ) {
435  int ibin = me->getTProfile()->GetXaxis()->FindBin(LS[ils]);
436  double y = me->getTProfile()->GetBinContent(ibin);
437 
438  meVsLumi->Fill(lumi[ils],y);
439  }
440  }
441 
442 
443 }
444 
445 void
447  pset.add<std::string>("folder", "HLT/LumiMonitoring");
448  pset.add<std::string>("name" , "lumiVsLS");
449  pset.add<int> ("nbins", 440 );
450  pset.add<double>("xmin", 0.);
451  pset.add<double>("xmax", 22000.);
452 }
453 
454 
455 void
457  pset.add<std::string>("folder", "HLT/LumiMonitoring");
458  pset.add<std::string>("name" , "puVsLS");
459  pset.add<int> ("nbins", 260 );
460  pset.add<double>("xmin", 0.);
461  pset.add<double>("xmax", 130.);
462 }
463 
464 
466 {
467  return MEPSet{
468  pset.getParameter<std::string>("folder"),
469  pset.getParameter<std::string>("name"),
470  pset.getParameter<int>("nbins"),
471  pset.getParameter<double>("xmin"),
472  pset.getParameter<double>("xmax"),
473  };
474 }
475 
476 void
478  // The following says we do not know what parameters are allowed so do no validation
479  // Please change this to state exactly what you do use, even if it is no parameters
481  desc.addUntracked<std::string>( "dqmPath", "HLT/TimerService");
482  desc.add<bool>( "doPlotsVsScalLumi", true );
483  desc.add<bool>( "doPlotsVsPixelLumi", false );
484  desc.add<bool>( "doPlotsVsPU", true );
485 
486  edm::ParameterSetDescription scalLumiMEPSet;
487  fillLumiMePSetDescription(scalLumiMEPSet);
488  desc.add<edm::ParameterSetDescription>("scalLumiME", scalLumiMEPSet);
489 
490  edm::ParameterSetDescription pixelLumiMEPSet;
491  fillLumiMePSetDescription(pixelLumiMEPSet);
492  desc.add<edm::ParameterSetDescription>("pixelLumiME", pixelLumiMEPSet);
493 
495  fillPUMePSetDescription(puMEPSet);
496  desc.add<edm::ParameterSetDescription>("puME", puMEPSet);
497 
498  descriptions.add("fastTimerServiceClient", desc);
499 }
500 
501 //define this as a plug-in
size
Write out results.
T getParameter(std::string const &) const
static void fillPUMePSetDescription(edm::ParameterSetDescription &pset)
void dqmEndLuminosityBlock(DQMStore::IBooker &booker, DQMStore::IGetter &getter, edm::LuminosityBlock const &, edm::EventSetup const &) override
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
MonitorElement * bookProfile(Args &&...args)
Definition: DQMStore.h:157
void fillPlotsVsLumi(DQMStore::IBooker &booker, DQMStore::IGetter &getter, std::string const &current_path, std::string const &suffix, MEPSet pset)
MonitorElement * get(const std::string &path)
Definition: DQMStore.cc:305
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
std::string folder
void fillProcessSummaryPlots(DQMStore::IBooker &booker, DQMStore::IGetter &getter, std::string const &path)
TH1D * getTH1D(void) const
def setup(process, global_tag, zero_tesla=False)
Definition: GeneralSetup.py:1
Definition: config.py:1
double getMean(int axis=1) const
get mean value of histogram along x, y or z axis (axis=1, 2, 3 respectively)
~FastTimerServiceClient() override
void Fill(long long x)
void dqmEndJob(DQMStore::IBooker &booker, DQMStore::IGetter &getter) override
static MEPSet getHistoPSet(const edm::ParameterSet &pset)
void fillPathSummaryPlots(DQMStore::IBooker &booker, DQMStore::IGetter &getter, double events, std::string const &path)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
MonitorElement * book1D(Args &&...args)
Definition: DQMStore.h:115
static void fillLumiMePSetDescription(edm::ParameterSetDescription &pset)
T min(T a, T b)
Definition: MathUtil.h:58
ParameterDescriptionBase * add(U const &iLabel, T const &value)
std::vector< std::string > getMEs(void)
Definition: DQMStore.cc:327
FastTimerServiceClient(edm::ParameterSet const &)
std::string name
void fillSummaryPlots(DQMStore::IBooker &booker, DQMStore::IGetter &getter)
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:277
TH1F * getTH1F(void) const
void add(std::string const &label, ParameterSetDescription const &psetDescription)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::vector< std::string > getSubdirs(void)
Definition: DQMStore.cc:323
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:347
HLT enums.
TProfile * getTProfile(void) const
void Reset(void)
reset ME (ie. contents, errors, etc)
Definition: vlib.h:208