ATLAS Offline Software
SemiDetHelper.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 
7 // //
8 // Implementation of class SemiDetHelper //
9 // //
10 // Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) //
11 // Initial version: March 2011 //
12 // //
14 
15 #include "SemiDetHelper.h"
16 #include <climits>
17 #include <iostream>
18 #include <fstream>
19 #include <sstream>
20 #include <libgen.h>//needed on mac for basename
21 #include <algorithm>
22 #include <vector>
23 #include <set>
24 #include "boost/io/ios_state.hpp"
25 
26 PMonSD::SemiDetHelper::SemiDetHelper(const std::string& jobStartJiffies)
27  : m_cfg_walltime(0),
28  m_meas_pre_ini(true),
29  m_meas_post_ini(true),
30  m_meas_post_1stevt(true),
31  m_meas_post_lastevt(true),
32  m_meas_post_fin(true),
33  m_last_stepidx(INT_MAX),
34  m_last_nevts(UINT_MAX),
35  m_nevts(0),
36  m_need_finalise(true),
37  m_vmpeak(-1),
38  m_nevts_sum(0),
39  m_vmem_sum_evtloop(0),
40  m_rss_sum_evtloop(0),
41  m_prefix("PMonSD "),
42  m_stepprefix("step "),
43  m_specialstep("---"),
44  m_malloclibname(basename((char*)symb2lib("malloc"))),//const cast to char* is for compilation on mac.
45  m_malloc_status("ok"),
46  m_malloc_might_get_slow(false),
47  m_overhead_cpu_tmp(0),
48  m_overhead_cpu_total(0),
49  m_overhead_cpu_n(0),
50  m_overhead_cpu_snapshot_post_1stevt(-1),
51  m_overhead_cpu_snapshot_post_lastevt(-1)
52 {
53  //Magic sequence of malloc calls to tell any spylib (if present,
54  //rather harmless otherwise) that now would be a good time to start
55  //monitoring:
56  {delete[] new char[11];delete[] new char[117];delete[] new char[17];}
57 
58  m_tmpstr.reserve(127);
59  if (!jobStartJiffies.empty()) {
60  //How much time elapsed until now:
62  }
63  m_meas_pre_ini.capture();
67  //Small test that our malloc collection actually works on this platform and with this allocator:
68  // cppcheck-suppress uninitdata
69  double m0=get_malloc_kb(); char *volatile c = new char[1024]; double m1=get_malloc_kb(); delete[] c;
70  if (m0==m1) {
71  m_malloc_status="noinfo";
73  std::cout<<m_prefix<<"WARNING Can't retrieve Malloc information in this setup.";
74  if (m_malloclibname!=basename((char*)symb2lib("mallinfo")))
75  std::cout<<" This is likely because mallinfo is in a different lib than malloc.";
76  std::cout<<std::endl;
77  }
78 #if __GLIBC__<=2 && __GLIBC_MINOR__<=5
79  if (!m_meas.mallocDisabled()&&m_malloclibname=="libc.so.6"&&!envvar_is_set("PMONSD_DONTDISABLESLOWMALLOC")) {
80  //Get ready to disable calls to mallinfo since they might get really slow.
81  //Bug: http://sourceware.org/bugzilla/show_bug.cgi?id=4349
83  }
84 #endif
85 
86 #if DEBUG_SemiDetHelper
87  m_debug_nfinds=0;
88  m_debug_ninserts=0;
89 #endif
90 
91 }
92 
93 void PMonSD::SemiDetHelper::startAud(const std::string& stepName,const std::string& compName, unsigned val_nevts)
94 {
95 #if DEBUG_SemiDetHelper
96  m_debug_meas.capture(false/*cpufirst*/);
97  m_debug_data.addPointStart(m_debug_meas);
98 #endif
99 
100  //We delay the m_measurement.capture() call as long as possible to minimise inclusion of own overhead
101 
102  m_overhead_cpu_tmp = get_cpu_ms();
103 
104  int stepidx = CompDataStdSteps::index(stepName);
105  if (val_nevts==0&&stepidx==CompDataStdSteps::index_evt)
106  stepidx = CompDataStdSteps::index_1st;
107 
108  if (stepidx==CompDataStdSteps::index_other) {
109  startAudOther(compName,stepName);
110  } else {
111  m_nevts=std::max(m_nevts,val_nevts);
112  if (m_last_stepidx!=stepidx||m_last_nevts!=val_nevts)
113  specialAud(stepidx,val_nevts);
114  startAudStd(compName,stepidx);
115  }
116 
117 #if DEBUG_SemiDetHelper
118  m_debug_meas.capture(true/*cpufirst*/);
119  m_debug_data.addPointStop(m_debug_meas);
120 #endif
121 }
122 
123 void PMonSD::SemiDetHelper::stopAud(const std::string& stepName,const std::string& compName, unsigned val_nevts)
124 {
125 #if DEBUG_SemiDetHelper
126  m_debug_meas.capture(false/*cpufirst*/);
127  m_debug_data.addPointStart(m_debug_meas);
128 #endif
129 
130  m_meas.capture(true/*cpufirst*/);//Do this ASAP to minimise inclusion of own overhead
131  m_overhead_cpu_tmp=m_meas.last_cpu_raw_ms();
132 
133  int stepidx = CompDataStdSteps::index(stepName);
134  if (val_nevts==0&&stepidx==CompDataStdSteps::index_evt)
135  stepidx = CompDataStdSteps::index_1st;
136 
137  if (stepidx==CompDataStdSteps::index_other)
138  stopAudOther(compName,stepName);
139  else
140  stopAudStd(compName,stepidx,val_nevts);
141 
142  double dcpu=get_cpu_ms()-m_overhead_cpu_tmp;
143  m_meas.incrementOffsets(0,0,dcpu);
144  m_overhead_cpu_total+=dcpu; ++m_overhead_cpu_n;
145 
146 #if DEBUG_SemiDetHelper
147  m_debug_meas.capture(true/*cpufirst*/);
148  m_debug_data.addPointStop(m_debug_meas);
149 #endif
150 }
151 
153 {
154  //Fixme: for now we don't use the code below. Need to figure out the
155  //optimal way to get rid of addresses from call-backs:
156  return &(mapLookup(compName,m_data_std,m_data_std_lastlookup));
157 
158  //tmp//size_t pos;
159  //tmp//if (stepidx!=CompDataStdSteps::index_cbk||(pos=compName.find('['))==0||pos>=compName.size())
160  //tmp// return &(mapLookup(compName,m_data_std,m_data_std_lastlookup));
161  //tmp////compNames like "TrigConf::DSConfigSvc[0x1e3de4f0]+e7797940" in
162  //tmp////callbacks are annoying and irreproducible. Remove the addresses:
163  //tmp//m_tmpstr.assign(compName.c_str(),pos);
164  //tmp//return &(mapLookup(m_tmpstr,m_data_std,m_data_std_lastlookup));
165 }
166 
167 void PMonSD::SemiDetHelper::startAudStd(const std::string& compName, int stepidx)
168 {
169  CompDataStdSteps * d = findStdData(compName,stepidx);
171  if (stepidx==CompDataStdSteps::index_evt) {
172  m_meas_post_1stevt.captureIfUnused();
173  if (m_overhead_cpu_snapshot_post_1stevt<0)
174  m_overhead_cpu_snapshot_post_1stevt=m_overhead_cpu_total;
175  m_meas.capture(false/*cpufirst*/);//as late as possible to minimise inclusion of own overhead
176  data=&(d->data_evt);
177  } else {
178  if (stepidx==CompDataStdSteps::index_fin) {
179  [[maybe_unused]] static const bool first = [&]() {
180  //Magic sequence of malloc calls+specific string to tell any
181  //spylib (if present, rather harmless otherwise) that now
182  //would be a good time to produce a report from collected data:
183  { std::string dummy("libstringspy_trigger_report"); }
184  { delete[] new char[13];delete[] new char[117];delete[] new char[17]; }
185  return false;
186  }();
187  m_meas_post_lastevt.captureIfUnused();
188  if (m_overhead_cpu_snapshot_post_lastevt<0)
189  m_overhead_cpu_snapshot_post_lastevt=m_overhead_cpu_total;
190  } else if (stepidx==CompDataStdSteps::index_1st) {
191  m_meas_post_ini.captureIfUnused();
192  }
193  data=&(d->data[stepidx]);
194  }
195  startAudFinishUp(data);
196 }
198 {
199  m_meas.capture(false/*cpufirst*/);//as late as possible to minimise inclusion of own overhead
200  double dcpu=m_meas.last_cpu_raw_ms()-m_overhead_cpu_tmp;
201  m_meas.cpu-=dcpu;
202  m_meas.incrementOffsets(0,0,dcpu);//dcpu will be subtracted on next "capture"
203  m_overhead_cpu_total+=dcpu;
204  ++m_overhead_cpu_n;
205  data->addPointStart(m_meas);
206 }
207 
208 void PMonSD::SemiDetHelper::stopAudStd(const std::string& compName, int stepidx,unsigned val_nevts)
209 {
210  CompDataStdSteps * d = findStdData(compName,stepidx);
211  if (stepidx==CompDataStdSteps::index_evt) {
212  d->data_evt.addPointStop(m_meas,val_nevts);
213  } else {
214  d->data[stepidx].addPointStop(m_meas);
215  //Check repeatedly during finalisation for the issue appearing
216  //(due to heavy fragmentation occuring):
217  if (m_malloc_might_get_slow&&stepidx==CompDataStdSteps::index_fin)
218  checkForMallocSlowness(CompDataStdSteps::index_fin);
219  }
220 }
221 
223 {
224  if (m_overhead_cpu_n>1000&&m_overhead_cpu_total>0.2*m_overhead_cpu_n) {
225  //Spending more than 0.2ms/snapshot is unacceptable and is
226  //almost certainly due to the mallinfo performance bug in glibc2.5.
227  m_meas.disableMalloc();
228  if (stepidx==CompDataStdSteps::index_evt) m_malloc_status="autooff_evt";
229  else if (stepidx==CompDataStdSteps::index_fin) m_malloc_status="autooff_fin";
230  else m_malloc_status="autooff";
231  m_malloc_might_get_slow=false;
232  std::cout<<m_prefix<<"WARNING Malloc information gathering becoming slow. Disabling."<<std::endl;
233  }
234 }
235 
236 void PMonSD::SemiDetHelper::specialAud(int stepidx,unsigned val_nevts)
237 {
238  if (m_last_stepidx!=stepidx) {
239  //step changed:
240  switch (stepidx) {
242  m_meas_post_ini.captureIfUnused();
243  break;
245  m_meas_post_1stevt.captureIfUnused();
246  break;
248  m_meas_post_1stevt.captureIfUnused();
249  m_meas_post_lastevt.captureIfUnused();
250  if (m_malloc_might_get_slow)
251  checkForMallocSlowness(CompDataStdSteps::index_fin);
252  break;
253  default: break;
254  };
255  }
256 
257  if (stepidx==CompDataStdSteps::index_evt&&m_last_nevts!=val_nevts) {
258  double vmem,rss;
259  get_vmem_rss_kb(vmem,rss);
260  ++m_nevts_sum;//should be m_nevts-1 in normal jobs, but better be safe.
261  m_vmem_sum_evtloop+=vmem;
262  m_rss_sum_evtloop+=rss;
263  if (val_nevts>=10) {
264  double malloc(get_malloc_kb());
265  if (val_nevts<=100) {
266  m_fit_11to100_vmem.addPoint(val_nevts,vmem);
267  m_fit_11to100_malloc.addPoint(val_nevts,malloc);
268  } else {
269  m_fit_101plus_vmem.addPoint(val_nevts,vmem);
270  m_fit_101plus_malloc.addPoint(val_nevts,malloc);
271  }
272  }
273  m_last_nevts=val_nevts;//important to only increment in evt steps (since interspersed with cbk steps)
274  if (m_malloc_might_get_slow)
275  checkForMallocSlowness(CompDataStdSteps::index_evt);
276  }
277  m_last_stepidx=stepidx;
278 }
279 
280 void PMonSD::SemiDetHelper::startAudOther(const std::string& compName, const std::string& stepName)
281 {
282  m_tmp_otherkey.first=compName;
283  m_tmp_otherkey.second=stepName;
284  CompDataBasic& data=mapLookup(m_tmp_otherkey,m_data_other,m_data_other_lastlookup);
285  startAudFinishUp(&data);
286 }
287 
288 void PMonSD::SemiDetHelper::stopAudOther(const std::string& compName, const std::string& stepName)
289 {
290  m_tmp_otherkey.first=compName;
291  m_tmp_otherkey.second=stepName;
292  CompDataBasic& data=mapLookup(m_tmp_otherkey,m_data_other,m_data_other_lastlookup);
293 
294  data.addPointStop(m_meas);
295  //if (data.nEntries()==2&&data.sortValCPU()<200&&data.sortValMemory()<200&&stepName=="dso") {
296  // //Special: For some reason some dso's are loaded twice (but taking
297  // //essentially zero resources). This is rather confusing to most
298  // //users, so we exclude additional entries count for a given dso *IF* it
299  // //covers innocent resource movements.
300  // data.setEntries(data.nEntries()-1);
301  // static unsigned hackcount=0;
302  // if (++hackcount==50)
303  // std::cout<<m_prefix<<"WARNING: Internal dso reporting"
304  // <<" hack has gotten out of hand (current dso "<<compName<<")"<<std::endl;
305  //}
306 }
307 
309 {
310  if (!m_need_finalise)
311  return;
312  m_need_finalise=false;
313  m_meas_post_fin.captureIfUnused();
314  m_vmpeak=vmpeak();
315 }
316 
318  const std::string& info_full_output_inside)
319 {
320  finalise();
321  bool ok=true;
322  std::ofstream f;
323  f.open(file.c_str());
324  if (!f.fail()&&f.is_open()) {
325  actualReport(f,true,info_full_output_inside);
326  } else {
327  ok=false;
328  }
329  f.close();
330  if (!ok)
331  std::cout<<m_prefix<<"WARNING Could not write output to file: "<<file<<std::endl;
332  return ok;
333 }
334 
335 void PMonSD::SemiDetHelper::reportToStdout(const std::string& info_full_output_inside,bool showall)
336 {
337  finalise();
338  actualReport(std::cout,showall,info_full_output_inside);
339 }
340 
341 bool PMonSD::SemiDetHelper::report(const std::string& file,
342  const std::string& info_full_output_inside,
343  bool stdout_uncollapsed)
344 {
345  finalise();
346  std::string actualfile=file;
347  bool fileok=reportToFile(file,info_full_output_inside);
348  if (!fileok)
349  actualfile+=" (failed)";
350  reportToStdout(info_full_output_inside,stdout_uncollapsed);
351  return fileok;
352 }
353 
355  const std::string& stepName,
356  const std::string& infoName,
357  const Meas&m) const
358 {
359  double vmem(0),malloc(0),cpu(0),wall(0);
360  unsigned n(0);
361  if (!m.unused()) {
362  n=1;
363  vmem=m.vmem;
364  malloc=m.malloc;
365  cpu=m.cpu;
366  wall=m.wall;
367  }
368  bool special=m.hasWallTime();
369  int w(special?8:6);
370  os<<m_prefix<<"["<<stepName<<"]";
371  os<<" ";field_i(os,4,n);
372  os<<" ";field_f(os,w,cpu,false);
373  if (special) {
374  os<<" ";
375  field_f(os,w,wall,false);
376  }
377  os<<" ";field_f(os,w,vmem,false);
378  os<<" ";field_f(os,w,malloc,false);
379  os<<" "<<infoName;
380  os<<"\n";
381 }
382 
384  const std::string& stepName,
385  const std::string& compName,
386  const CompDataBasic* data,
387  bool normal_as_extended) const
388 {
389  const CompDataExtended* data_e = dynamic_cast<const CompDataExtended*>(data);
390  os<<m_prefix<<"["<<stepName<<"]";
391  if (data_e) {
392  os<<" ";field_i(os,4,data_e->nEntries());
393  os<<" ";field_f(os,6,data_e->meanDeltaCPU(),false);
394  os<<" ";field_f(os,6,data_e->maxDeltaCPU(),false);
395  os<<"@";field_i(os,4,data_e->maxDeltaCPU_iEntry(),true);
396  os<<" ";field_f(os,6,data_e->meanDeltaVMEM(),false);
397  os<<" ";field_f(os,6,data_e->maxDeltaVMEM(),false);
398  os<<"@";field_i(os,4,data_e->maxDeltaVMEM_iEntry(),true);
399  os<<" ";field_f(os,6,data_e->meanDeltaMalloc(),false);
400  os<<" ";field_f(os,6,data_e->maxDeltaMalloc(),false);
401  os<<"@";field_i(os,4,data_e->maxDeltaMalloc_iEntry(),true);
402  } else {
403  os<<" ";field_i(os,4,data->nEntries());
404  os<<" ";field_f(os,6,data->meanDeltaCPU(),false);
405  if (normal_as_extended) { os <<" "; }
406  os<<" ";field_f(os,7,data->meanDeltaVMEM(),false);
407  if (normal_as_extended) { os <<" "; }
408  os<<" ";field_f(os,7,data->meanDeltaMalloc(),false);
409  if (normal_as_extended) { os <<" "; }
410  }
411  os <<" "<<compName<<"\n";
412 }
413 
414 void PMonSD::SemiDetHelper::format(std::ostream&os,const std::string& stepName, const std::string& infoName,
415  const PerfMon::LinFitSglPass& fit_vmem, const PerfMon::LinFitSglPass& fit_malloc) const
416 {
417  os<<m_prefix<<"["<<stepName<<"]";
418  os<<" ";field_i(os,4,fit_vmem.nPoints());
419  os<<" - ";
420  os<<" - ";
421  field_f(os,8,fit_vmem.slope(),false);
422  os<<" ";field_f(os,8,fit_malloc.slope(),false);
423  os<<" "<<infoName;
424  os<<"\n";
425 }
426 
427 void PMonSD::SemiDetHelper::format(std::ostream&os,const std::string& str, bool center) const
428 {
429  const unsigned width(80);
430  unsigned nleft=0;
431  if (str.size()<width)
432  nleft=(width-str.size())/2;
433  unsigned nright=nleft;
434  if (!center) {
435  nleft=0;
436  nright*=2;
437  }
438  if ((nleft+nright+str.size())<width)
439  nright+=1;
440 
441  os<<m_prefix<<"===";
442  for (unsigned i=0;i<nleft;++i) os<<"=";
443  os<<" "<<str<<" ";
444  for (unsigned i=0;i<nright;++i) os<<"=";
445  os<<"===\n";
446 }
448 {
449  //null sw means special section
450  if (sw&&dynamic_cast<const CompDataExtended*>(sw->getExampleData())) {
451  //extended...
452  os<<m_prefix;spaces(os,sw->stepName().size()+2);
453  os<<" n cpu max@evt vmem max@evt malloc max@evt component\n";
454  } else {
455  os<<m_prefix;spaces(os,(sw?sw->stepName():m_specialstep).size()+2);
456  os<<" n";
457  if (!sw)
458  os<<" cpu wall vmem malloc component";//bigger numbers, bigger spacing
459  else
460  os<<" cpu vmem malloc component";
461  os<<"\n";
462  }
463 }
464 
465 namespace PMonSD {
466  struct Entry {
467  static const int show_group_undef = -2;
468  static const int show_group_displayed = -1;
470  public:
471  const std::string* compName;
473 
474  Entry(const std::string*c,const CompDataBasic*d)
476 
479  bool displayed() const { return m_show_group==show_group_displayed; }
480  int collapse_nentries() const { assert(m_show_group>=0); return m_show_group; }
481  };
482 
483  class CmpEntries {
484  public:
485  static const unsigned specialsort=UINT_MAX;
486  CmpEntries(unsigned ival) : m_ival(ival) {}
487  bool operator()(const Entry&a,const Entry&b) {
488  double va,vb;
489  if (m_ival==specialsort) {
490  //sort by vmem+malloc followed cpu:
491  va=a.data->sortValMemory();
492  vb=b.data->sortValMemory();
493  if (va!=vb)
494  return va>vb;
495  va=a.data->sortValCPU();vb=b.data->sortValCPU();
496  } else {
497  va=a.data->sortVal(m_ival);vb=b.data->sortVal(m_ival);
498  }
499  if (va==vb) {
500  //if cpu, try to sort by vmem+malloc as well (for the final evt-report):
502  va=a.data->sortValMemory();
503  vb=b.data->sortValMemory();
504  if (va!=vb)
505  return va>vb;
506  }
507  //Finally sort by names, just to have a well-defined order.
508  return *(a.compName)<*(b.compName);
509  }
510  return va>vb;
511  }
512  private:
513  unsigned m_ival;
514  };
515 
516  struct Count { Count(): val(0) {} unsigned val; };//an integer which inits to 0.
517 
518 }
519 
520 void PMonSD::SemiDetHelper::processStep(std::ostream&os,StepWrapper*sw,bool showall) const {
521 
523  //Settings for collapsing insignificant entries:
524 
525  unsigned collapse_limit=6;//fewer than this won't be collapsed
526  double showfraction=1.0;
527  if (!showall) {
528  if (sw->stepName()=="evt") showfraction=0.99;
529  else if (sw->stepName()=="dso") showfraction=0.25;
530  else showfraction=0.8;
531  }
532 
533  const std::string ignore_name("PerfMonSlice");
534 
536  //1) Collect info in more handy structures:
537  static const unsigned nvals=CompDataBasic::nvals;
538  float totals[nvals];
539  float totals_sortvals[nvals];//sum of absolute values
540  std::vector<Entry> entries;
541  // => Init:
542  entries.reserve(sw->nComps());
543  for(unsigned ival=0; ival<nvals; ++ival)
544  totals[ival]=totals_sortvals[ival]=0.0;
545  // => Collect
546  const std::string* compName;
547  const CompDataBasic *data(0);
548  sw->iterateReset();
549  bool hasentry(false);
550  while(sw->getNext(compName,data)) {
551  if (*compName==ignore_name) continue;
552  if (data->nEntries()==0) continue;//always ignore data with no entries
553  hasentry=true;
554  entries.push_back(Entry(compName,data));
555  for(unsigned ival=0; ival<nvals; ++ival) {
556  totals[ival] += data->getVal(ival);//nb: this is not the value mean, but the sum (which is what we want)
557  totals_sortvals[ival] += data->sortVal(ival);
558  }
559  }
560 
562  //2) Find out which entries to show and which to collapse
563 
564  if (showall) {
565  //Don't collapse any components...
567  for (;it!=itE;++it)
568  it->setDisplayed();
569  } else {
570  // => For each type of value, take the first components until
571  // limit is reached and collapse the rest:
572  for(unsigned ival=0; ival<nvals; ++ival) {
573  double sum(0.0), limit(showfraction*totals_sortvals[ival]);
574  std::sort(entries.begin(),entries.end(),CmpEntries(ival));
576  for (;it!=itE;++it) {
577  double v=it->data->sortVal(ival);
578  if (sum<limit&&(showall||v>0.5)) {
579  sum+=v;
580  it->setDisplayed();
581  } else {
582  //Collapse unless already displayed due to other value:
583  if (!it->displayed())
584  it->setCollapsed(it->data->nEntries());
585  }
586  }
587  }
588  {
589  //To avoid stupidities like collapsing 1 component, go back and decollapse some:
590  // -> count:
591  std::map<unsigned,Count> collapse_count;
592  std::map<unsigned,Count>::iterator collapse_count_cache(collapse_count.end());
594  for (it=entries.begin();it!=itE;++it)
595  if (!it->displayed())
596  mapLookup(it->data->nEntries(),collapse_count,collapse_count_cache).val += 1;
597  // -> decollapse:
598  for (it=entries.begin();it!=itE;++it)
599  if (!it->displayed()&&collapse_count[it->data->nEntries()].val<collapse_limit)
600  it->setDisplayed();
601  }
602 
603  }
604 
606  //3) Print
607  format(os,m_stepprefix+sw->stepName());
608  if (hasentry)
609  colheader(os,sw);
610  // -> print displayed entries and collect collapsed/total statistics
611  std::sort(entries.begin(),entries.end(),CmpEntries(sw->stepName()=="evt"?0:CmpEntries::specialsort));
613  std::map<unsigned,CompDataBasic> collapse_map,totals_map;
614  std::map<unsigned,CompDataBasic>::iterator it_collapse_cache(collapse_map.end());
615  std::map<unsigned,CompDataBasic>::iterator it_totals_cache(totals_map.end());
616  for (;it!=itE;++it) {
617  unsigned n(it->data->nEntries());
618  CompDataBasic& data_total = mapLookup(n,totals_map,it_totals_cache);
619  data_total.add(*(it->data));
620  if (it->displayed()) {
621  format(os,sw->stepName(),*(it->compName),it->data);
622  } else {
623  //Add to collapse
624  CompDataBasic& data_collapse = mapLookup(n,collapse_map,it_collapse_cache);
625  data_collapse.add(*(it->data));
626  }
627  }
628  // -> print collapsed and total statistics:
629  std::map<unsigned,CompDataBasic>::iterator it_summary, it_summaryE;
630  it_summary=collapse_map.begin();it_summaryE=collapse_map.end();
631  for (;it_summary!=it_summaryE;++it_summary) {
632  std::stringstream s;
633  s<<"[collapsed_"<<it_summary->second.nEntries()<<"_comps]";
634  it_summary->second.setEntries(it_summary->first);
635  format(os,sw->stepName(),s.str(),&it_summary->second,sw->extended());
636  }
637  it_summary=totals_map.begin();it_summaryE=totals_map.end();
638  for (;it_summary!=it_summaryE;++it_summary) {
639  std::stringstream s;
640  s<<"[total_for_"<<it_summary->second.nEntries()<<"_comps]";
641  it_summary->second.setEntries(it_summary->first);
642  format(os,sw->stepName(),s.str(),&it_summary->second,sw->extended());
643  }
644 }
645 
646 void PMonSD::SemiDetHelper::actualReport(std::ostream&os,bool showall,const std::string& info_full_output_inside)
647 {
648  boost::io::ios_base_all_saver ssave (os);
649  finalise();
650 #if DEBUG_SemiDetHelper
651 // m_debug_meas.capture(false/*cpufirst*/);
652 // m_debug_data.addPointStart(m_debug_meas);
653 #endif
654 
655  os << std::fixed;//because we don't care about differences <1ms or <1kb.
656 
657  format(os,showall?"semi-detailed perfmon info v1.0f / start" //Remember to update version number if changing!
658  :"semi-detailed perfmon info v1.0c / start");//=> And must ALWAYS be the same as in PMonSD.py
659  format(os,"Documentation: https://twiki.cern.ch/twiki/bin/viewauth/Atlas/PerfMonSD",false/*center*/);
660  format(os,"Note that documentation includes recipe for easy parsing from python. ",false/*center*/);
661  format(os,"Units are milliseconds (cpu/wall) and kilobytes (vmem/malloc). ",false/*center*/);
662  if (!info_full_output_inside.empty()) {
663  const unsigned cw(71);
664  std::string s;s.reserve(cw);
665  s.clear();s+="Full output inside: ";s+=info_full_output_inside;
666  while (s.size()<cw) s+=" ";
667  format(os,s,false/*center*/);
668  }
669  //Standard steps - output:
670  { StepWrapperStd step_ini("ini",&m_data_std);processStep(os,&step_ini,showall); }
671  { StepWrapperStd step_1st("1st",&m_data_std);processStep(os,&step_1st,showall); }
672  { StepWrapperStd step_cbk("cbk",&m_data_std);processStep(os,&step_cbk,showall); }
673  { StepWrapperStd step_evt("evt",&m_data_std);processStep(os,&step_evt,showall); }
674  { StepWrapperStd step_fin("fin",&m_data_std);processStep(os,&step_fin,showall); }
675 
676  //Other steps - which do we have?:
677  std::set<std::string> othersteps;
678  MapOtherSteps::iterator it_other(m_data_other.begin()),it_other_E(m_data_other.end());
679  for (;it_other!=it_other_E;++it_other)
680  othersteps.insert((*it_other).first.second);
681 
682  //Other steps - output:
683  std::set<std::string>::const_iterator it_other_stepname(othersteps.begin()),it_other_stepnameE(othersteps.end());
684  for (;it_other_stepname!=it_other_stepnameE;++it_other_stepname) {
685  StepWrapperOther step(*it_other_stepname,&m_data_other);
686  processStep(os,&step,showall);
687  }
688 
689  //Special steps
690  format(os,"special info");
691  colheader(os,0);
692  //since we don't know what the first value of wall/cpu actually means, subtract it:
693  m_meas_post_ini.wall-=m_meas_pre_ini.wall;
694  m_meas_post_1stevt.wall-=m_meas_pre_ini.wall;
695  m_meas_post_lastevt.wall-=m_meas_pre_ini.wall;
696  m_meas_post_fin.wall-=m_meas_pre_ini.wall;
697  m_meas_pre_ini.wall=0;
698  m_meas_post_ini.cpu-=m_meas_pre_ini.cpu;
699  m_meas_post_1stevt.cpu-=m_meas_pre_ini.cpu;
700  m_meas_post_lastevt.cpu-=m_meas_pre_ini.cpu;
701  m_meas_post_fin.cpu-=m_meas_pre_ini.cpu;
702  m_meas_pre_ini.cpu=0;
703  //Figure out evtloop and overhead contributions:
704  unsigned evtloop_n(0), overhead_n(0);
705  double evtloop_cpu(0.),evtloop_wall(0.), overhead_cpu(0.), overhead_wall(0.);
706  double internalcpu_evtloop(0),internalcpu_onceperjob(0);
707  //NB: if first event is puny and the following are huge, we could in
708  //principle end up with negative overhead numbers.
709  if (m_nevts>1 && !m_meas_post_lastevt.unused() && !m_meas_post_1stevt.unused()) {
710  evtloop_cpu = (m_meas_post_lastevt.cpu -m_meas_post_1stevt.cpu )/(m_nevts-1);
711  evtloop_wall = (m_meas_post_lastevt.wall-m_meas_post_1stevt.wall)/(m_nevts-1);
712  evtloop_n = m_nevts;
713  internalcpu_evtloop=(m_overhead_cpu_snapshot_post_lastevt-m_overhead_cpu_snapshot_post_1stevt)/(m_nevts-1);
714  if (!m_meas_pre_ini.unused()&&!m_meas_post_fin.unused()) {
715  overhead_cpu = m_meas_post_fin.cpu -m_meas_pre_ini.cpu-evtloop_n*evtloop_cpu;
716  overhead_wall = m_meas_post_fin.wall-m_meas_pre_ini.wall-evtloop_n*evtloop_wall;
717  overhead_n = 1;
718  internalcpu_onceperjob=m_overhead_cpu_total-evtloop_n*internalcpu_evtloop;
719  }
720  }
721  //output
722  os<<m_prefix<<"[---] ";field_i(os,4,evtloop_n);os<<" ";field_f(os,8,evtloop_cpu);
723  os<<" ";field_f(os,8,evtloop_wall);os<<" - - evtloop_time\n";
724  os<<m_prefix<<"[---] ";field_i(os,4,overhead_n);os<<" ";field_f(os,8,overhead_cpu);
725  os<<" ";field_f(os,8,overhead_wall);os<<" - - overhead_time\n";
726  const std::string s=m_specialstep;
727  format(os,s,"snapshot_pre_ini",m_meas_pre_ini);
728  format(os,s,"snapshot_post_ini",m_meas_post_ini);
729  format(os,s,"snapshot_post_1stevt",m_meas_post_1stevt);
730  format(os,s,"snapshot_post_lastevt",m_meas_post_lastevt);
731  format(os,s,"snapshot_post_fin",m_meas_post_fin);
732  format(os,s,"leakperevt_evt11to100",m_fit_11to100_vmem,m_fit_11to100_malloc);
733  format(os,s,"leakperevt_evt101plus",m_fit_101plus_vmem,m_fit_101plus_malloc);
734  os<<m_prefix<<"["<<s<<"] vmem_peak="<<int(m_vmpeak+0.5)
735  <<" vmem_mean="<<(m_nevts_sum?int(m_vmem_sum_evtloop/m_nevts_sum+.5):0)
736  <<" rss_mean="<< (m_nevts_sum?int( m_rss_sum_evtloop/m_nevts_sum+.5):0)<<"\n";
737  os<<m_prefix<<"["<<s<<"] jobcfg_walltime="<<int(m_cfg_walltime+0.5)<<" jobstart="<<m_starttime<<"\n";
738  os<<m_prefix<<"["<<s<<"] cpu_bmips="<<bogomips()
739  <<" cpu_res="<<int(0.5+1000.0*secs_per_jiffy())
740  <<" release="<<envvar("AtlasVersion","unknown_release")<<"/"<<envvar("CMTCONFIG","unknown_cmtconfig")<<"\n";
741  os<<m_prefix<<"["<<s<<"] cpu_model="<<cpu_model()<<"\n";
742  os<<m_prefix<<"["<<s<<"] malloc="<<m_malloclibname<<"/"<<m_malloc_status
743  <<" pycintex_vmemfix="<<envvar("ATHENA_PYCINTEX_MINVMEM","0")<<"\n";
744  os<<m_prefix<<"["<<s<<"] pmonsd_cost_onceperjob="<<int(0.5+internalcpu_onceperjob)
745  <<" pmonsd_cost_perevt="<<int(0.5+internalcpu_evtloop)<<"\n";
746 
747 #if DEBUG_SemiDetHelper
748 // m_debug_meas.capture(true/*cpufirst*/);
749 // m_debug_data.addPointStop(m_debug_meas);
750  os<<m_prefix<<"Own resource consumption ["<<m_debug_data.nEntries()
751  <<" calls]: <cpu> [ms]="<<m_debug_data.meanDeltaCPU()
752  <<", total memory usage[kb]~="<<m_debug_data.meanDeltaMalloc()*m_debug_data.nEntries()
753  <<", total memory usage vmem [kb]~="<<m_debug_data.meanDeltaVMEM()*m_debug_data.nEntries()
754  <<", #map lookups="<<m_debug_nfinds
755  <<", #map inserts="<<m_debug_ninserts
756  <<"\n";
757 #endif
758  format(os,"semi-detailed perfmon info / end");
759  os<<std::flush;
760 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
PMonSD::SemiDetHelper::m_meas
Meas m_meas
Definition: SemiDetHelper.h:88
PMonSD::CmpEntries
Definition: SemiDetHelper.cxx:483
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
python.CaloRecoConfig.f
f
Definition: CaloRecoConfig.py:127
AddEmptyComponent.compName
compName
Definition: AddEmptyComponent.py:32
PerfMon::LinFitSglPass
Definition: LinFitSglPass.h:22
PMonSD::SemiDetHelper::specialAud
void specialAud(int stepidx, unsigned val_nevts)
Definition: SemiDetHelper.cxx:236
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
PMonSD::setUTCTimeString
void setUTCTimeString(std::string &s, double offset_ms=0)
Definition: SemiDetMisc.h:611
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
PMonSD::Meas::disableMalloc
void disableMalloc()
Definition: SemiDetMisc.h:99
max
#define max(a, b)
Definition: cfImp.cxx:41
PMonSD::CmpEntries::m_ival
unsigned m_ival
Definition: SemiDetHelper.cxx:513
vtune_athena.format
format
Definition: vtune_athena.py:14
FullCPAlgorithmsTest_eljob.flush
flush
Definition: FullCPAlgorithmsTest_eljob.py:168
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
PMonSD::StepWrapper::stepName
virtual const std::string & stepName() const =0
PMonSD::get_absolute_wall_ms
double get_absolute_wall_ms()
Definition: SemiDetMisc.h:402
hist_file_dump.d
d
Definition: hist_file_dump.py:137
PMonSD::CompDataStdSteps::index_fin
static constexpr int index_fin
Definition: SemiDetMisc.h:185
PMonSD::CompDataBasic::meanDeltaVMEM
double meanDeltaVMEM() const
Definition: SemiDetMisc.h:568
xAOD::char
char
Definition: TrigDecision_v1.cxx:38
PMonSD::StepWrapper::nComps
virtual unsigned nComps() const =0
PMonSD::CompDataStdSteps::index_evt
static constexpr int index_evt
Definition: SemiDetMisc.h:182
skel.it
it
Definition: skel.GENtoEVGEN.py:423
PMonSD::CompDataStdSteps::index_other
static constexpr int index_other
Definition: SemiDetMisc.h:181
PMonSD::Count::Count
Count()
Definition: SemiDetHelper.cxx:516
PMonSD::CompDataStdSteps::index_1st
static constexpr int index_1st
Definition: SemiDetMisc.h:183
PMonSD::CompDataExtended::maxDeltaVMEM_iEntry
unsigned maxDeltaVMEM_iEntry() const
Definition: SemiDetMisc.h:596
SemiDetHelper.h
PMonSD::SemiDetHelper::findStdData
CompDataStdSteps * findStdData(const std::string &compName, int stepidx)
Definition: SemiDetHelper.cxx:152
PMonSD::CompDataBasic::meanDeltaMalloc
double meanDeltaMalloc() const
Definition: SemiDetMisc.h:569
PMonSD::CompDataBasic
Definition: SemiDetMisc.h:109
PMonSD::SemiDetHelper::m_starttime
std::string m_starttime
Definition: SemiDetHelper.h:95
PMonSD::SemiDetHelper::colheader
void colheader(std::ostream &os, StepWrapper *sw) const
Definition: SemiDetHelper.cxx:447
PMonSD::secs_per_jiffy
double secs_per_jiffy()
Definition: SemiDetMisc.h:412
PMonSD::SemiDetHelper::m_tmpstr
std::string m_tmpstr
Definition: SemiDetHelper.h:195
PMonSD::SemiDetHelper::m_prefix
const std::string m_prefix
Definition: SemiDetHelper.h:153
PMonSD::Entry::show_group_displayed
static const int show_group_displayed
Definition: SemiDetHelper.cxx:468
PMonSD::Meas
Definition: SemiDetMisc.h:55
PMonSD::Entry::Entry
Entry(const std::string *c, const CompDataBasic *d)
Definition: SemiDetHelper.cxx:474
TruthTest.itE
itE
Definition: TruthTest.py:25
PMonSD::StepWrapper::getExampleData
const CompDataBasic * getExampleData()
Definition: SemiDetMisc.h:222
PMonSD::Entry::displayed
bool displayed() const
Definition: SemiDetHelper.cxx:479
PMonSD::get_cpu_ms
double get_cpu_ms()
Definition: SemiDetMisc.h:544
PMonSD::Entry::data
const CompDataBasic * data
Definition: SemiDetHelper.cxx:472
PMonSD::cpu_model
std::string cpu_model()
Definition: SemiDetMisc.h:361
WriteCellNoiseToCool.ival
ival
Definition: WriteCellNoiseToCool.py:337
PMonSD::envvar
const char * envvar(const char *e, const char *def="")
Definition: SemiDetMisc.h:374
PMonSD::SemiDetHelper::finalise
void finalise()
Definition: SemiDetHelper.cxx:308
PlotCalibFromCool.nentries
nentries
Definition: PlotCalibFromCool.py:798
python.changerun.m1
m1
Definition: changerun.py:32
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
PMonSD::SemiDetHelper::startAud
void startAud(const std::string &stepName, const std::string &compName, unsigned val_nevts)
Definition: SemiDetHelper.cxx:93
PMonSD::jobstart_jiffy2unix_ms
double jobstart_jiffy2unix_ms(const std::string &s)
Definition: SemiDetMisc.h:426
lumiFormat.i
int i
Definition: lumiFormat.py:92
PMonSD::Count::val
unsigned val
Definition: SemiDetHelper.cxx:516
beamspotman.n
n
Definition: beamspotman.py:731
PMonSD::Meas::mallocDisabled
bool mallocDisabled() const
Definition: SemiDetMisc.h:98
PMonSD::SemiDetHelper::processStep
void processStep(std::ostream &os, StepWrapper *, bool showall) const
Definition: SemiDetHelper.cxx:520
PMonSD::CompDataBasic::nEntries
unsigned nEntries() const
Definition: SemiDetMisc.h:566
file
TFile * file
Definition: tile_monitor.h:29
PMonSD::StepWrapper::getNext
virtual bool getNext(const std::string *&compName, const CompDataBasic *&)=0
PMonSD::CompDataStdSteps
Definition: SemiDetMisc.h:176
PMonSD::SemiDetHelper::m_data_std
MapStdSteps m_data_std
Definition: SemiDetHelper.h:110
python.xAODType.dummy
dummy
Definition: xAODType.py:4
TrigInDetValidation_Base.malloc
malloc
Definition: TrigInDetValidation_Base.py:129
PMonSD::Entry::collapse_nentries
int collapse_nentries() const
Definition: SemiDetHelper.cxx:480
PMonSD::Entry::compName
const std::string * compName
Definition: SemiDetHelper.cxx:471
PMonSD::CompDataExtended::maxDeltaVMEM
double maxDeltaVMEM() const
Definition: SemiDetMisc.h:595
PerfMon::LinFitSglPass::nPoints
unsigned nPoints() const
Definition: LinFitSglPass.h:31
ReadFromCoolCompare.os
os
Definition: ReadFromCoolCompare.py:231
PMonSD::Entry::setCollapsed
void setCollapsed(unsigned nentries)
Definition: SemiDetHelper.cxx:477
PMonSD::SemiDetHelper::m_meas_pre_ini
Meas m_meas_pre_ini
Definition: SemiDetHelper.h:90
PMonSD
Definition: PerfMonSvc.h:61
PMonSD::SemiDetHelper::startAudStd
void startAudStd(const std::string &compName, int stepidx)
Definition: SemiDetHelper.cxx:167
PMonSD::StepWrapperStd
Definition: SemiDetMisc.h:232
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
PMonSD::symb2lib
const char * symb2lib(const char *symbol, const char *failstr="unknown")
Definition: SemiDetMisc.h:433
PMonSD::CompDataExtended::maxDeltaCPU_iEntry
unsigned maxDeltaCPU_iEntry() const
Definition: SemiDetMisc.h:594
PMonSD::SemiDetHelper::reportToStdout
void reportToStdout(const std::string &info_full_output_inside, bool showall)
Definition: SemiDetHelper.cxx:335
PMonSD::Entry::setDisplayed
void setDisplayed()
Definition: SemiDetHelper.cxx:478
PMonSD::Entry::show_group_undef
static const int show_group_undef
Definition: SemiDetHelper.cxx:467
PMonSD::Count
Definition: SemiDetHelper.cxx:516
PMonSD::SemiDetHelper::m_cfg_walltime
double m_cfg_walltime
Definition: SemiDetHelper.h:89
PMonSD::StepWrapper::extended
virtual bool extended() const
Definition: SemiDetMisc.h:221
python.PyAthena.v
v
Definition: PyAthena.py:157
PMonSD::StepWrapper::iterateReset
virtual void iterateReset()=0
PMonSD::SemiDetHelper::m_data_other
MapOtherSteps m_data_other
Definition: SemiDetHelper.h:114
PMonSD::CompDataBasic::add
void add(const CompDataBasic &other)
Definition: SemiDetMisc.h:143
PMonSD::StepWrapper
Definition: SemiDetMisc.h:213
PMonSD::StepWrapperOther
Definition: SemiDetMisc.h:270
a
TList * a
Definition: liststreamerinfos.cxx:10
PMonSD::vmpeak
unsigned vmpeak()
Definition: SemiDetMisc.h:302
PMonSD::SemiDetHelper::reportToFile
bool reportToFile(const std::string &file, const std::string &info_full_output_inside)
Definition: SemiDetHelper.cxx:317
PMonSD::Entry::m_show_group
int m_show_group
Definition: SemiDetHelper.cxx:469
Base_Fragment.width
width
Definition: Sherpa_i/share/common/Base_Fragment.py:59
PMonSD::CompDataBasic::nvals
static constexpr unsigned nvals
Definition: SemiDetMisc.h:129
PMonSD::SemiDetHelper::m_malloclibname
const std::string m_malloclibname
Definition: SemiDetHelper.h:156
DeMoScan.first
bool first
Definition: DeMoScan.py:534
PMonSD::bogomips
int bogomips()
Definition: SemiDetMisc.h:367
PMonSD::SemiDetHelper::m_data_std_lastlookup
MapStdSteps::iterator m_data_std_lastlookup
Definition: SemiDetHelper.h:111
PMonSD::Entry
Definition: SemiDetHelper.cxx:466
PMonSD::get_vmem_rss_kb
void get_vmem_rss_kb(double &vmem, double &rss, bool vmemonly=false)
Definition: SemiDetMisc.h:447
PMonSD::SemiDetHelper::actualReport
void actualReport(std::ostream &, bool showall, const std::string &info_full_output_inside)
Definition: SemiDetHelper.cxx:646
PerfMon::LinFitSglPass::slope
double slope() const
Definition: LinFitSglPass.h:75
PMonSD::SemiDetHelper::checkForMallocSlowness
void checkForMallocSlowness(int stepidx)
Definition: SemiDetHelper.cxx:222
PMonSD::CompDataBasic::meanDeltaCPU
double meanDeltaCPU() const
Definition: SemiDetMisc.h:567
entries
double entries
Definition: listroot.cxx:49
PMonSD::CompDataExtended::maxDeltaMalloc_iEntry
unsigned maxDeltaMalloc_iEntry() const
Definition: SemiDetMisc.h:598
PMonSD::SemiDetHelper::m_malloc_status
std::string m_malloc_status
Definition: SemiDetHelper.h:157
LArCellBinning.step
step
Definition: LArCellBinning.py:158
PMonSD::CompDataBasic::ival_cpu
static constexpr unsigned ival_cpu
Definition: SemiDetMisc.h:130
str
Definition: BTagTrackIpAccessor.cxx:11
PMonSD::SemiDetHelper::stopAudStd
void stopAudStd(const std::string &compName, int stepidx, unsigned val_nevts)
Definition: SemiDetHelper.cxx:208
PMonSD::SemiDetHelper::startAudFinishUp
void startAudFinishUp(CompDataBasic *)
Definition: SemiDetHelper.cxx:197
PMonSD::SemiDetHelper::SemiDetHelper
SemiDetHelper(const std::string &jobStartJiffies="")
Definition: SemiDetHelper.cxx:26
PMonSD::CompDataExtended::maxDeltaMalloc
double maxDeltaMalloc() const
Definition: SemiDetMisc.h:597
PMonSD::CmpEntries::operator()
bool operator()(const Entry &a, const Entry &b)
Definition: SemiDetHelper.cxx:487
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:200
PMonSD::SemiDetHelper::startAudOther
void startAudOther(const std::string &compName, const std::string &stepName)
Definition: SemiDetHelper.cxx:280
PMonSD::CmpEntries::CmpEntries
CmpEntries(unsigned ival)
Definition: SemiDetHelper.cxx:486
PMonSD::CompDataStdSteps::index
static int index(const std::string &stepName)
Definition: SemiDetMisc.h:599
PMonSD::SemiDetHelper::stopAudOther
void stopAudOther(const std::string &compName, const std::string &stepName)
Definition: SemiDetHelper.cxx:288
PMonSD::SemiDetHelper::stopAud
void stopAud(const std::string &stepName, const std::string &compName, unsigned val_nevts)
Definition: SemiDetHelper.cxx:123
python.compressB64.c
def c
Definition: compressB64.py:93
updateCoolNtuple.limit
int limit
Definition: updateCoolNtuple.py:45
PMonSD::SemiDetHelper::format
void format(std::ostream &os, const std::string &stepName, const std::string &compName, const CompDataBasic *, bool normal_as_extended=false) const
Definition: SemiDetHelper.cxx:383
PMonSD::SemiDetHelper::report
bool report(const std::string &file, const std::string &info_full_output_inside, bool stdout_uncollapsed)
Definition: SemiDetHelper.cxx:341
PMonSD::CmpEntries::specialsort
static const unsigned specialsort
Definition: SemiDetHelper.cxx:485
PMonSD::SemiDetHelper::m_data_other_lastlookup
MapOtherSteps::iterator m_data_other_lastlookup
Definition: SemiDetHelper.h:115
PMonSD::envvar_is_set
bool envvar_is_set(const char *e)
Definition: SemiDetMisc.h:379
PMonSD::SemiDetHelper::m_malloc_might_get_slow
bool m_malloc_might_get_slow
Definition: SemiDetHelper.h:188
PMonSD::CompDataExtended::maxDeltaCPU
double maxDeltaCPU() const
Definition: SemiDetMisc.h:593
PMonSD::CompDataExtended
Definition: SemiDetMisc.h:157
beamspotman.basename
basename
Definition: beamspotman.py:640