CMS 3D CMS Logo

SimpleMemoryCheck.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Services
4 // Class : Memory
5 //
6 // Implementation:
7 //
8 // Original Author: Jim Kowalkowski
9 //
10 // Change Log
11 //
12 // 1 - Apr 25, 2008 M. Fischler
13 // Collect event summary information and output to XML file and logger
14 // at the end of the job. Involves split-up of updateAndPrint method.
15 //
16 // 2 - May 7, 2008 M. Fischler
17 // Collect module summary information and output to XML file and logger
18 // at the end of the job.
19 //
20 // 3 - Jan 14, 2009 Natalia Garcia Nebot
21 // Added: - Average rate of growth in RSS and peak value attained.
22 // - Average rate of growth in VSize over time, Peak VSize
23 //
24 //
26 
31 
32 
45 
46 #include <cstring>
47 #include <iostream>
48 #include <memory>
49 #ifdef __linux__
50 #include <malloc.h>
51 #endif
52 #include <sstream>
53 //#include <stdio.h>
54 #include <string>
55 //#include <string.h>
56 #include <boost/lexical_cast.hpp>
57 
58 #include <cstdio>
59 #include <atomic>
60 
61 namespace edm {
62  class EventID;
63  class Timestamp;
64 
65  namespace service {
66  struct smapsInfo
67  {
69  smapsInfo(double private_sz, double pss_sz): private_(private_sz),pss_(pss_sz) {}
70 
71  bool operator==(const smapsInfo& p) const
72  { return private_==p.private_ && pss_==p.pss_; }
73 
74  bool operator>(const smapsInfo& p) const
75  { return private_>p.private_ || pss_>p.pss_; }
76 
77  double private_; // in MB
78  double pss_; // in MB
79  };
80 
81 
83  {
84  public:
85 
88 
89  static void fillDescriptions(edm::ConfigurationDescriptions & descriptions);
90 
91  void preSourceConstruction(const ModuleDescription&);
92  void postSourceConstruction(const ModuleDescription&);
93  void postSourceEvent(StreamID);
94 
95  void postBeginJob();
96 
97  void postEvent(StreamContext const&);
98 
99  void postModuleBeginJob(const ModuleDescription&);
100  void postModuleConstruction(const ModuleDescription&);
101 
102  void preModule(StreamContext const&, ModuleCallingContext const&);
103  void postModule(StreamContext const&, ModuleCallingContext const&);
104 
105  void postEndJob();
106 
107  private:
108  ProcInfo fetch();
109  smapsInfo fetchSmaps();
110  double pageSize() const { return pg_size_; }
111  double averageGrowthRate(double current, double past, int count);
112  void update();
113  void updateMax();
114  void andPrint(const std::string& type,
115  const std::string& mdlabel, const std::string& mdname) const;
116  void updateAndPrint(const std::string& type,
117  const std::string& mdlabel, const std::string& mdname);
118  void openFiles();
119 
120  char const* smapsLineBuffer() const {return get_underlying_safe(smapsLineBuffer_);}
121  char*& smapsLineBuffer() {return get_underlying_safe(smapsLineBuffer_);}
122 
128 
130 
132  double pg_size_;
134  //options
139  std::atomic<int> count_;
140 
141  //smaps
145 
146 
147  //Rates of growth
150 
151  // Event summary statistics changeLog 1
153  int count;
154  double vsize;
155  double deltaVsize;
156  double rss;
157  double deltaRss;
159  double privateSize;
160  double pss;
162  SignificantEvent() : count(0), vsize(0), deltaVsize(0),
163  rss(0), deltaRss(0), monitorPssAndPrivate(false), privateSize(0), pss(0),event() {}
164  void set (double deltaV, double deltaR,
165  edm::EventID const & e, SimpleMemoryCheck *t)
166  { count = t->count_;
167  vsize = t->current_->vsize;
168  deltaVsize = deltaV;
169  rss = t->current_->rss;
170  deltaRss = deltaR;
171  monitorPssAndPrivate = t->monitorPssAndPrivate_;
172  if (monitorPssAndPrivate) {
173  privateSize = t->currentSmaps_.private_;
174  pss = t->currentSmaps_.pss_;
175  }
176  event = e;
177  }
178  }; // SignificantEvent
179  friend struct SignificantEvent;
180  friend std::ostream & operator<< (std::ostream & os,
182 
183  /*
184  Significative events for deltaVsize:
185  - eventM_: Event which makes the biggest value for deltaVsize
186  - eventL1_: Event which makes the second biggest value for deltaVsize
187  - eventL2_: Event which makes the third biggest value for deltaVsize
188  - eventR1_: Event which makes the second biggest value for deltaVsize
189  - eventR2_: Event which makes the third biggest value for deltaVsize
190  M>L1>L2 and M>R1>R2
191  Unknown relation between Ls and Rs events ???????
192  Significative events for vsize:
193  - eventT1_: Event whith the biggest value for vsize
194  - eventT2_: Event whith the second biggest value for vsize
195  - eventT3_: Event whith the third biggest value for vsize
196  T1>T2>T3
197  */
206 
207  /*
208  Significative event for deltaRss:
209  - eventRssT1_: Event whith the biggest value for rss
210  - eventRssT2_: Event whith the second biggest value for rss
211  - eventRssT3_: Event whith the third biggest value for rss
212  T1>T2>T3
213  Significative events for deltaRss:
214  - eventDeltaRssT1_: Event whith the biggest value for deltaRss
215  - eventDeltaRssT2_: Event whith the second biggest value for deltaRss
216  - eventDeltaRssT3_: Event whith the third biggest value for deltaRss
217  T1>T2>T3
218  */
225 
226 
227  void updateEventStats(edm::EventID const & e);
228  std::string eventStatOutput(std::string title,
229  SignificantEvent const& e) const;
230  void eventStatOutput(std::string title,
231  SignificantEvent const& e,
232  std::map<std::string, std::string> &m) const;
233  std::string mallOutput(std::string title, size_t const& n) const;
234 
235  // Module summary statistices
243  SignificantModule() : postEarlyCount (0)
244  , totalDeltaVsize (0)
245  , maxDeltaVsize (0)
246  , eventMaxDeltaV ()
247  , totalEarlyVsize (0)
248  , maxEarlyVsize (0) {}
249  void set (double deltaV, bool early);
250  }; // SignificantModule
251  friend struct SignificantModule;
252  friend std::ostream & operator<< (std::ostream & os,
255  typedef std::map<std::string,SignificantModule> SignificantModulesMap;
256  SignificantModulesMap modules_;
258  void updateModuleMemoryStats(SignificantModule & m, double dv, edm::EventID const&);
259 
260  //Used to guarantee we only do one measurement at a time
261  std::atomic<bool> measurementUnderway_;
262  std::atomic<bool> moduleMeasurementUnderway_;
263  std::atomic<unsigned int> moduleStreamID_;
264  std::atomic<unsigned int> moduleID_;
265 
266  }; // SimpleMemoryCheck
267 
268  std::ostream &
269  operator<< (std::ostream & os,
271 
272  std::ostream &
273  operator<< (std::ostream & os,
275 
276  }
277 }
278 
279 
280 
281 
282 #ifdef __linux__
283 #define LINUX 1
284 #endif
285 
286 #include <fcntl.h>
287 #include <unistd.h>
288 
289 namespace edm {
290  namespace service {
291 
292  static std::string d2str(double d) {
293  std::ostringstream t;
294  t << d;
295  return t.str();
296  }
297 
298  static std::string i2str(int i) {
299  std::ostringstream t;
300  t << i;
301  return t.str();
302  }
303 
305  return piFetcher_.fetch();
306  }
307 
309  smapsInfo ret;
310  ret.private_ = 0;
311  ret.pss_ = 0;
312 #ifdef LINUX
313  fseek(smapsFile_, 0, SEEK_SET);
314  ssize_t read;
315 
316  /*
317  The format of the report is
318  Private_Clean: 0 kB
319  Private_Dirty: 72 kB
320  Swap: 0 kB
321  Pss: 72 kB
322  */
323 
324  while ((read = getline(&smapsLineBuffer(), &smapsLineBufferLen_, smapsFile_)) != -1) {
325  if(read > 14) {
326  //Private
327  if(0==strncmp("Private_",smapsLineBuffer_,8)) {
328  unsigned int value = atoi(smapsLineBuffer_+14);
329  //Convert from kB to MB
330  ret.private_ += static_cast<double>(value)/1024.;
331  } else if(0==strncmp("Pss:",smapsLineBuffer_,4)) {
332  unsigned int value = atoi(smapsLineBuffer_+4);
333  //Convert from kB to MB
334  ret.pss_ += static_cast<double>(value)/1024.;
335  }
336  }
337  }
338 #endif
339  return ret;
340  }
341 
342  double SimpleMemoryCheck::averageGrowthRate(double current, double past, int count) {
343  return(current-past)/(double)count;
344  }
345 
347  ActivityRegistry&iReg)
348  : a_()
349  , b_()
350  , current_(&a_)
351  , previous_(&b_)
352  , pg_size_(sysconf(_SC_PAGESIZE)) // getpagesize()
353  , num_to_skip_(iPS.getUntrackedParameter<int>("ignoreTotal"))
354  , showMallocInfo_(iPS.getUntrackedParameter<bool>("showMallocInfo"))
355  , oncePerEventMode_(iPS.getUntrackedParameter<bool>("oncePerEventMode"))
356  , jobReportOutputOnly_(iPS.getUntrackedParameter<bool>("jobReportOutputOnly"))
357  , monitorPssAndPrivate_(iPS.getUntrackedParameter<bool>("monitorPssAndPrivate"))
358  , count_()
359  , smapsFile_(nullptr)
360  , smapsLineBuffer_(nullptr)
361  , smapsLineBufferLen_(0)
362  , growthRateVsize_()
363  , growthRateRss_()
364  , moduleSummaryRequested_(iPS.getUntrackedParameter<bool>("moduleMemorySummary"))
365  , measurementUnderway_(false){
366  // changelog 2
367  // pg_size = (double)getpagesize();
368  std::ostringstream ost;
369 
370  openFiles();
371 
372  if(!oncePerEventMode_) { // default, prints on increases
382  } else {
385  }
386  if(moduleSummaryRequested_) { // changelog 2
388  if(oncePerEventMode_) {
390  }
391  }
392 
393  // The following are not currenty used/implemented below for either
394  // of the print modes (but are left here for reference)
395  // iReg.watchPostBeginJob(this,
396  // &SimpleMemoryCheck::postBeginJob);
397  // iReg.watchPreProcessEvent(this,
398  // &SimpleMemoryCheck::preEventProcessing);
399  // iReg.watchPreModule(this,
400  // &SimpleMemoryCheck::preModule);
401 
402 #ifndef __SANITIZE_ADDRESS__
403  typedef MallocOpts::opt_type opt_type;
405 
406  opt_type
407  p_mmap_max = iPS.getUntrackedParameter<int>("M_MMAP_MAX"),
408  p_trim_thr = iPS.getUntrackedParameter<int>("M_TRIM_THRESHOLD"),
409  p_top_pad = iPS.getUntrackedParameter<int>("M_TOP_PAD"),
410  p_mmap_thr = iPS.getUntrackedParameter<int>("M_MMAP_THRESHOLD");
411 
412  if(p_mmap_max >= 0) mopts.set_mmap_max(p_mmap_max);
413  if(p_trim_thr >= 0) mopts.set_trim_thr(p_trim_thr);
414  if(p_top_pad >= 0) mopts.set_top_pad(p_top_pad);
415  if(p_mmap_thr >= 0) mopts.set_mmap_thr(p_mmap_thr);
416 
417  mopts.adjustMallocParams();
418 
419  if(mopts.hasErrors()) {
420  LogWarning("MemoryCheck")
421  << "ERROR: Problem with setting malloc options\n"
422  << mopts.error_message();
423  }
424 
425  if(iPS.getUntrackedParameter<bool>("dump") == true) {
426  MallocOpts mo = mopts.get();
427  LogWarning("MemoryCheck")
428  << "Malloc options: " << mo << "\n";
429  }
430 #endif
431  }
432 
434 #ifdef LINUX
435  if(0 != smapsFile_) {
436  fclose(smapsFile_);
437  }
438 #endif
439  if (smapsLineBuffer_) {
440  //getline will create the memory using malloc
441  free(smapsLineBuffer_);
442  }
443  }
444 
447  desc.addUntracked<int>("ignoreTotal", 1);
448  desc.addUntracked<bool>("showMallocInfo", false);
449  desc.addUntracked<bool>("oncePerEventMode", false);
450  desc.addUntracked<bool>("jobReportOutputOnly", false);
451  desc.addUntracked<bool>("monitorPssAndPrivate", false);
452  desc.addUntracked<bool>("moduleMemorySummary", false);
453  desc.addUntracked<int>("M_MMAP_MAX", -1);
454  desc.addUntracked<int>("M_TRIM_THRESHOLD", -1);
455  desc.addUntracked<int>("M_TOP_PAD", -1);
456  desc.addUntracked<int>("M_MMAP_THRESHOLD", -1);
457  desc.addUntracked<bool>("dump", false);
458  descriptions.add("SimpleMemoryCheck", desc);
459  }
460 
462 #ifdef LINUX
463  if (monitorPssAndPrivate_) {
464  std::ostringstream smapsNameOst;
465  smapsNameOst <<"/proc/"<<getpid()<<"/smaps";
466  if((smapsFile_ =fopen(smapsNameOst.str().c_str(), "r"))==0) {
467  throw Exception(errors::Configuration) <<"Failed to open smaps file "<<smapsNameOst.str()<<std::endl;
468  }
469  }
470 #endif
471  }
472 
474  growthRateVsize_ = current_->vsize;
475  growthRateRss_ = current_->rss;
476  }
477 
479  bool expected = false;
480  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
481  std::shared_ptr<void> guard(nullptr,[this](void const*) {
482  measurementUnderway_.store(false,std::memory_order_release);
483  });
484  updateAndPrint("pre-ctor", md.moduleLabel(), md.moduleName());
485  }
486  }
487 
488 
490  bool expected = false;
491  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
492  std::shared_ptr<void> guard(nullptr,[this](void const*) {
493  measurementUnderway_.store(false,std::memory_order_release);
494  });
495  updateAndPrint("ctor", md.moduleLabel(), md.moduleName());
496  }
497  }
498 
500  bool expected = false;
501  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
502  std::shared_ptr<void> guard(nullptr,[this](void const*) {
503  measurementUnderway_.store(false,std::memory_order_release);
504  });
505  updateAndPrint("module", "source", "source");
506  }
507  }
508 
510  bool expected = false;
511  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
512  std::shared_ptr<void> guard(nullptr,[this](void const*) {
513  measurementUnderway_.store(false,std::memory_order_release);
514  });
515  updateAndPrint("ctor", md.moduleLabel(), md.moduleName());
516  }
517  }
518 
520  bool expected = false;
521  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
522  std::shared_ptr<void> guard(nullptr,[this](void const*) {
523  measurementUnderway_.store(false,std::memory_order_release);
524  });
525  updateAndPrint("beginJob", md.moduleLabel(), md.moduleName());
526  }
527  }
528 
530  if(not jobReportOutputOnly_) {
531  LogAbsolute("MemoryReport") // changelog 1
532  << "MemoryReport> Peak virtual size " << eventT1_.vsize << " Mbytes"
533  << "\n"
534  << " Key events increasing vsize: \n"
535  << eventL2_ << "\n"
536  << eventL1_ << "\n"
537  << eventM_ << "\n"
538  << eventR1_ << "\n"
539  << eventR2_ << "\n"
540  << eventT3_ << "\n"
541  << eventT2_ << "\n"
542  << eventT1_ ;
543  }
544  if(moduleSummaryRequested_ and not jobReportOutputOnly_) { // changelog 1
545  LogAbsolute mmr("ModuleMemoryReport"); // at end of if block, mmr
546  // is destructed, causing
547  // message to be logged
548  mmr << "ModuleMemoryReport> Each line has module label and: \n";
549  mmr << " (after early ignored events) \n";
550  mmr <<
551  " count of times module executed; average increase in vsize \n";
552  mmr <<
553  " maximum increase in vsize; event on which maximum occurred \n";
554  mmr << " (during early ignored events) \n";
555  mmr << " total and maximum vsize increases \n \n";
556  for(SignificantModulesMap::iterator im = modules_.begin();
557  im != modules_.end(); ++im) {
558  SignificantModule const& m = im->second;
559  if(m.totalDeltaVsize == 0 && m.totalEarlyVsize == 0) continue;
560  mmr << im->first << ": ";
561  mmr << "n = " << m.postEarlyCount;
562  if(m.postEarlyCount > 0) {
563  mmr << " avg = " << m.totalDeltaVsize/m.postEarlyCount;
564  }
565  mmr << " max = " << m.maxDeltaVsize << " " << m.eventMaxDeltaV;
566  if(m.totalEarlyVsize > 0) {
567  mmr << " early total: " << m.totalEarlyVsize;
568  mmr << " max: " << m.maxEarlyVsize;
569  }
570  mmr << "\n";
571  }
572  } // end of if; mmr goes out of scope; log message is queued
573 
574  Service<JobReport> reportSvc;
575  // changelog 1
576 #define SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
577 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
578 // std::map<std::string, double> reportData;
579  std::map<std::string, std::string> reportData;
580 
581  if(eventL2_.vsize > 0)
582  eventStatOutput("LargeVsizeIncreaseEventL2", eventL2_, reportData);
583  if(eventL1_.vsize > 0)
584  eventStatOutput("LargeVsizeIncreaseEventL1", eventL1_, reportData);
585  if(eventM_.vsize > 0)
586  eventStatOutput("LargestVsizeIncreaseEvent", eventM_, reportData);
587  if(eventR1_.vsize > 0)
588  eventStatOutput("LargeVsizeIncreaseEventR1", eventR1_, reportData);
589  if(eventR2_.vsize > 0)
590  eventStatOutput("LargeVsizeIncreaseEventR2", eventR2_, reportData);
591  if(eventT3_.vsize > 0)
592  eventStatOutput("ThirdLargestVsizeEventT3", eventT3_, reportData);
593  if(eventT2_.vsize > 0)
594  eventStatOutput("SecondLargestVsizeEventT2", eventT2_, reportData);
595  if(eventT1_.vsize > 0)
596  eventStatOutput("LargestVsizeEventT1", eventT1_, reportData);
597 
598  if(eventRssT3_.rss > 0)
599  eventStatOutput("ThirdLargestRssEvent", eventRssT3_, reportData);
600  if(eventRssT2_.rss > 0)
601  eventStatOutput("SecondLargestRssEvent", eventRssT2_, reportData);
602  if(eventRssT1_.rss > 0)
603  eventStatOutput("LargestRssEvent", eventRssT1_, reportData);
604  if(eventDeltaRssT3_.deltaRss > 0)
605  eventStatOutput("ThirdLargestIncreaseRssEvent", eventDeltaRssT3_, reportData);
606  if(eventDeltaRssT2_.deltaRss > 0)
607  eventStatOutput("SecondLargestIncreaseRssEvent", eventDeltaRssT2_, reportData);
608  if(eventDeltaRssT1_.deltaRss > 0)
609  eventStatOutput("LargestIncreaseRssEvent", eventDeltaRssT1_, reportData);
610 
611 #ifdef __linux__
612  struct mallinfo minfo = mallinfo();
613  reportData.insert(
614  std::make_pair("HEAP_ARENA_SIZE_BYTES", i2str(minfo.arena)));
615  reportData.insert(
616  std::make_pair("HEAP_ARENA_N_UNUSED_CHUNKS", i2str(minfo.ordblks)));
617  reportData.insert(
618  std::make_pair("HEAP_TOP_FREE_BYTES", i2str(minfo.keepcost)));
619  reportData.insert(
620  std::make_pair("HEAP_MAPPED_SIZE_BYTES", i2str(minfo.hblkhd)));
621  reportData.insert(
622  std::make_pair("HEAP_MAPPED_N_CHUNKS", i2str(minfo.hblks)));
623  reportData.insert(
624  std::make_pair("HEAP_USED_BYTES", i2str(minfo.uordblks)));
625  reportData.insert(
626  std::make_pair("HEAP_UNUSED_BYTES", i2str(minfo.fordblks)));
627 #endif
628 
629  // Report Growth rates for VSize and Rss
630  reportData.insert(
631  std::make_pair("AverageGrowthRateVsize", d2str(averageGrowthRate(current_->vsize, growthRateVsize_, count_))));
632  reportData.insert(
633  std::make_pair("PeakValueVsize", d2str(eventT1_.vsize)));
634  reportData.insert(
635  std::make_pair("AverageGrowthRateRss", d2str(averageGrowthRate(current_->rss, growthRateRss_, count_))));
636  reportData.insert(
637  std::make_pair("PeakValueRss", d2str(eventRssT1_.rss)));
638 
639  if(moduleSummaryRequested_) { // changelog 2
640  for(SignificantModulesMap::iterator im = modules_.begin();
641  im != modules_.end(); ++im) {
642  SignificantModule const& m = im->second;
643  if(m.totalDeltaVsize == 0 && m.totalEarlyVsize == 0) continue;
644  std::string label = im->first+":";
645  reportData.insert(std::make_pair(label+"PostEarlyCount", i2str(m.postEarlyCount)));
646  if(m.postEarlyCount > 0) {
647  reportData.insert(std::make_pair(label+"AverageDeltaVsize",
649  }
650  reportData.insert(std::make_pair(label+"MaxDeltaVsize", d2str(m.maxDeltaVsize)));
651  if(m.totalEarlyVsize > 0) {
652  reportData.insert(std::make_pair(label+"TotalEarlyVsize", d2str(m.totalEarlyVsize)));
653  reportData.insert(std::make_pair(label+"MaxEarlyDeltaVsize", d2str(m.maxEarlyVsize)));
654  }
655  }
656  }
657 
658  std::map<std::string, std::string> reportMemoryProperties;
659 
660  if(FILE* fmeminfo = fopen("/proc/meminfo", "r")) {
661  char buf[128];
662  char space[] = " ";
663  size_t value;
664 
665  while(fgets(buf, sizeof(buf), fmeminfo)) {
666  char* token = nullptr;
667  token = strtok(buf, space);
668  if(token != nullptr) {
669  value = atol(strtok(nullptr, space));
670  std::string category = token;
671  reportMemoryProperties.insert(std::make_pair(category.substr(0, strlen(token)-1), i2str(value)));
672  }
673  }
674 
675  fclose(fmeminfo);
676  }
677 
678 // reportSvc->reportMemoryInfo(reportData, reportMemoryProperties);
679  reportSvc->reportPerformanceSummary("ApplicationMemory", reportData);
680  reportSvc->reportPerformanceSummary("SystemMemory", reportMemoryProperties);
681 #endif
682 
683 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT
684  std::vector<std::string> reportData;
685 
686  if(eventL2_.vsize > 0) reportData.push_back(
687  eventStatOutput("LargeVsizeIncreaseEventL2", eventL2_));
688  if(eventL1_.vsize > 0) reportData.push_back(
689  eventStatOutput("LargeVsizeIncreaseEventL1", eventL1_));
690  if(eventM_.vsize > 0) reportData.push_back(
691  eventStatOutput("LargestVsizeIncreaseEvent", eventM_));
692  if(eventR1_.vsize > 0) reportData.push_back(
693  eventStatOutput("LargeVsizeIncreaseEventR1", eventR1_));
694  if(eventR2_.vsize > 0) reportData.push_back(
695  eventStatOutput("LargeVsizeIncreaseEventR2", eventR2_));
696  if(eventT3_.vsize > 0) reportData.push_back(
697  eventStatOutput("ThirdLargestVsizeEventT3", eventT3_));
698  if(eventT2_.vsize > 0) reportData.push_back(
699  eventStatOutput("SecondLargestVsizeEventT2", eventT2_));
700  if(eventT1_.vsize > 0) reportData.push_back(
701  eventStatOutput("LargestVsizeEventT1", eventT1_));
702 
703  if(eventRssT3_.rss > 0)
704  eventStatOutput("ThirdLargestRssEvent", eventRssT3_, reportData);
705  if(eventRssT2_.rss > 0)
706  eventStatOutput("SecondLargestRssEvent", eventRssT2_, reportData);
707  if(eventRssT1_.rss > 0)
708  eventStatOutput("LargestRssEvent", eventRssT1_, reportData);
709  if(eventDeltaRssT3_.deltaRss > 0)
710  eventStatOutput("ThirdLargestIncreaseRssEvent", eventDeltaRssT3_, reportData);
711  if(eventDeltaRssT2_.deltaRss > 0)
712  eventStatOutput("SecondLargestIncreaseRssEvent", eventDeltaRssT2_, reportData);
713  if(eventDeltaRssT1_.deltaRss > 0)
714  eventStatOutput("LargestIncreaseRssEvent", eventDeltaRssT1_, reportData);
715 
716  struct mallinfo minfo = mallinfo();
717  reportData.push_back(
718  mallOutput("HEAP_ARENA_SIZE_BYTES", minfo.arena));
719  reportData.push_back(
720  mallOutput("HEAP_ARENA_N_UNUSED_CHUNKS", minfo.ordblks));
721  reportData.push_back(
722  mallOutput("HEAP_TOP_FREE_BYTES", minfo.keepcost));
723  reportData.push_back(
724  mallOutput("HEAP_MAPPED_SIZE_BYTES", minfo.hblkhd));
725  reportData.push_back(
726  mallOutput("HEAP_MAPPED_N_CHUNKS", minfo.hblks));
727  reportData.push_back(
728  mallOutput("HEAP_USED_BYTES", minfo.uordblks));
729  reportData.push_back(
730  mallOutput("HEAP_UNUSED_BYTES", minfo.fordblks));
731 
732  // Report Growth rates for VSize and Rss
733  reportData.insert(
734  std::make_pair("AverageGrowthRateVsize", d2str(averageGrowthRate(current_->vsize, growthRateVsize_, count_))));
735  reportData.insert(
736  std::make_pair("PeakValueVsize", d2str(eventT1_.vsize)));
737  reportData.insert(
738  std::make_pair("AverageGrowthRateRss", d2str(averageGrowthRate(current_->rss, growthRateRss_, count_))));
739  reportData.insert(
740  std::make_pair("PeakValueRss", d2str(eventRssT1_.rss)));
741 
742  reportSvc->reportMemoryInfo(reportData);
743  // This is a form of reportMemoryInfo taking s vector, not a map
744 #endif
745  } // postEndJob
746 
748  ++count_;
749  bool expected = false;
750  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
751  std::shared_ptr<void> guard(nullptr,[this](void const*) {
752  measurementUnderway_.store(false,std::memory_order_release);
753  });
754  update();
755  if (monitorPssAndPrivate_) {
757  }
758  updateEventStats(iContext.eventID());
759  if(oncePerEventMode_) {
760  // should probably use be Run:Event or count_ for the label and name
761  updateMax();
762  andPrint("event", "", "");
763  }
764  }
765  }
766 
767  void SimpleMemoryCheck::preModule(StreamContext const& iStreamContext, ModuleCallingContext const& iModuleContext) {
768  bool expected = false;
769  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
770  std::shared_ptr<void> guard(nullptr,[this](void const*) {
771  measurementUnderway_.store(false,std::memory_order_release);
772  });
773  bool expected = false;
774  if(moduleMeasurementUnderway_.compare_exchange_strong(expected,true) ) {
775  update();
776  // changelog 2
777  moduleEntryVsize_ = current_->vsize;
778  moduleStreamID_.store(iStreamContext.streamID().value(), std::memory_order_release);
779  moduleID_.store(iModuleContext.moduleDescription()->id(),std::memory_order_release);
780  }
781  }
782  }
783 
784  void SimpleMemoryCheck::postModule(StreamContext const& iStreamContext, ModuleCallingContext const& iModuleContext) {
785  if(!oncePerEventMode_) {
786  bool expected = false;
787  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
788  std::shared_ptr<void> guard(nullptr,[this](void const*) {
789  measurementUnderway_.store(false,std::memory_order_release);
790  });
791  auto const md = iModuleContext.moduleDescription();
792  updateAndPrint("module", md->moduleLabel(), md->moduleName());
793  }
794  }
795 
797  //is this the module instance we are measuring?
798  if(moduleMeasurementUnderway_.load(std::memory_order_acquire) and
799  (iStreamContext.streamID().value()==moduleStreamID_.load(std::memory_order_acquire) ) and
800  (iModuleContext.moduleDescription()->id() == moduleID_.load(std::memory_order_acquire))) {
801  //Need to release our module measurement lock
802  std::shared_ptr<void> guard(nullptr,[this](void const*) {
803  moduleMeasurementUnderway_.store(false,std::memory_order_release);
804  });
805  bool expected = false;
806  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
807  std::shared_ptr<void> guard(nullptr,[this](void const*) {
808  measurementUnderway_.store(false,std::memory_order_release);
809  });
810  if(oncePerEventMode_) {
811  update();
812  }
813  // changelog 2
814  double dv = current_->vsize - moduleEntryVsize_;
815  std::string label = iModuleContext.moduleDescription()->moduleLabel();
816  updateModuleMemoryStats (modules_[label], dv, iStreamContext.eventID());
817  }
818  }
819  }
820  }
821 
824  *current_ = fetch();
825  }
826 
828  if((*current_ > max_) || oncePerEventMode_) {
829  if(count_ >= num_to_skip_) {
830  }
831  max_ = *current_;
832  }
833  }
834 
836  if(count_ < num_to_skip_) return;
837  if(count_ == num_to_skip_) {
838  eventT1_.set(0, 0, e, this);
839  eventM_.set (0, 0, e, this);
840  eventRssT1_.set(0, 0, e, this);
841  eventDeltaRssT1_.set(0, 0, e, this);
842  return;
843  }
844  double vsize = current_->vsize;
845  double deltaVsize = vsize - eventT1_.vsize;
846 
847  // Update significative events for Vsize
848  if(vsize > eventT1_.vsize) {
849  double deltaRss = current_->rss - eventT1_.rss;
850  eventT3_ = eventT2_;
851  eventT2_ = eventT1_;
852  eventT1_.set(deltaVsize, deltaRss, e, this);
853  } else if(vsize > eventT2_.vsize) {
854  double deltaRss = current_->rss - eventT1_.rss;
855  eventT3_ = eventT2_;
856  eventT2_.set(deltaVsize, deltaRss, e, this);
857  } else if(vsize > eventT3_.vsize) {
858  double deltaRss = current_->rss - eventT1_.rss;
859  eventT3_.set(deltaVsize, deltaRss, e, this);
860  }
861 
862  if(deltaVsize > eventM_.deltaVsize) {
863  double deltaRss = current_->rss - eventM_.rss;
865  eventL2_ = eventL1_;
866  } else {
867  eventL2_ = eventR1_;
868  }
869  eventL1_ = eventM_;
870  eventM_.set(deltaVsize, deltaRss, e, this);
873  } else if(deltaVsize > eventR1_.deltaVsize) {
874  double deltaRss = current_->rss - eventM_.rss;
875  eventR2_ = eventR1_;
876  eventR1_.set(deltaVsize, deltaRss, e, this);
877  } else if(deltaVsize > eventR2_.deltaVsize) {
878  double deltaRss = current_->rss - eventR1_.rss;
879  eventR2_.set(deltaVsize, deltaRss, e, this);
880  }
881 
882  // Update significative events for Rss
883  double rss = current_->rss;
884  double deltaRss = rss - eventRssT1_.rss;
885 
886  if(rss > eventRssT1_.rss) {
889  eventRssT1_.set(deltaVsize, deltaRss, e, this);
890  } else if(rss > eventRssT2_.rss) {
892  eventRssT2_.set(deltaVsize, deltaRss, e, this);
893  } else if(rss > eventRssT3_.rss) {
894  eventRssT3_.set(deltaVsize, deltaRss, e, this);
895  }
896  if(deltaRss > eventDeltaRssT1_.deltaRss) {
899  eventDeltaRssT1_.set(deltaVsize, deltaRss, e, this);
900  } else if(deltaRss > eventDeltaRssT2_.deltaRss) {
902  eventDeltaRssT2_.set(deltaVsize, deltaRss, e, this);
903  } else if(deltaRss > eventDeltaRssT3_.deltaRss) {
904  eventDeltaRssT3_.set(deltaVsize, deltaRss, e, this);
905  }
906  } // updateEventStats
907 
909  std::string const& mdlabel, std::string const& mdname) const {
910  if(not jobReportOutputOnly_ && ((*current_ > max_) || oncePerEventMode_)) {
911  if(count_ >= num_to_skip_) {
912  double deltaVSIZE = current_->vsize - max_.vsize;
913  double deltaRSS = current_->rss - max_.rss;
914  if(!showMallocInfo_) { // default
915  LogWarning("MemoryCheck")
916  << "MemoryCheck: " << type << " "
917  << mdname << ":" << mdlabel
918  << " VSIZE " << current_->vsize << " " << deltaVSIZE
919  << " RSS " << current_->rss << " " << deltaRSS;
920  } else {
921 #ifdef __linux__
922  struct mallinfo minfo = mallinfo();
923 #endif
924  LogWarning("MemoryCheck")
925  << "MemoryCheck: " << type << " "
926  << mdname << ":" << mdlabel
927  << " VSIZE " << current_->vsize << " " << deltaVSIZE
928  << " RSS " << current_->rss << " " << deltaRSS
929 #ifdef __linux__
930  << " HEAP-ARENA [ SIZE-BYTES " << minfo.arena
931  << " N-UNUSED-CHUNKS " << minfo.ordblks
932  << " TOP-FREE-BYTES " << minfo.keepcost << " ]"
933  << " HEAP-MAPPED [ SIZE-BYTES " << minfo.hblkhd
934  << " N-CHUNKS " << minfo.hblks << " ]"
935  << " HEAP-USED-BYTES " << minfo.uordblks
936  << " HEAP-UNUSED-BYTES " << minfo.fordblks
937 #endif
938  ;
939  }
940  }
941  }
942  }
943 
945  std::string const& mdlabel, std::string const& mdname) {
946  update();
947  andPrint(type, mdlabel, mdname);
948  updateMax();
949  }
950 
951 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
952  void
954  SignificantEvent const& e,
955  std::map<std::string, std::string>& m) const {
956  { std::ostringstream os;
957  os << title << "-a-COUNT";
958  m.insert(std::make_pair(os.str(), i2str(e.count))); }
959  { std::ostringstream os;
960  os << title << "-b-RUN";
961  m.insert(std::make_pair(os.str(), d2str(static_cast<double>(e.event.run())))); }
962  { std::ostringstream os;
963  os << title << "-c-EVENT";
964  m.insert(std::make_pair(os.str(), d2str(static_cast<double>(e.event.event())))); }
965  { std::ostringstream os;
966  os << title << "-d-VSIZE";
967  m.insert(std::make_pair(os.str(), d2str(e.vsize))); }
968  { std::ostringstream os;
969  os << title << "-e-DELTV";
970  m.insert(std::make_pair(os.str(), d2str(e.deltaVsize))); }
971  { std::ostringstream os;
972  os << title << "-f-RSS";
973  m.insert(std::make_pair(os.str(), d2str(e.rss))); }
974  if (monitorPssAndPrivate_) {
975  { std::ostringstream os;
976  os << title << "-g-PRIVATE";
977  m.insert(std::make_pair(os.str(), d2str(e.privateSize))); }
978  { std::ostringstream os;
979  os << title << "-h-PSS";
980  m.insert(std::make_pair(os.str(), d2str(e.pss))); }
981  }
982  } // eventStatOutput
983 #endif
984 
985 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT
988  SignificantEvent const& e) const {
989  std::ostringstream os;
990  os << " <" << title << ">\n";
991  os << " " << e.count << ": " << e.event;
992  os << " vsize " << e.vsize-e.deltaVsize << " + " << e.deltaVsize
993  << " = " << e.vsize;
994  os << " rss: " << e.rss << "\n";
995  os << " </" << title << ">\n";
996  return os.str();
997  } // eventStatOutput
998 
1000  SimpleMemoryCheck::mallOutput(std::string title, size_t const& n) const {
1001  std::ostringstream os;
1002  os << " <" << title << ">\n";
1003  os << " " << n << "\n";
1004  os << " </" << title << ">\n";
1005  return os.str();
1006  }
1007 #endif
1008  // changelog 2
1009  void
1011  double dv, edm::EventID const& currentEventID) {
1012  if(count_ < num_to_skip_) {
1013  m.totalEarlyVsize += dv;
1014  if(dv > m.maxEarlyVsize) m.maxEarlyVsize = dv;
1015  } else {
1016  ++m.postEarlyCount;
1017  m.totalDeltaVsize += dv;
1018  if(dv > m.maxDeltaVsize) {
1019  m.maxDeltaVsize = dv;
1020  m.eventMaxDeltaV = currentEventID;
1021  }
1022  }
1023  } //updateModuleMemoryStats
1024 
1025  std::ostream&
1026  operator<< (std::ostream& os,
1028  os << "[" << se.count << "] "
1029  << se.event << " vsize = " << se.vsize
1030  << " deltaVsize = " << se.deltaVsize
1031  << " rss = " << se.rss << " delta = " << se.deltaRss;
1032 
1033  if (se.monitorPssAndPrivate) {
1034  os <<" private = "<<se.privateSize<<" pss = "<<se.pss;
1035  }
1036  return os;
1037  }
1038 
1039  std::ostream&
1040  operator<< (std::ostream& os,
1042  if(sm.postEarlyCount > 0) {
1043  os << "\nPost Early Events: TotalDeltaVsize: " << sm.totalDeltaVsize
1044  << " (avg: " << sm.totalDeltaVsize/sm.postEarlyCount
1045  << "; max: " << sm.maxDeltaVsize
1046  << " during " << sm.eventMaxDeltaV << ")";
1047  }
1048  if(sm.totalEarlyVsize > 0) {
1049  os << "\n Early Events: TotalDeltaVsize: " << sm.totalEarlyVsize
1050  << " (max: " << sm.maxEarlyVsize << ")";
1051  }
1052 
1053  return os;
1054  }
1055 
1056  } // end namespace service
1057 } // end namespace edm
1058 
1059 
1060 #if defined(__linux__)
1063 #endif
1064 
RunNumber_t run() const
Definition: EventID.h:39
void watchPostModuleConstruction(PostModuleConstruction::slot_type const &iSlot)
MallocOpts get() const
Definition: MallocOpts.h:84
std::map< std::string, SignificantModule > SignificantModulesMap
type
Definition: HCALResponse.h:21
EventNumber_t event() const
Definition: EventID.h:41
T getUntrackedParameter(std::string const &, T const &) const
void set_trim_thr(opt_type trim_thr)
Definition: MallocOpts.h:77
static std::string i2str(int i)
std::string eventStatOutput(std::string title, SignificantEvent const &e) const
void preSourceConstruction(const ModuleDescription &)
void set_mmap_max(opt_type mmap_max)
Definition: MallocOpts.h:75
friend std::ostream & operator<<(std::ostream &os, SimpleMemoryCheck::SignificantEvent const &se)
bool hasErrors() const
Definition: MallocOpts.h:72
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
void watchPostEndJob(PostEndJob::slot_type const &iSlot)
edm::propagate_const< ProcInfo * > current_
std::atomic< bool > measurementUnderway_
void set_mmap_thr(opt_type mmap_thr)
Definition: MallocOpts.h:81
void watchPreModuleEvent(PreModuleEvent::slot_type const &iSlot)
void updateEventStats(edm::EventID const &e)
void watchPostEvent(PostEvent::slot_type const &iSlot)
std::atomic< bool > moduleMeasurementUnderway_
void watchPreSourceConstruction(PreSourceConstruction::slot_type const &iSlot)
void watchPostSourceConstruction(PostSourceConstruction::slot_type const &iSlot)
std::string const & moduleName() const
void watchPostModuleEvent(PostModuleEvent::slot_type const &iSlot)
void watchPostSourceEvent(PostSourceEvent::slot_type const &iSlot)
#define nullptr
std::string const & moduleLabel() const
void andPrint(const std::string &type, const std::string &mdlabel, const std::string &mdname) const
std::atomic< unsigned int > moduleStreamID_
edm::propagate_const< FILE * > smapsFile_
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
ModuleDescription const * moduleDescription() const
char const * smapsLineBuffer() const
std::shared_ptr< T > & get_underlying_safe(propagate_const< std::shared_ptr< T >> &iP)
Definition: value.py:1
std::ostream & operator<<(std::ostream &os, SimpleMemoryCheck::SignificantEvent const &se)
void set(double deltaV, double deltaR, edm::EventID const &e, SimpleMemoryCheck *t)
edm::propagate_const< ProcInfo * > previous_
StreamID const & streamID() const
Definition: StreamContext.h:57
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
smapsInfo(double private_sz, double pss_sz)
#define DEFINE_FWK_SERVICE(type)
Definition: ServiceMaker.h:113
void updateAndPrint(const std::string &type, const std::string &mdlabel, const std::string &mdname)
bool operator==(const smapsInfo &p) const
unsigned int value() const
Definition: StreamID.h:46
void preModule(StreamContext const &, ModuleCallingContext const &)
static std::string d2str(double d)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void updateModuleMemoryStats(SignificantModule &m, double dv, edm::EventID const &)
std::string error_message() const
Definition: MallocOpts.h:73
void postEvent(StreamContext const &)
HLT enums.
std::string mallOutput(std::string title, size_t const &n) const
#define update(a, b)
edm::propagate_const< char * > smapsLineBuffer_
void watchPostModuleBeginJob(PostModuleBeginJob::slot_type const &iSlot)
void postSourceConstruction(const ModuleDescription &)
EventID const & eventID() const
Definition: StreamContext.h:59
void postModuleBeginJob(const ModuleDescription &)
double averageGrowthRate(double current, double past, int count)
void set_top_pad(opt_type top_pad)
Definition: MallocOpts.h:79
SimpleMemoryCheck(const ParameterSet &, ActivityRegistry &)
void postModule(StreamContext const &, ModuleCallingContext const &)
std::pair< std::string, std::shared_ptr< void > > fetch(const cond::Hash &payloadId, Session &session)
Definition: CondDBFetch.cc:327
void postModuleConstruction(const ModuleDescription &)
bool operator>(const smapsInfo &p) const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
MallocOptionSetter & getGlobalOptionSetter()
Definition: MallocOpts.cc:221
unsigned int id() const
void watchPostBeginJob(PostBeginJob::slot_type const &iSlot)
convenience function for attaching to signal
std::atomic< unsigned int > moduleID_