CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Memory.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 //
25 
27 
39 
40 #include <cstring>
41 #include <iostream>
42 #include <memory>
43 #ifdef __linux__
44 #include <malloc.h>
45 #endif
46 #include <sstream>
47 //#include <stdio.h>
48 #include <string>
49 //#include <string.h>
50 #include <boost/lexical_cast.hpp>
51 
52 #ifdef __linux__
53 #define LINUX 1
54 #endif
55 
56 #include <fcntl.h>
57 #include <unistd.h>
58 
59 namespace edm {
60  namespace service {
61 
62  static std::string d2str(double d) {
63  std::ostringstream t;
64  t << d;
65  return t.str();
66  }
67 
68  static std::string i2str(int i) {
69  std::ostringstream t;
70  t << i;
71  return t.str();
72  }
73 
75  return piFetcher_.fetch();
76  }
77 
79  smapsInfo ret;
80  ret.private_ = 0;
81  ret.pss_ = 0;
82 #ifdef LINUX
83  fseek(smapsFile_, 0, SEEK_SET);
84  ssize_t read;
85 
86  /*
87  The format of the report is
88  Private_Clean: 0 kB
89  Private_Dirty: 72 kB
90  Swap: 0 kB
91  Pss: 72 kB
92  */
93 
94  while ((read = getline(&smapsLineBuffer_, &smapsLineBufferLen_, smapsFile_)) != -1) {
95  if(read > 14) {
96  //Private
97  if(0==strncmp("Private_",smapsLineBuffer_,8)) {
98  unsigned int value = atoi(smapsLineBuffer_+14);
99  //Convert from kB to MB
100  ret.private_ += static_cast<double>(value)/1024.;
101  } else if(0==strncmp("Pss:",smapsLineBuffer_,4)) {
102  unsigned int value = atoi(smapsLineBuffer_+4);
103  //Convert from kB to MB
104  ret.pss_ += static_cast<double>(value)/1024.;
105  }
106  }
107  }
108 #endif
109  return ret;
110  }
111 
112  double SimpleMemoryCheck::averageGrowthRate(double current, double past, int count) {
113  return(current-past)/(double)count;
114  }
115 
117  ActivityRegistry&iReg)
118  : a_()
119  , b_()
120  , current_(&a_)
121  , previous_(&b_)
122  , pg_size_(sysconf(_SC_PAGESIZE)) // getpagesize()
123  , num_to_skip_(iPS.getUntrackedParameter<int>("ignoreTotal"))
124  , showMallocInfo_(iPS.getUntrackedParameter<bool>("showMallocInfo"))
125  , oncePerEventMode_(iPS.getUntrackedParameter<bool>("oncePerEventMode"))
126  , jobReportOutputOnly_(iPS.getUntrackedParameter<bool>("jobReportOutputOnly"))
127  , monitorPssAndPrivate_(iPS.getUntrackedParameter<bool>("monitorPssAndPrivate"))
128  , count_()
129  , smapsFile_(0)
130  , smapsLineBuffer_(NULL)
131  , smapsLineBufferLen_(0)
132  , growthRateVsize_()
133  , growthRateRss_()
134  , moduleSummaryRequested_(iPS.getUntrackedParameter<bool>("moduleMemorySummary"))
135  , measurementUnderway_(false){
136  // changelog 2
137  // pg_size = (double)getpagesize();
138  std::ostringstream ost;
139 
140  openFiles();
142 
143  if(!oncePerEventMode_) { // default, prints on increases
153  } else {
156  }
157  if(moduleSummaryRequested_) { // changelog 2
159  if(oncePerEventMode_) {
161  }
162  }
163 
164  // The following are not currenty used/implemented below for either
165  // of the print modes (but are left here for reference)
166  // iReg.watchPostBeginJob(this,
167  // &SimpleMemoryCheck::postBeginJob);
168  // iReg.watchPreProcessEvent(this,
169  // &SimpleMemoryCheck::preEventProcessing);
170  // iReg.watchPreModule(this,
171  // &SimpleMemoryCheck::preModule);
172 
173 #ifndef __SANITIZE_ADDRESS__
174  typedef MallocOpts::opt_type opt_type;
176 
177  opt_type
178  p_mmap_max = iPS.getUntrackedParameter<int>("M_MMAP_MAX"),
179  p_trim_thr = iPS.getUntrackedParameter<int>("M_TRIM_THRESHOLD"),
180  p_top_pad = iPS.getUntrackedParameter<int>("M_TOP_PAD"),
181  p_mmap_thr = iPS.getUntrackedParameter<int>("M_MMAP_THRESHOLD");
182 
183  if(p_mmap_max >= 0) mopts.set_mmap_max(p_mmap_max);
184  if(p_trim_thr >= 0) mopts.set_trim_thr(p_trim_thr);
185  if(p_top_pad >= 0) mopts.set_top_pad(p_top_pad);
186  if(p_mmap_thr >= 0) mopts.set_mmap_thr(p_mmap_thr);
187 
188  mopts.adjustMallocParams();
189 
190  if(mopts.hasErrors()) {
191  LogWarning("MemoryCheck")
192  << "ERROR: Problem with setting malloc options\n"
193  << mopts.error_message();
194  }
195 
196  if(iPS.getUntrackedParameter<bool>("dump") == true) {
197  MallocOpts mo = mopts.get();
198  LogWarning("MemoryCheck")
199  << "Malloc options: " << mo << "\n";
200  }
201 #endif
202  }
203 
205 #ifdef LINUX
206  if(0 != smapsFile_) {
207  fclose(smapsFile_);
208  }
209 #endif
210  if (smapsLineBuffer_) {
211  //getline will create the memory using malloc
212  free(smapsLineBuffer_);
213  }
214  }
215 
218  desc.addUntracked<int>("ignoreTotal", 1);
219  desc.addUntracked<bool>("showMallocInfo", false);
220  desc.addUntracked<bool>("oncePerEventMode", false);
221  desc.addUntracked<bool>("jobReportOutputOnly", false);
222  desc.addUntracked<bool>("monitorPssAndPrivate", false);
223  desc.addUntracked<bool>("moduleMemorySummary", false);
224  desc.addUntracked<int>("M_MMAP_MAX", -1);
225  desc.addUntracked<int>("M_TRIM_THRESHOLD", -1);
226  desc.addUntracked<int>("M_TOP_PAD", -1);
227  desc.addUntracked<int>("M_MMAP_THRESHOLD", -1);
228  desc.addUntracked<bool>("dump", false);
229  descriptions.add("SimpleMemoryCheck", desc);
230  }
231 
233 #ifdef LINUX
234  if (monitorPssAndPrivate_) {
235  std::ostringstream smapsNameOst;
236  smapsNameOst <<"/proc/"<<getpid()<<"/smaps";
237  if((smapsFile_ =fopen(smapsNameOst.str().c_str(), "r"))==0) {
238  throw Exception(errors::Configuration) <<"Failed to open smaps file "<<smapsNameOst.str()<<std::endl;
239  }
240  }
241 #endif
242  }
243 
247  }
248 
250  bool expected = false;
251  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
252  std::shared_ptr<void> guard(nullptr,[this](void const*) {
253  measurementUnderway_.store(false,std::memory_order_release);
254  });
255  updateAndPrint("pre-ctor", md.moduleLabel(), md.moduleName());
256  }
257  }
258 
259 
261  bool expected = false;
262  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
263  std::shared_ptr<void> guard(nullptr,[this](void const*) {
264  measurementUnderway_.store(false,std::memory_order_release);
265  });
266  updateAndPrint("ctor", md.moduleLabel(), md.moduleName());
267  }
268  }
269 
271  bool expected = false;
272  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
273  std::shared_ptr<void> guard(nullptr,[this](void const*) {
274  measurementUnderway_.store(false,std::memory_order_release);
275  });
276  updateAndPrint("module", "source", "source");
277  }
278  }
279 
281  bool expected = false;
282  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
283  std::shared_ptr<void> guard(nullptr,[this](void const*) {
284  measurementUnderway_.store(false,std::memory_order_release);
285  });
286  updateAndPrint("ctor", md.moduleLabel(), md.moduleName());
287  }
288  }
289 
291  bool expected = false;
292  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
293  std::shared_ptr<void> guard(nullptr,[this](void const*) {
294  measurementUnderway_.store(false,std::memory_order_release);
295  });
296  updateAndPrint("beginJob", md.moduleLabel(), md.moduleName());
297  }
298  }
299 
301  if(not jobReportOutputOnly_) {
302  LogAbsolute("MemoryReport") // changelog 1
303  << "MemoryReport> Peak virtual size " << eventT1_.vsize << " Mbytes"
304  << "\n"
305  << " Key events increasing vsize: \n"
306  << eventL2_ << "\n"
307  << eventL1_ << "\n"
308  << eventM_ << "\n"
309  << eventR1_ << "\n"
310  << eventR2_ << "\n"
311  << eventT3_ << "\n"
312  << eventT2_ << "\n"
313  << eventT1_ ;
314  }
315  if(moduleSummaryRequested_ and not jobReportOutputOnly_) { // changelog 1
316  LogAbsolute mmr("ModuleMemoryReport"); // at end of if block, mmr
317  // is destructed, causing
318  // message to be logged
319  mmr << "ModuleMemoryReport> Each line has module label and: \n";
320  mmr << " (after early ignored events) \n";
321  mmr <<
322  " count of times module executed; average increase in vsize \n";
323  mmr <<
324  " maximum increase in vsize; event on which maximum occurred \n";
325  mmr << " (during early ignored events) \n";
326  mmr << " total and maximum vsize increases \n \n";
327  for(SignificantModulesMap::iterator im = modules_.begin();
328  im != modules_.end(); ++im) {
329  SignificantModule const& m = im->second;
330  if(m.totalDeltaVsize == 0 && m.totalEarlyVsize == 0) continue;
331  mmr << im->first << ": ";
332  mmr << "n = " << m.postEarlyCount;
333  if(m.postEarlyCount > 0) {
334  mmr << " avg = " << m.totalDeltaVsize/m.postEarlyCount;
335  }
336  mmr << " max = " << m.maxDeltaVsize << " " << m.eventMaxDeltaV;
337  if(m.totalEarlyVsize > 0) {
338  mmr << " early total: " << m.totalEarlyVsize;
339  mmr << " max: " << m.maxEarlyVsize;
340  }
341  mmr << "\n";
342  }
343  } // end of if; mmr goes out of scope; log message is queued
344 
345  Service<JobReport> reportSvc;
346  // changelog 1
347 #define SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
348 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
349 // std::map<std::string, double> reportData;
350  std::map<std::string, std::string> reportData;
351 
352  if(eventL2_.vsize > 0)
353  eventStatOutput("LargeVsizeIncreaseEventL2", eventL2_, reportData);
354  if(eventL1_.vsize > 0)
355  eventStatOutput("LargeVsizeIncreaseEventL1", eventL1_, reportData);
356  if(eventM_.vsize > 0)
357  eventStatOutput("LargestVsizeIncreaseEvent", eventM_, reportData);
358  if(eventR1_.vsize > 0)
359  eventStatOutput("LargeVsizeIncreaseEventR1", eventR1_, reportData);
360  if(eventR2_.vsize > 0)
361  eventStatOutput("LargeVsizeIncreaseEventR2", eventR2_, reportData);
362  if(eventT3_.vsize > 0)
363  eventStatOutput("ThirdLargestVsizeEventT3", eventT3_, reportData);
364  if(eventT2_.vsize > 0)
365  eventStatOutput("SecondLargestVsizeEventT2", eventT2_, reportData);
366  if(eventT1_.vsize > 0)
367  eventStatOutput("LargestVsizeEventT1", eventT1_, reportData);
368 
369  if(eventRssT3_.rss > 0)
370  eventStatOutput("ThirdLargestRssEvent", eventRssT3_, reportData);
371  if(eventRssT2_.rss > 0)
372  eventStatOutput("SecondLargestRssEvent", eventRssT2_, reportData);
373  if(eventRssT1_.rss > 0)
374  eventStatOutput("LargestRssEvent", eventRssT1_, reportData);
375  if(eventDeltaRssT3_.deltaRss > 0)
376  eventStatOutput("ThirdLargestIncreaseRssEvent", eventDeltaRssT3_, reportData);
377  if(eventDeltaRssT2_.deltaRss > 0)
378  eventStatOutput("SecondLargestIncreaseRssEvent", eventDeltaRssT2_, reportData);
379  if(eventDeltaRssT1_.deltaRss > 0)
380  eventStatOutput("LargestIncreaseRssEvent", eventDeltaRssT1_, reportData);
381 
382 #ifdef __linux__
383  struct mallinfo minfo = mallinfo();
384  reportData.insert(
385  std::make_pair("HEAP_ARENA_SIZE_BYTES", i2str(minfo.arena)));
386  reportData.insert(
387  std::make_pair("HEAP_ARENA_N_UNUSED_CHUNKS", i2str(minfo.ordblks)));
388  reportData.insert(
389  std::make_pair("HEAP_TOP_FREE_BYTES", i2str(minfo.keepcost)));
390  reportData.insert(
391  std::make_pair("HEAP_MAPPED_SIZE_BYTES", i2str(minfo.hblkhd)));
392  reportData.insert(
393  std::make_pair("HEAP_MAPPED_N_CHUNKS", i2str(minfo.hblks)));
394  reportData.insert(
395  std::make_pair("HEAP_USED_BYTES", i2str(minfo.uordblks)));
396  reportData.insert(
397  std::make_pair("HEAP_UNUSED_BYTES", i2str(minfo.fordblks)));
398 #endif
399 
400  // Report Growth rates for VSize and Rss
401  reportData.insert(
402  std::make_pair("AverageGrowthRateVsize", d2str(averageGrowthRate(current_->vsize, growthRateVsize_, count_))));
403  reportData.insert(
404  std::make_pair("PeakValueVsize", d2str(eventT1_.vsize)));
405  reportData.insert(
406  std::make_pair("AverageGrowthRateRss", d2str(averageGrowthRate(current_->rss, growthRateRss_, count_))));
407  reportData.insert(
408  std::make_pair("PeakValueRss", d2str(eventRssT1_.rss)));
409 
410  if(moduleSummaryRequested_) { // changelog 2
411  for(SignificantModulesMap::iterator im = modules_.begin();
412  im != modules_.end(); ++im) {
413  SignificantModule const& m = im->second;
414  if(m.totalDeltaVsize == 0 && m.totalEarlyVsize == 0) continue;
415  std::string label = im->first+":";
416  reportData.insert(std::make_pair(label+"PostEarlyCount", i2str(m.postEarlyCount)));
417  if(m.postEarlyCount > 0) {
418  reportData.insert(std::make_pair(label+"AverageDeltaVsize",
420  }
421  reportData.insert(std::make_pair(label+"MaxDeltaVsize", d2str(m.maxDeltaVsize)));
422  if(m.totalEarlyVsize > 0) {
423  reportData.insert(std::make_pair(label+"TotalEarlyVsize", d2str(m.totalEarlyVsize)));
424  reportData.insert(std::make_pair(label+"MaxEarlyDeltaVsize", d2str(m.maxEarlyVsize)));
425  }
426  }
427  }
428 
429  std::map<std::string, std::string> reportMemoryProperties;
430 
431  if(FILE* fmeminfo = fopen("/proc/meminfo", "r")) {
432  char buf[128];
433  char space[] = " ";
434  size_t value;
435 
436  while(fgets(buf, sizeof(buf), fmeminfo)) {
437  char* token = NULL;
438  token = strtok(buf, space);
439  if(token != NULL) {
440  value = atol(strtok(NULL, space));
441  std::string category = token;
442  reportMemoryProperties.insert(std::make_pair(category.substr(0, strlen(token)-1), i2str(value)));
443  }
444  }
445 
446  fclose(fmeminfo);
447  }
448 
449 // reportSvc->reportMemoryInfo(reportData, reportMemoryProperties);
450  reportSvc->reportPerformanceSummary("ApplicationMemory", reportData);
451  reportSvc->reportPerformanceSummary("SystemMemory", reportMemoryProperties);
452 #endif
453 
454 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT
455  std::vector<std::string> reportData;
456 
457  if(eventL2_.vsize > 0) reportData.push_back(
458  eventStatOutput("LargeVsizeIncreaseEventL2", eventL2_));
459  if(eventL1_.vsize > 0) reportData.push_back(
460  eventStatOutput("LargeVsizeIncreaseEventL1", eventL1_));
461  if(eventM_.vsize > 0) reportData.push_back(
462  eventStatOutput("LargestVsizeIncreaseEvent", eventM_));
463  if(eventR1_.vsize > 0) reportData.push_back(
464  eventStatOutput("LargeVsizeIncreaseEventR1", eventR1_));
465  if(eventR2_.vsize > 0) reportData.push_back(
466  eventStatOutput("LargeVsizeIncreaseEventR2", eventR2_));
467  if(eventT3_.vsize > 0) reportData.push_back(
468  eventStatOutput("ThirdLargestVsizeEventT3", eventT3_));
469  if(eventT2_.vsize > 0) reportData.push_back(
470  eventStatOutput("SecondLargestVsizeEventT2", eventT2_));
471  if(eventT1_.vsize > 0) reportData.push_back(
472  eventStatOutput("LargestVsizeEventT1", eventT1_));
473 
474  if(eventRssT3_.rss > 0)
475  eventStatOutput("ThirdLargestRssEvent", eventRssT3_, reportData);
476  if(eventRssT2_.rss > 0)
477  eventStatOutput("SecondLargestRssEvent", eventRssT2_, reportData);
478  if(eventRssT1_.rss > 0)
479  eventStatOutput("LargestRssEvent", eventRssT1_, reportData);
480  if(eventDeltaRssT3_.deltaRss > 0)
481  eventStatOutput("ThirdLargestIncreaseRssEvent", eventDeltaRssT3_, reportData);
482  if(eventDeltaRssT2_.deltaRss > 0)
483  eventStatOutput("SecondLargestIncreaseRssEvent", eventDeltaRssT2_, reportData);
484  if(eventDeltaRssT1_.deltaRss > 0)
485  eventStatOutput("LargestIncreaseRssEvent", eventDeltaRssT1_, reportData);
486 
487  struct mallinfo minfo = mallinfo();
488  reportData.push_back(
489  mallOutput("HEAP_ARENA_SIZE_BYTES", minfo.arena));
490  reportData.push_back(
491  mallOutput("HEAP_ARENA_N_UNUSED_CHUNKS", minfo.ordblks));
492  reportData.push_back(
493  mallOutput("HEAP_TOP_FREE_BYTES", minfo.keepcost));
494  reportData.push_back(
495  mallOutput("HEAP_MAPPED_SIZE_BYTES", minfo.hblkhd));
496  reportData.push_back(
497  mallOutput("HEAP_MAPPED_N_CHUNKS", minfo.hblks));
498  reportData.push_back(
499  mallOutput("HEAP_USED_BYTES", minfo.uordblks));
500  reportData.push_back(
501  mallOutput("HEAP_UNUSED_BYTES", minfo.fordblks));
502 
503  // Report Growth rates for VSize and Rss
504  reportData.insert(
505  std::make_pair("AverageGrowthRateVsize", d2str(averageGrowthRate(current_->vsize, growthRateVsize_, count_))));
506  reportData.insert(
507  std::make_pair("PeakValueVsize", d2str(eventT1_.vsize)));
508  reportData.insert(
509  std::make_pair("AverageGrowthRateRss", d2str(averageGrowthRate(current_->rss, growthRateRss_, count_))));
510  reportData.insert(
511  std::make_pair("PeakValueRss", d2str(eventRssT1_.rss)));
512 
513  reportSvc->reportMemoryInfo(reportData);
514  // This is a form of reportMemoryInfo taking s vector, not a map
515 #endif
516  } // postEndJob
517 
519  ++count_;
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  update();
526  if (monitorPssAndPrivate_) {
528  }
529  updateEventStats(iContext.eventID());
530  if(oncePerEventMode_) {
531  // should probably use be Run:Event or count_ for the label and name
532  updateMax();
533  andPrint("event", "", "");
534  }
535  }
536  }
537 
538  void SimpleMemoryCheck::preModule(StreamContext const& iStreamContext, ModuleCallingContext const& iModuleContext) {
539  bool expected = false;
540  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
541  std::shared_ptr<void> guard(nullptr,[this](void const*) {
542  measurementUnderway_.store(false,std::memory_order_release);
543  });
544  bool expected = false;
545  if(moduleMeasurementUnderway_.compare_exchange_strong(expected,true) ) {
546  update();
547  // changelog 2
549  moduleStreamID_.store(iStreamContext.streamID().value(), std::memory_order_release);
550  moduleID_.store(iModuleContext.moduleDescription()->id(),std::memory_order_release);
551  }
552  }
553  }
554 
555  void SimpleMemoryCheck::postModule(StreamContext const& iStreamContext, ModuleCallingContext const& iModuleContext) {
556  if(!oncePerEventMode_) {
557  bool expected = false;
558  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
559  std::shared_ptr<void> guard(nullptr,[this](void const*) {
560  measurementUnderway_.store(false,std::memory_order_release);
561  });
562  auto const md = iModuleContext.moduleDescription();
563  updateAndPrint("module", md->moduleLabel(), md->moduleName());
564  }
565  }
566 
568  //is this the module instance we are measuring?
569  if(moduleMeasurementUnderway_.load(std::memory_order_acquire) and
570  (iStreamContext.streamID().value()==moduleStreamID_.load(std::memory_order_acquire) ) and
571  (iModuleContext.moduleDescription()->id() == moduleID_.load(std::memory_order_acquire))) {
572  //Need to release our module measurement lock
573  std::shared_ptr<void> guard(nullptr,[this](void const*) {
574  moduleMeasurementUnderway_.store(false,std::memory_order_release);
575  });
576  bool expected = false;
577  if(measurementUnderway_.compare_exchange_strong(expected,true,std::memory_order_acq_rel) ) {
578  std::shared_ptr<void> guard(nullptr,[this](void const*) {
579  measurementUnderway_.store(false,std::memory_order_release);
580  });
581  if(oncePerEventMode_) {
582  update();
583  }
584  // changelog 2
585  double dv = current_->vsize - moduleEntryVsize_;
586  std::string label = iModuleContext.moduleDescription()->moduleLabel();
587  updateModuleMemoryStats (modules_[label], dv, iStreamContext.eventID());
588  }
589  }
590  }
591  }
592 
593  void SimpleMemoryCheck::postFork(unsigned int, unsigned int) {
594 #ifdef LINUX
595  if(0 != smapsFile_) {
596  fclose(smapsFile_);
597  }
598  openFiles();
599 #endif
600  }
601 
604  *current_ = fetch();
605  }
606 
608  if((*current_ > max_) || oncePerEventMode_) {
609  if(count_ >= num_to_skip_) {
610  }
611  max_ = *current_;
612  }
613  }
614 
616  if(count_ < num_to_skip_) return;
617  if(count_ == num_to_skip_) {
618  eventT1_.set(0, 0, e, this);
619  eventM_.set (0, 0, e, this);
620  eventRssT1_.set(0, 0, e, this);
621  eventDeltaRssT1_.set(0, 0, e, this);
622  return;
623  }
624  double vsize = current_->vsize;
625  double deltaVsize = vsize - eventT1_.vsize;
626 
627  // Update significative events for Vsize
628  if(vsize > eventT1_.vsize) {
629  double deltaRss = current_->rss - eventT1_.rss;
630  eventT3_ = eventT2_;
631  eventT2_ = eventT1_;
632  eventT1_.set(deltaVsize, deltaRss, e, this);
633  } else if(vsize > eventT2_.vsize) {
634  double deltaRss = current_->rss - eventT1_.rss;
635  eventT3_ = eventT2_;
636  eventT2_.set(deltaVsize, deltaRss, e, this);
637  } else if(vsize > eventT3_.vsize) {
638  double deltaRss = current_->rss - eventT1_.rss;
639  eventT3_.set(deltaVsize, deltaRss, e, this);
640  }
641 
642  if(deltaVsize > eventM_.deltaVsize) {
643  double deltaRss = current_->rss - eventM_.rss;
645  eventL2_ = eventL1_;
646  } else {
647  eventL2_ = eventR1_;
648  }
649  eventL1_ = eventM_;
650  eventM_.set(deltaVsize, deltaRss, e, this);
653  } else if(deltaVsize > eventR1_.deltaVsize) {
654  double deltaRss = current_->rss - eventM_.rss;
655  eventR2_ = eventR1_;
656  eventR1_.set(deltaVsize, deltaRss, e, this);
657  } else if(deltaVsize > eventR2_.deltaVsize) {
658  double deltaRss = current_->rss - eventR1_.rss;
659  eventR2_.set(deltaVsize, deltaRss, e, this);
660  }
661 
662  // Update significative events for Rss
663  double rss = current_->rss;
664  double deltaRss = rss - eventRssT1_.rss;
665 
666  if(rss > eventRssT1_.rss) {
669  eventRssT1_.set(deltaVsize, deltaRss, e, this);
670  } else if(rss > eventRssT2_.rss) {
672  eventRssT2_.set(deltaVsize, deltaRss, e, this);
673  } else if(rss > eventRssT3_.rss) {
674  eventRssT3_.set(deltaVsize, deltaRss, e, this);
675  }
676  if(deltaRss > eventDeltaRssT1_.deltaRss) {
679  eventDeltaRssT1_.set(deltaVsize, deltaRss, e, this);
680  } else if(deltaRss > eventDeltaRssT2_.deltaRss) {
682  eventDeltaRssT2_.set(deltaVsize, deltaRss, e, this);
683  } else if(deltaRss > eventDeltaRssT3_.deltaRss) {
684  eventDeltaRssT3_.set(deltaVsize, deltaRss, e, this);
685  }
686  } // updateEventStats
687 
689  std::string const& mdlabel, std::string const& mdname) const {
690  if(not jobReportOutputOnly_ && ((*current_ > max_) || oncePerEventMode_)) {
691  if(count_ >= num_to_skip_) {
692  double deltaVSIZE = current_->vsize - max_.vsize;
693  double deltaRSS = current_->rss - max_.rss;
694  if(!showMallocInfo_) { // default
695  LogWarning("MemoryCheck")
696  << "MemoryCheck: " << type << " "
697  << mdname << ":" << mdlabel
698  << " VSIZE " << current_->vsize << " " << deltaVSIZE
699  << " RSS " << current_->rss << " " << deltaRSS
700  << "\n";
701  } else {
702 #ifdef __linux__
703  struct mallinfo minfo = mallinfo();
704 #endif
705  LogWarning("MemoryCheck")
706  << "MemoryCheck: " << type << " "
707  << mdname << ":" << mdlabel
708  << " VSIZE " << current_->vsize << " " << deltaVSIZE
709  << " RSS " << current_->rss << " " << deltaRSS
710 #ifdef __linux__
711  << " HEAP-ARENA [ SIZE-BYTES " << minfo.arena
712  << " N-UNUSED-CHUNKS " << minfo.ordblks
713  << " TOP-FREE-BYTES " << minfo.keepcost << " ]"
714  << " HEAP-MAPPED [ SIZE-BYTES " << minfo.hblkhd
715  << " N-CHUNKS " << minfo.hblks << " ]"
716  << " HEAP-USED-BYTES " << minfo.uordblks
717  << " HEAP-UNUSED-BYTES " << minfo.fordblks
718 #endif
719  << "\n";
720  }
721  }
722  }
723  }
724 
726  std::string const& mdlabel, std::string const& mdname) {
727  update();
728  andPrint(type, mdlabel, mdname);
729  updateMax();
730  }
731 
732 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
733  void
735  SignificantEvent const& e,
736  std::map<std::string, std::string>& m) const {
737  { std::ostringstream os;
738  os << title << "-a-COUNT";
739  m.insert(std::make_pair(os.str(), i2str(e.count))); }
740  { std::ostringstream os;
741  os << title << "-b-RUN";
742  m.insert(std::make_pair(os.str(), d2str(static_cast<double>(e.event.run())))); }
743  { std::ostringstream os;
744  os << title << "-c-EVENT";
745  m.insert(std::make_pair(os.str(), d2str(static_cast<double>(e.event.event())))); }
746  { std::ostringstream os;
747  os << title << "-d-VSIZE";
748  m.insert(std::make_pair(os.str(), d2str(e.vsize))); }
749  { std::ostringstream os;
750  os << title << "-e-DELTV";
751  m.insert(std::make_pair(os.str(), d2str(e.deltaVsize))); }
752  { std::ostringstream os;
753  os << title << "-f-RSS";
754  m.insert(std::make_pair(os.str(), d2str(e.rss))); }
755  if (monitorPssAndPrivate_) {
756  { std::ostringstream os;
757  os << title << "-g-PRIVATE";
758  m.insert(std::make_pair(os.str(), d2str(e.privateSize))); }
759  { std::ostringstream os;
760  os << title << "-h-PSS";
761  m.insert(std::make_pair(os.str(), d2str(e.pss))); }
762  }
763  } // eventStatOutput
764 #endif
765 
766 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT
769  SignificantEvent const& e) const {
770  std::ostringstream os;
771  os << " <" << title << ">\n";
772  os << " " << e.count << ": " << e.event;
773  os << " vsize " << e.vsize-e.deltaVsize << " + " << e.deltaVsize
774  << " = " << e.vsize;
775  os << " rss: " << e.rss << "\n";
776  os << " </" << title << ">\n";
777  return os.str();
778  } // eventStatOutput
779 
781  SimpleMemoryCheck::mallOutput(std::string title, size_t const& n) const {
782  std::ostringstream os;
783  os << " <" << title << ">\n";
784  os << " " << n << "\n";
785  os << " </" << title << ">\n";
786  return os.str();
787  }
788 #endif
789  // changelog 2
790  void
792  double dv, edm::EventID const& currentEventID) {
793  if(count_ < num_to_skip_) {
794  m.totalEarlyVsize += dv;
795  if(dv > m.maxEarlyVsize) m.maxEarlyVsize = dv;
796  } else {
797  ++m.postEarlyCount;
798  m.totalDeltaVsize += dv;
799  if(dv > m.maxDeltaVsize) {
800  m.maxDeltaVsize = dv;
801  m.eventMaxDeltaV = currentEventID;
802  }
803  }
804  } //updateModuleMemoryStats
805 
806  std::ostream&
807  operator<< (std::ostream& os,
809  os << "[" << se.count << "] "
810  << se.event << " vsize = " << se.vsize
811  << " deltaVsize = " << se.deltaVsize
812  << " rss = " << se.rss << " delta = " << se.deltaRss;
813 
814  if (se.monitorPssAndPrivate) {
815  os <<" private = "<<se.privateSize<<" pss = "<<se.pss;
816  }
817  return os;
818  }
819 
820  std::ostream&
821  operator<< (std::ostream& os,
823  if(sm.postEarlyCount > 0) {
824  os << "\nPost Early Events: TotalDeltaVsize: " << sm.totalDeltaVsize
825  << " (avg: " << sm.totalDeltaVsize/sm.postEarlyCount
826  << "; max: " << sm.maxDeltaVsize
827  << " during " << sm.eventMaxDeltaV << ")";
828  }
829  if(sm.totalEarlyVsize > 0) {
830  os << "\n Early Events: TotalDeltaVsize: " << sm.totalEarlyVsize
831  << " (max: " << sm.maxEarlyVsize << ")";
832  }
833 
834  return os;
835  }
836 
837  } // end namespace service
838 } // end namespace edm
839 
RunNumber_t run() const
Definition: EventID.h:42
void watchPostModuleConstruction(PostModuleConstruction::slot_type const &iSlot)
MallocOpts get() const
Definition: MallocOpts.h:84
type
Definition: HCALResponse.h:21
EventNumber_t event() const
Definition: EventID.h:44
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)
Definition: Memory.cc:68
int i
Definition: DBlmapReader.cc:9
std::string eventStatOutput(std::string title, SignificantEvent const &e) const
void postFork(unsigned int, unsigned int)
Definition: Memory.cc:593
SignificantEvent eventDeltaRssT1_
Definition: Memory.h:192
void preSourceConstruction(const ModuleDescription &)
Definition: Memory.cc:249
void set_mmap_max(opt_type mmap_max)
Definition: MallocOpts.h:75
bool hasErrors() const
Definition: MallocOpts.h:72
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
void watchPostEndJob(PostEndJob::slot_type const &iSlot)
SignificantEvent eventM_
Definition: Memory.h:168
std::atomic< bool > measurementUnderway_
Definition: Memory.h:231
SignificantEvent eventT1_
Definition: Memory.h:173
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)
Definition: Memory.cc:615
ProcInfoFetcher piFetcher_
Definition: Memory.h:101
void watchPostEvent(PostEvent::slot_type const &iSlot)
std::atomic< bool > moduleMeasurementUnderway_
Definition: Memory.h:232
void watchPreSourceConstruction(PreSourceConstruction::slot_type const &iSlot)
void watchPostSourceConstruction(PostSourceConstruction::slot_type const &iSlot)
SignificantEvent eventRssT2_
Definition: Memory.h:190
SignificantEvent eventL1_
Definition: Memory.h:169
std::string const & moduleName() const
void watchPostModuleEvent(PostModuleEvent::slot_type const &iSlot)
#define NULL
Definition: scimark2.h:8
void watchPostSourceEvent(PostSourceEvent::slot_type const &iSlot)
SignificantEvent eventT3_
Definition: Memory.h:175
std::string const & moduleLabel() const
void andPrint(const std::string &type, const std::string &mdlabel, const std::string &mdname) const
Definition: Memory.cc:688
std::atomic< unsigned int > moduleStreamID_
Definition: Memory.h:233
SignificantEvent eventRssT3_
Definition: Memory.h:191
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
ModuleDescription const * moduleDescription() const
friend struct SignificantEvent
Definition: Memory.h:149
std::ostream & operator<<(std::ostream &os, SimpleMemoryCheck::SignificantEvent const &se)
Definition: Memory.cc:807
void set(double deltaV, double deltaR, edm::EventID const &e, SimpleMemoryCheck *t)
Definition: Memory.h:134
SignificantEvent eventR1_
Definition: Memory.h:171
SignificantEvent eventDeltaRssT3_
Definition: Memory.h:194
StreamID const & streamID() const
Definition: StreamContext.h:57
void updateAndPrint(const std::string &type, const std::string &mdlabel, const std::string &mdname)
Definition: Memory.cc:725
unsigned int value() const
Definition: StreamID.h:46
SignificantEvent eventR2_
Definition: Memory.h:172
void preModule(StreamContext const &, ModuleCallingContext const &)
Definition: Memory.cc:538
static std::string d2str(double d)
Definition: Memory.cc:62
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void updateModuleMemoryStats(SignificantModule &m, double dv, edm::EventID const &)
Definition: Memory.cc:791
std::atomic< int > count_
Definition: Memory.h:109
void watchPostForkReacquireResources(PostForkReacquireResources::slot_type const &iSlot)
std::string error_message() const
Definition: MallocOpts.h:73
SignificantEvent eventL2_
Definition: Memory.h:170
SignificantEvent eventDeltaRssT2_
Definition: Memory.h:193
void postEvent(StreamContext const &)
Definition: Memory.cc:518
std::string mallOutput(std::string title, size_t const &n) const
void watchPostModuleBeginJob(PostModuleBeginJob::slot_type const &iSlot)
void postSourceConstruction(const ModuleDescription &)
Definition: Memory.cc:260
SignificantEvent eventT2_
Definition: Memory.h:174
void postSourceEvent(StreamID)
Definition: Memory.cc:270
EventID const & eventID() const
Definition: StreamContext.h:59
void postModuleBeginJob(const ModuleDescription &)
Definition: Memory.cc:290
volatile std::atomic< bool > shutdown_flag false
double averageGrowthRate(double current, double past, int count)
Definition: Memory.cc:112
void set_top_pad(opt_type top_pad)
Definition: MallocOpts.h:79
SimpleMemoryCheck(const ParameterSet &, ActivityRegistry &)
Definition: Memory.cc:116
SignificantModulesMap modules_
Definition: Memory.h:226
SignificantEvent eventRssT1_
Definition: Memory.h:189
void postModule(StreamContext const &, ModuleCallingContext const &)
Definition: Memory.cc:555
void postModuleConstruction(const ModuleDescription &)
Definition: Memory.cc:280
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
Definition: Memory.cc:216
MallocOptionSetter & getGlobalOptionSetter()
Definition: MallocOpts.cc:219
unsigned int id() const
void watchPostBeginJob(PostBeginJob::slot_type const &iSlot)
convenience function for attaching to signal
std::atomic< unsigned int > moduleID_
Definition: Memory.h:234