00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "FWCore/Services/src/Memory.h"
00027
00028 #include "DataFormats/Provenance/interface/ModuleDescription.h"
00029 #include "FWCore/Framework/interface/Event.h"
00030 #include "FWCore/MessageLogger/interface/JobReport.h"
00031 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00032 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00033 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00034 #include "FWCore/ServiceRegistry/interface/Service.h"
00035 #include "FWCore/Utilities/interface/Exception.h"
00036 #include "FWCore/Utilities/interface/MallocOpts.h"
00037
00038 #include <cstring>
00039 #include <iostream>
00040 #ifdef __linux__
00041 #include <malloc.h>
00042 #endif
00043 #include <sstream>
00044
00045 #include <string>
00046
00047 #include <boost/lexical_cast.hpp>
00048
00049 #ifdef __linux__
00050 #define LINUX 1
00051 #endif
00052
00053 #include <fcntl.h>
00054 #include <unistd.h>
00055
00056 namespace edm {
00057 namespace service {
00058
00059 static std::string d2str(double d) {
00060 std::ostringstream t;
00061 t << d;
00062 return t.str();
00063 }
00064
00065 static std::string i2str(int i) {
00066 std::ostringstream t;
00067 t << i;
00068 return t.str();
00069 }
00070
00071 struct linux_proc {
00072 int pid;
00073 std::string comm;
00074 char state;
00075 int ppid;
00076 int pgrp;
00077 int session;
00078 int tty;
00079 int tpgid;
00080 unsigned long flags;
00081 unsigned long minflt;
00082 unsigned long cminflt;
00083 unsigned long majflt;
00084 unsigned long cmajflt;
00085 unsigned long utime;
00086 unsigned long stime;
00087 long cutime;
00088 long cstime;
00089 long priority;
00090 long nice;
00091 long num_threads;
00092 long itrealvalue;
00093 int starttime;
00094 unsigned long vsize;
00095 long rss;
00096 unsigned long rlim;
00097 unsigned long startcode;
00098 unsigned long endcode;
00099 unsigned long startstack;
00100 unsigned long kstkesp;
00101 unsigned long kstkeip;
00102 unsigned long signal;
00103 unsigned long blocked;
00104 unsigned long sigignore;
00105 unsigned long sigcatch;
00106 unsigned long wchan;
00107 };
00108
00109 class Fetcher {
00110 public:
00111 friend Fetcher& operator>>(Fetcher&, int&);
00112 friend Fetcher& operator>>(Fetcher&, long&);
00113 friend Fetcher& operator>>(Fetcher&, unsigned int&);
00114 friend Fetcher& operator>>(Fetcher&, unsigned long&);
00115 friend Fetcher& operator>>(Fetcher&, char&);
00116 friend Fetcher& operator>>(Fetcher&, std::string&);
00117
00118 explicit Fetcher(char* buffer) :
00119 buffer_(buffer),
00120 save_(0),
00121 delims_(" \t\n\f\v\r") {
00122 }
00123 private:
00124 int getInt() {
00125 const char* t = getItem();
00126
00127 return boost::lexical_cast<int>(t);
00128 }
00129 long getLong() {
00130 const char* t = getItem();
00131
00132 return boost::lexical_cast<long>(t);
00133 }
00134 unsigned int getUInt() {
00135 const char* t = getItem();
00136
00137 return boost::lexical_cast<unsigned int>(t);
00138 }
00139 unsigned long getULong() {
00140 const char* t = getItem();
00141
00142 return boost::lexical_cast<unsigned long>(t);
00143 }
00144 char getChar() {
00145 return *getItem();
00146 }
00147 std::string getString() {
00148 return std::string(getItem());
00149 }
00150 char* getItem() {
00151 char* item = strtok_r(buffer_, delims_, &save_);
00152 assert(item);
00153 buffer_ = 0;
00154 return item;
00155 }
00156 char* buffer_;
00157 char* save_;
00158 char const* const delims_;
00159 };
00160
00161 Fetcher& operator>>(Fetcher& iFetch, int& oValue) {
00162 oValue = iFetch.getInt();
00163 return iFetch;
00164 }
00165 Fetcher& operator>>(Fetcher& iFetch, long& oValue) {
00166 oValue = iFetch.getLong();
00167 return iFetch;
00168 }
00169 Fetcher& operator>>(Fetcher& iFetch, unsigned int& oValue) {
00170 oValue = iFetch.getUInt();
00171 return iFetch;
00172 }
00173 Fetcher& operator>>(Fetcher& iFetch, unsigned long& oValue) {
00174 oValue = iFetch.getULong();
00175 return iFetch;
00176 }
00177 Fetcher& operator>>(Fetcher& iFetch, char& oValue) {
00178 oValue = iFetch.getChar();
00179 return iFetch;
00180 }
00181 Fetcher& operator>>(Fetcher& iFetch, std::string& oValue) {
00182 oValue = iFetch.getString();
00183 return iFetch;
00184 }
00185
00186
00187 procInfo SimpleMemoryCheck::fetch() {
00188 procInfo ret;
00189
00190 #ifdef LINUX
00191 double pr_size = 0.0, pr_rssize = 0.0;
00192
00193 linux_proc pinfo;
00194 int cnt;
00195
00196 lseek(fd_, 0, SEEK_SET);
00197
00198 if((cnt = read(fd_, buf_, sizeof(buf_) - 1)) < 0) {
00199 perror("Read of Proc file failed:");
00200 return procInfo();
00201 }
00202
00203 if(cnt > 0) {
00204 buf_[cnt] = '\0';
00205
00206
00207 try {
00208 Fetcher fetcher(buf_);
00209 fetcher >> pinfo.pid
00210 >> pinfo.comm
00211 >> pinfo.state
00212 >> pinfo.ppid
00213 >> pinfo.pgrp
00214 >> pinfo.session
00215 >> pinfo.tty
00216 >> pinfo.tpgid
00217 >> pinfo.flags
00218 >> pinfo.minflt
00219 >> pinfo.cminflt
00220 >> pinfo.majflt
00221 >> pinfo.cmajflt
00222 >> pinfo.utime
00223 >> pinfo.stime
00224 >> pinfo.cutime
00225 >> pinfo.cstime
00226 >> pinfo.priority
00227 >> pinfo.nice
00228 >> pinfo.num_threads
00229 >> pinfo.itrealvalue
00230 >> pinfo.starttime
00231 >> pinfo.vsize
00232 >> pinfo.rss
00233 >> pinfo.rlim
00234 >> pinfo.startcode
00235 >> pinfo.endcode
00236 >> pinfo.startstack
00237 >> pinfo.kstkesp
00238 >> pinfo.kstkeip
00239 >> pinfo.signal
00240 >> pinfo.blocked
00241 >> pinfo.sigignore
00242 >> pinfo.sigcatch
00243 >> pinfo.wchan;
00244 } catch (boost::bad_lexical_cast& iE) {
00245 LogWarning("MemoryCheck")<<"Parsing of Prof file failed:"<<iE.what()<<std::endl;
00246 return procInfo();
00247 }
00248
00249
00250 pr_size = (double)pinfo.vsize;
00251 pr_rssize = (double)pinfo.rss;
00252
00253 ret.vsize = pr_size / (1024.0*1024.0);
00254 ret.rss = (pr_rssize * pg_size_) / (1024.0*1024.0);
00255 }
00256 #else
00257 ret.vsize = 0;
00258 ret.rss = 0;
00259 #endif
00260 return ret;
00261 }
00262
00263 smapsInfo SimpleMemoryCheck::fetchSmaps() {
00264 smapsInfo ret;
00265 ret.private_ = 0;
00266 ret.pss_ = 0;
00267 #ifdef LINUX
00268 fseek(smapsFile_, 0, SEEK_SET);
00269 ssize_t read;
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 while ((read = getline(&smapsLineBuffer_, &smapsLineBufferLen_, smapsFile_)) != -1) {
00280 if(read > 14) {
00281
00282 if(0==strncmp("Private_",smapsLineBuffer_,8)) {
00283 unsigned int value = atoi(smapsLineBuffer_+14);
00284
00285 ret.private_ += static_cast<double>(value)/1024.;
00286 } else if(0==strncmp("Pss:",smapsLineBuffer_,4)) {
00287 unsigned int value = atoi(smapsLineBuffer_+4);
00288
00289 ret.pss_ += static_cast<double>(value)/1024.;
00290 }
00291 }
00292 }
00293 #endif
00294 return ret;
00295 }
00296
00297 double SimpleMemoryCheck::averageGrowthRate(double current, double past, int count) {
00298 return(current-past)/(double)count;
00299 }
00300
00301 SimpleMemoryCheck::SimpleMemoryCheck(ParameterSet const& iPS,
00302 ActivityRegistry&iReg)
00303 : a_()
00304 , b_()
00305 , current_(&a_)
00306 , previous_(&b_)
00307 , pg_size_(sysconf(_SC_PAGESIZE))
00308 , num_to_skip_(iPS.getUntrackedParameter<int>("ignoreTotal"))
00309 , showMallocInfo_(iPS.getUntrackedParameter<bool>("showMallocInfo"))
00310 , oncePerEventMode_(iPS.getUntrackedParameter<bool>("oncePerEventMode"))
00311 , jobReportOutputOnly_(iPS.getUntrackedParameter<bool>("jobReportOutputOnly"))
00312 , monitorPssAndPrivate_(iPS.getUntrackedParameter<bool>("monitorPssAndPrivate"))
00313 , count_()
00314 , smapsFile_(0)
00315 , smapsLineBuffer_(NULL)
00316 , smapsLineBufferLen_(0)
00317 , growthRateVsize_()
00318 , growthRateRss_()
00319 , moduleSummaryRequested_(iPS.getUntrackedParameter<bool>("moduleMemorySummary")) {
00320
00321
00322 std::ostringstream ost;
00323
00324 openFiles();
00325 iReg.watchPostForkReacquireResources(this,&SimpleMemoryCheck::postFork);
00326
00327 if(!oncePerEventMode_) {
00328 iReg.watchPreSourceConstruction(this, &SimpleMemoryCheck::preSourceConstruction);
00329 iReg.watchPostSourceConstruction(this, &SimpleMemoryCheck::postSourceConstruction);
00330 iReg.watchPostSource(this, &SimpleMemoryCheck::postSource);
00331 iReg.watchPostModuleConstruction(this, &SimpleMemoryCheck::postModuleConstruction);
00332 iReg.watchPostModuleBeginJob(this, &SimpleMemoryCheck::postModuleBeginJob);
00333 iReg.watchPostProcessEvent(this, &SimpleMemoryCheck::postEventProcessing);
00334 iReg.watchPostModule(this, &SimpleMemoryCheck::postModule);
00335 iReg.watchPostBeginJob(this, &SimpleMemoryCheck::postBeginJob);
00336 iReg.watchPostEndJob(this, &SimpleMemoryCheck::postEndJob);
00337 } else {
00338 iReg.watchPostProcessEvent(this, &SimpleMemoryCheck::postEventProcessing);
00339 iReg.watchPostEndJob(this, &SimpleMemoryCheck::postEndJob);
00340 }
00341 if(moduleSummaryRequested_) {
00342 iReg.watchPreProcessEvent(this, &SimpleMemoryCheck::preEventProcessing);
00343 iReg.watchPreModule(this, &SimpleMemoryCheck::preModule);
00344 if(oncePerEventMode_) {
00345 iReg.watchPostModule(this, &SimpleMemoryCheck::postModule);
00346 }
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 typedef MallocOpts::opt_type opt_type;
00359 MallocOptionSetter& mopts = getGlobalOptionSetter();
00360
00361 opt_type
00362 p_mmap_max = iPS.getUntrackedParameter<int>("M_MMAP_MAX"),
00363 p_trim_thr = iPS.getUntrackedParameter<int>("M_TRIM_THRESHOLD"),
00364 p_top_pad = iPS.getUntrackedParameter<int>("M_TOP_PAD"),
00365 p_mmap_thr = iPS.getUntrackedParameter<int>("M_MMAP_THRESHOLD");
00366
00367 if(p_mmap_max >= 0) mopts.set_mmap_max(p_mmap_max);
00368 if(p_trim_thr >= 0) mopts.set_trim_thr(p_trim_thr);
00369 if(p_top_pad >= 0) mopts.set_top_pad(p_top_pad);
00370 if(p_mmap_thr >= 0) mopts.set_mmap_thr(p_mmap_thr);
00371
00372 mopts.adjustMallocParams();
00373
00374 if(mopts.hasErrors()) {
00375 LogWarning("MemoryCheck")
00376 << "ERROR: Problem with setting malloc options\n"
00377 << mopts.error_message();
00378 }
00379
00380 if(iPS.getUntrackedParameter<bool>("dump") == true) {
00381 MallocOpts mo = mopts.get();
00382 LogWarning("MemoryCheck")
00383 << "Malloc options: " << mo << "\n";
00384 }
00385 }
00386
00387 SimpleMemoryCheck::~SimpleMemoryCheck() {
00388 #ifdef LINUX
00389 close(fd_);
00390 if(0 != smapsFile_) {
00391 fclose(smapsFile_);
00392 }
00393 #endif
00394 if (smapsLineBuffer_) {
00395
00396 free(smapsLineBuffer_);
00397 }
00398 }
00399
00400 void SimpleMemoryCheck::fillDescriptions(ConfigurationDescriptions& descriptions) {
00401 ParameterSetDescription desc;
00402 desc.addUntracked<int>("ignoreTotal", 1);
00403 desc.addUntracked<bool>("showMallocInfo", false);
00404 desc.addUntracked<bool>("oncePerEventMode", false);
00405 desc.addUntracked<bool>("jobReportOutputOnly", false);
00406 desc.addUntracked<bool>("monitorPssAndPrivate", false);
00407 desc.addUntracked<bool>("moduleMemorySummary", false);
00408 desc.addUntracked<int>("M_MMAP_MAX", -1);
00409 desc.addUntracked<int>("M_TRIM_THRESHOLD", -1);
00410 desc.addUntracked<int>("M_TOP_PAD", -1);
00411 desc.addUntracked<int>("M_MMAP_THRESHOLD", -1);
00412 desc.addUntracked<bool>("dump", false);
00413 descriptions.add("SimpleMemoryCheck", desc);
00414 }
00415
00416 void SimpleMemoryCheck::openFiles() {
00417 #ifdef LINUX
00418 std::ostringstream ost;
00419 ost << "/proc/" << getpid() << "/stat";
00420 fname_ = ost.str();
00421
00422 if((fd_ = open(ost.str().c_str(), O_RDONLY)) < 0) {
00423 throw Exception(errors::Configuration)
00424 << "Memory checker server: Failed to open " << ost.str() << std::endl;
00425 }
00426 if (monitorPssAndPrivate_) {
00427 std::ostringstream smapsNameOst;
00428 smapsNameOst <<"/proc/"<<getpid()<<"/smaps";
00429 if((smapsFile_ =fopen(smapsNameOst.str().c_str(), "r"))==0) {
00430 throw Exception(errors::Configuration) <<"Failed to open smaps file "<<smapsNameOst.str()<<std::endl;
00431 }
00432 }
00433 #endif
00434 }
00435
00436 void SimpleMemoryCheck::postBeginJob() {
00437 growthRateVsize_ = current_->vsize;
00438 growthRateRss_ = current_->rss;
00439 }
00440
00441 void SimpleMemoryCheck::preSourceConstruction(ModuleDescription const& md) {
00442 updateAndPrint("pre-ctor", md.moduleLabel(), md.moduleName());
00443 }
00444
00445
00446 void SimpleMemoryCheck::postSourceConstruction(ModuleDescription const& md) {
00447 updateAndPrint("ctor", md.moduleLabel(), md.moduleName());
00448 }
00449
00450 void SimpleMemoryCheck::postSource() {
00451 updateAndPrint("module", "source", "source");
00452 }
00453
00454 void SimpleMemoryCheck::postModuleConstruction(ModuleDescription const& md) {
00455 updateAndPrint("ctor", md.moduleLabel(), md.moduleName());
00456 }
00457
00458 void SimpleMemoryCheck::postModuleBeginJob(ModuleDescription const& md) {
00459 updateAndPrint("beginJob", md.moduleLabel(), md.moduleName());
00460 }
00461
00462 void SimpleMemoryCheck::postEndJob() {
00463 if(not jobReportOutputOnly_) {
00464 LogAbsolute("MemoryReport")
00465 << "MemoryReport> Peak virtual size " << eventT1_.vsize << " Mbytes"
00466 << "\n"
00467 << " Key events increasing vsize: \n"
00468 << eventL2_ << "\n"
00469 << eventL1_ << "\n"
00470 << eventM_ << "\n"
00471 << eventR1_ << "\n"
00472 << eventR2_ << "\n"
00473 << eventT3_ << "\n"
00474 << eventT2_ << "\n"
00475 << eventT1_ ;
00476 }
00477 if(moduleSummaryRequested_ and not jobReportOutputOnly_) {
00478 LogAbsolute mmr("ModuleMemoryReport");
00479
00480
00481 mmr << "ModuleMemoryReport> Each line has module label and: \n";
00482 mmr << " (after early ignored events) \n";
00483 mmr <<
00484 " count of times module executed; average increase in vsize \n";
00485 mmr <<
00486 " maximum increase in vsize; event on which maximum occurred \n";
00487 mmr << " (during early ignored events) \n";
00488 mmr << " total and maximum vsize increases \n \n";
00489 for(SignificantModulesMap::iterator im = modules_.begin();
00490 im != modules_.end(); ++im) {
00491 SignificantModule const& m = im->second;
00492 if(m.totalDeltaVsize == 0 && m.totalEarlyVsize == 0) continue;
00493 mmr << im->first << ": ";
00494 mmr << "n = " << m.postEarlyCount;
00495 if(m.postEarlyCount > 0) {
00496 mmr << " avg = " << m.totalDeltaVsize/m.postEarlyCount;
00497 }
00498 mmr << " max = " << m.maxDeltaVsize << " " << m.eventMaxDeltaV;
00499 if(m.totalEarlyVsize > 0) {
00500 mmr << " early total: " << m.totalEarlyVsize;
00501 mmr << " max: " << m.maxEarlyVsize;
00502 }
00503 mmr << "\n";
00504 }
00505 }
00506
00507 Service<JobReport> reportSvc;
00508
00509 #define SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
00510 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
00511
00512 std::map<std::string, std::string> reportData;
00513
00514 if(eventL2_.vsize > 0)
00515 eventStatOutput("LargeVsizeIncreaseEventL2", eventL2_, reportData);
00516 if(eventL1_.vsize > 0)
00517 eventStatOutput("LargeVsizeIncreaseEventL1", eventL1_, reportData);
00518 if(eventM_.vsize > 0)
00519 eventStatOutput("LargestVsizeIncreaseEvent", eventM_, reportData);
00520 if(eventR1_.vsize > 0)
00521 eventStatOutput("LargeVsizeIncreaseEventR1", eventR1_, reportData);
00522 if(eventR2_.vsize > 0)
00523 eventStatOutput("LargeVsizeIncreaseEventR2", eventR2_, reportData);
00524 if(eventT3_.vsize > 0)
00525 eventStatOutput("ThirdLargestVsizeEventT3", eventT3_, reportData);
00526 if(eventT2_.vsize > 0)
00527 eventStatOutput("SecondLargestVsizeEventT2", eventT2_, reportData);
00528 if(eventT1_.vsize > 0)
00529 eventStatOutput("LargestVsizeEventT1", eventT1_, reportData);
00530
00531 if(eventRssT3_.rss > 0)
00532 eventStatOutput("ThirdLargestRssEvent", eventRssT3_, reportData);
00533 if(eventRssT2_.rss > 0)
00534 eventStatOutput("SecondLargestRssEvent", eventRssT2_, reportData);
00535 if(eventRssT1_.rss > 0)
00536 eventStatOutput("LargestRssEvent", eventRssT1_, reportData);
00537 if(eventDeltaRssT3_.deltaRss > 0)
00538 eventStatOutput("ThirdLargestIncreaseRssEvent", eventDeltaRssT3_, reportData);
00539 if(eventDeltaRssT2_.deltaRss > 0)
00540 eventStatOutput("SecondLargestIncreaseRssEvent", eventDeltaRssT2_, reportData);
00541 if(eventDeltaRssT1_.deltaRss > 0)
00542 eventStatOutput("LargestIncreaseRssEvent", eventDeltaRssT1_, reportData);
00543
00544 #ifdef __linux__
00545 struct mallinfo minfo = mallinfo();
00546 reportData.insert(
00547 std::make_pair("HEAP_ARENA_SIZE_BYTES", i2str(minfo.arena)));
00548 reportData.insert(
00549 std::make_pair("HEAP_ARENA_N_UNUSED_CHUNKS", i2str(minfo.ordblks)));
00550 reportData.insert(
00551 std::make_pair("HEAP_TOP_FREE_BYTES", i2str(minfo.keepcost)));
00552 reportData.insert(
00553 std::make_pair("HEAP_MAPPED_SIZE_BYTES", i2str(minfo.hblkhd)));
00554 reportData.insert(
00555 std::make_pair("HEAP_MAPPED_N_CHUNKS", i2str(minfo.hblks)));
00556 reportData.insert(
00557 std::make_pair("HEAP_USED_BYTES", i2str(minfo.uordblks)));
00558 reportData.insert(
00559 std::make_pair("HEAP_UNUSED_BYTES", i2str(minfo.fordblks)));
00560 #endif
00561
00562
00563 reportData.insert(
00564 std::make_pair("AverageGrowthRateVsize", d2str(averageGrowthRate(current_->vsize, growthRateVsize_, count_))));
00565 reportData.insert(
00566 std::make_pair("PeakValueVsize", d2str(eventT1_.vsize)));
00567 reportData.insert(
00568 std::make_pair("AverageGrowthRateRss", d2str(averageGrowthRate(current_->rss, growthRateRss_, count_))));
00569 reportData.insert(
00570 std::make_pair("PeakValueRss", d2str(eventRssT1_.rss)));
00571
00572 if(moduleSummaryRequested_) {
00573 for(SignificantModulesMap::iterator im = modules_.begin();
00574 im != modules_.end(); ++im) {
00575 SignificantModule const& m = im->second;
00576 if(m.totalDeltaVsize == 0 && m.totalEarlyVsize == 0) continue;
00577 std::string label = im->first+":";
00578 reportData.insert(std::make_pair(label+"PostEarlyCount", i2str(m.postEarlyCount)));
00579 if(m.postEarlyCount > 0) {
00580 reportData.insert(std::make_pair(label+"AverageDeltaVsize",
00581 d2str(m.totalDeltaVsize/m.postEarlyCount)));
00582 }
00583 reportData.insert(std::make_pair(label+"MaxDeltaVsize", d2str(m.maxDeltaVsize)));
00584 if(m.totalEarlyVsize > 0) {
00585 reportData.insert(std::make_pair(label+"TotalEarlyVsize", d2str(m.totalEarlyVsize)));
00586 reportData.insert(std::make_pair(label+"MaxEarlyDeltaVsize", d2str(m.maxEarlyVsize)));
00587 }
00588 }
00589 }
00590
00591 std::map<std::string, std::string> reportMemoryProperties;
00592
00593 if(FILE* fmeminfo = fopen("/proc/meminfo", "r")) {
00594 char buf[128];
00595 char space[] = " ";
00596 size_t value;
00597
00598 while(fgets(buf, sizeof(buf), fmeminfo)) {
00599 char* token = NULL;
00600 token = strtok(buf, space);
00601 if(token != NULL) {
00602 value = atol(strtok(NULL, space));
00603 std::string category = token;
00604 reportMemoryProperties.insert(std::make_pair(category.substr(0, strlen(token)-1), i2str(value)));
00605 }
00606 }
00607
00608 fclose(fmeminfo);
00609 }
00610
00611
00612 reportSvc->reportPerformanceSummary("ApplicationMemory", reportData);
00613 reportSvc->reportPerformanceSummary("SystemMemory", reportMemoryProperties);
00614 #endif
00615
00616 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT
00617 std::vector<std::string> reportData;
00618
00619 if(eventL2_.vsize > 0) reportData.push_back(
00620 eventStatOutput("LargeVsizeIncreaseEventL2", eventL2_));
00621 if(eventL1_.vsize > 0) reportData.push_back(
00622 eventStatOutput("LargeVsizeIncreaseEventL1", eventL1_));
00623 if(eventM_.vsize > 0) reportData.push_back(
00624 eventStatOutput("LargestVsizeIncreaseEvent", eventM_));
00625 if(eventR1_.vsize > 0) reportData.push_back(
00626 eventStatOutput("LargeVsizeIncreaseEventR1", eventR1_));
00627 if(eventR2_.vsize > 0) reportData.push_back(
00628 eventStatOutput("LargeVsizeIncreaseEventR2", eventR2_));
00629 if(eventT3_.vsize > 0) reportData.push_back(
00630 eventStatOutput("ThirdLargestVsizeEventT3", eventT3_));
00631 if(eventT2_.vsize > 0) reportData.push_back(
00632 eventStatOutput("SecondLargestVsizeEventT2", eventT2_));
00633 if(eventT1_.vsize > 0) reportData.push_back(
00634 eventStatOutput("LargestVsizeEventT1", eventT1_));
00635
00636 if(eventRssT3_.rss > 0)
00637 eventStatOutput("ThirdLargestRssEvent", eventRssT3_, reportData);
00638 if(eventRssT2_.rss > 0)
00639 eventStatOutput("SecondLargestRssEvent", eventRssT2_, reportData);
00640 if(eventRssT1_.rss > 0)
00641 eventStatOutput("LargestRssEvent", eventRssT1_, reportData);
00642 if(eventDeltaRssT3_.deltaRss > 0)
00643 eventStatOutput("ThirdLargestIncreaseRssEvent", eventDeltaRssT3_, reportData);
00644 if(eventDeltaRssT2_.deltaRss > 0)
00645 eventStatOutput("SecondLargestIncreaseRssEvent", eventDeltaRssT2_, reportData);
00646 if(eventDeltaRssT1_.deltaRss > 0)
00647 eventStatOutput("LargestIncreaseRssEvent", eventDeltaRssT1_, reportData);
00648
00649 struct mallinfo minfo = mallinfo();
00650 reportData.push_back(
00651 mallOutput("HEAP_ARENA_SIZE_BYTES", minfo.arena));
00652 reportData.push_back(
00653 mallOutput("HEAP_ARENA_N_UNUSED_CHUNKS", minfo.ordblks));
00654 reportData.push_back(
00655 mallOutput("HEAP_TOP_FREE_BYTES", minfo.keepcost));
00656 reportData.push_back(
00657 mallOutput("HEAP_MAPPED_SIZE_BYTES", minfo.hblkhd));
00658 reportData.push_back(
00659 mallOutput("HEAP_MAPPED_N_CHUNKS", minfo.hblks));
00660 reportData.push_back(
00661 mallOutput("HEAP_USED_BYTES", minfo.uordblks));
00662 reportData.push_back(
00663 mallOutput("HEAP_UNUSED_BYTES", minfo.fordblks));
00664
00665
00666 reportData.insert(
00667 std::make_pair("AverageGrowthRateVsize", d2str(averageGrowthRate(current_->vsize, growthRateVsize_, count_))));
00668 reportData.insert(
00669 std::make_pair("PeakValueVsize", d2str(eventT1_.vsize)));
00670 reportData.insert(
00671 std::make_pair("AverageGrowthRateRss", d2str(averageGrowthRate(current_->rss, growthRateRss_, count_))));
00672 reportData.insert(
00673 std::make_pair("PeakValueRss", d2str(eventRssT1_.rss)));
00674
00675 reportSvc->reportMemoryInfo(reportData);
00676
00677 #endif
00678 }
00679
00680 void SimpleMemoryCheck::preEventProcessing(EventID const& iID, Timestamp const&) {
00681 currentEventID_ = iID;
00682 }
00683
00684 void SimpleMemoryCheck::postEventProcessing(Event const& e, EventSetup const&) {
00685 ++count_;
00686 update();
00687 if (monitorPssAndPrivate_) {
00688 currentSmaps_ = fetchSmaps();
00689 }
00690 updateEventStats(e.id());
00691 if(oncePerEventMode_) {
00692
00693 updateMax();
00694 andPrint("event", "", "");
00695 }
00696 }
00697
00698 void SimpleMemoryCheck::preModule(ModuleDescription const&) {
00699 update();
00700 moduleEntryVsize_ = current_->vsize;
00701 }
00702
00703 void SimpleMemoryCheck::postModule(ModuleDescription const& md) {
00704 if(!oncePerEventMode_) {
00705 updateAndPrint("module", md.moduleLabel(), md.moduleName());
00706 } else if(moduleSummaryRequested_) {
00707 update();
00708 }
00709 if(moduleSummaryRequested_) {
00710 double dv = current_->vsize - moduleEntryVsize_;
00711 std::string label = md.moduleLabel();
00712 updateModuleMemoryStats (modules_[label], dv);
00713 }
00714 }
00715
00716 void SimpleMemoryCheck::postFork(unsigned int, unsigned int) {
00717 #ifdef LINUX
00718 close(fd_);
00719 if(0 != smapsFile_) {
00720 fclose(smapsFile_);
00721 }
00722 openFiles();
00723 #endif
00724 }
00725
00726 void SimpleMemoryCheck::update() {
00727 std::swap(current_, previous_);
00728 *current_ = fetch();
00729 }
00730
00731 void SimpleMemoryCheck::updateMax() {
00732 if((*current_ > max_) || oncePerEventMode_) {
00733 if(count_ >= num_to_skip_) {
00734 }
00735 max_ = *current_;
00736 }
00737 }
00738
00739 void SimpleMemoryCheck::updateEventStats(EventID const& e) {
00740 if(count_ < num_to_skip_) return;
00741 if(count_ == num_to_skip_) {
00742 eventT1_.set(0, 0, e, this);
00743 eventM_.set (0, 0, e, this);
00744 eventRssT1_.set(0, 0, e, this);
00745 eventDeltaRssT1_.set(0, 0, e, this);
00746 return;
00747 }
00748 double vsize = current_->vsize;
00749 double deltaVsize = vsize - eventT1_.vsize;
00750
00751
00752 if(vsize > eventT1_.vsize) {
00753 double deltaRss = current_->rss - eventT1_.rss;
00754 eventT3_ = eventT2_;
00755 eventT2_ = eventT1_;
00756 eventT1_.set(deltaVsize, deltaRss, e, this);
00757 } else if(vsize > eventT2_.vsize) {
00758 double deltaRss = current_->rss - eventT1_.rss;
00759 eventT3_ = eventT2_;
00760 eventT2_.set(deltaVsize, deltaRss, e, this);
00761 } else if(vsize > eventT3_.vsize) {
00762 double deltaRss = current_->rss - eventT1_.rss;
00763 eventT3_.set(deltaVsize, deltaRss, e, this);
00764 }
00765
00766 if(deltaVsize > eventM_.deltaVsize) {
00767 double deltaRss = current_->rss - eventM_.rss;
00768 if(eventL1_.deltaVsize >= eventR1_.deltaVsize) {
00769 eventL2_ = eventL1_;
00770 } else {
00771 eventL2_ = eventR1_;
00772 }
00773 eventL1_ = eventM_;
00774 eventM_.set(deltaVsize, deltaRss, e, this);
00775 eventR1_ = SignificantEvent();
00776 eventR2_ = SignificantEvent();
00777 } else if(deltaVsize > eventR1_.deltaVsize) {
00778 double deltaRss = current_->rss - eventM_.rss;
00779 eventR2_ = eventR1_;
00780 eventR1_.set(deltaVsize, deltaRss, e, this);
00781 } else if(deltaVsize > eventR2_.deltaVsize) {
00782 double deltaRss = current_->rss - eventR1_.rss;
00783 eventR2_.set(deltaVsize, deltaRss, e, this);
00784 }
00785
00786
00787 double rss = current_->rss;
00788 double deltaRss = rss - eventRssT1_.rss;
00789
00790 if(rss > eventRssT1_.rss) {
00791 eventRssT3_ = eventRssT2_;
00792 eventRssT2_ = eventRssT1_;
00793 eventRssT1_.set(deltaVsize, deltaRss, e, this);
00794 } else if(rss > eventRssT2_.rss) {
00795 eventRssT3_ = eventRssT2_;
00796 eventRssT2_.set(deltaVsize, deltaRss, e, this);
00797 } else if(rss > eventRssT3_.rss) {
00798 eventRssT3_.set(deltaVsize, deltaRss, e, this);
00799 }
00800 if(deltaRss > eventDeltaRssT1_.deltaRss) {
00801 eventDeltaRssT3_ = eventDeltaRssT2_;
00802 eventDeltaRssT2_ = eventDeltaRssT1_;
00803 eventDeltaRssT1_.set(deltaVsize, deltaRss, e, this);
00804 } else if(deltaRss > eventDeltaRssT2_.deltaRss) {
00805 eventDeltaRssT3_ = eventDeltaRssT2_;
00806 eventDeltaRssT2_.set(deltaVsize, deltaRss, e, this);
00807 } else if(deltaRss > eventDeltaRssT3_.deltaRss) {
00808 eventDeltaRssT3_.set(deltaVsize, deltaRss, e, this);
00809 }
00810 }
00811
00812 void SimpleMemoryCheck::andPrint(std::string const& type,
00813 std::string const& mdlabel, std::string const& mdname) const {
00814 if(not jobReportOutputOnly_ && ((*current_ > max_) || oncePerEventMode_)) {
00815 if(count_ >= num_to_skip_) {
00816 double deltaVSIZE = current_->vsize - max_.vsize;
00817 double deltaRSS = current_->rss - max_.rss;
00818 if(!showMallocInfo_) {
00819 LogWarning("MemoryCheck")
00820 << "MemoryCheck: " << type << " "
00821 << mdname << ":" << mdlabel
00822 << " VSIZE " << current_->vsize << " " << deltaVSIZE
00823 << " RSS " << current_->rss << " " << deltaRSS
00824 << "\n";
00825 } else {
00826 #ifdef __linux__
00827 struct mallinfo minfo = mallinfo();
00828 #endif
00829 LogWarning("MemoryCheck")
00830 << "MemoryCheck: " << type << " "
00831 << mdname << ":" << mdlabel
00832 << " VSIZE " << current_->vsize << " " << deltaVSIZE
00833 << " RSS " << current_->rss << " " << deltaRSS
00834 #ifdef __linux__
00835 << " HEAP-ARENA [ SIZE-BYTES " << minfo.arena
00836 << " N-UNUSED-CHUNKS " << minfo.ordblks
00837 << " TOP-FREE-BYTES " << minfo.keepcost << " ]"
00838 << " HEAP-MAPPED [ SIZE-BYTES " << minfo.hblkhd
00839 << " N-CHUNKS " << minfo.hblks << " ]"
00840 << " HEAP-USED-BYTES " << minfo.uordblks
00841 << " HEAP-UNUSED-BYTES " << minfo.fordblks
00842 #endif
00843 << "\n";
00844 }
00845 }
00846 }
00847 }
00848
00849 void SimpleMemoryCheck::updateAndPrint(std::string const& type,
00850 std::string const& mdlabel, std::string const& mdname) {
00851 update();
00852 andPrint(type, mdlabel, mdname);
00853 updateMax();
00854 }
00855
00856 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
00857 void
00858 SimpleMemoryCheck::eventStatOutput(std::string title,
00859 SignificantEvent const& e,
00860 std::map<std::string, std::string>& m) const {
00861 { std::ostringstream os;
00862 os << title << "-a-COUNT";
00863 m.insert(std::make_pair(os.str(), i2str(e.count))); }
00864 { std::ostringstream os;
00865 os << title << "-b-RUN";
00866 m.insert(std::make_pair(os.str(), d2str(static_cast<double>(e.event.run())))); }
00867 { std::ostringstream os;
00868 os << title << "-c-EVENT";
00869 m.insert(std::make_pair(os.str(), d2str(static_cast<double>(e.event.event())))); }
00870 { std::ostringstream os;
00871 os << title << "-d-VSIZE";
00872 m.insert(std::make_pair(os.str(), d2str(e.vsize))); }
00873 { std::ostringstream os;
00874 os << title << "-e-DELTV";
00875 m.insert(std::make_pair(os.str(), d2str(e.deltaVsize))); }
00876 { std::ostringstream os;
00877 os << title << "-f-RSS";
00878 m.insert(std::make_pair(os.str(), d2str(e.rss))); }
00879 if (monitorPssAndPrivate_) {
00880 { std::ostringstream os;
00881 os << title << "-g-PRIVATE";
00882 m.insert(std::make_pair(os.str(), d2str(e.privateSize))); }
00883 { std::ostringstream os;
00884 os << title << "-h-PSS";
00885 m.insert(std::make_pair(os.str(), d2str(e.pss))); }
00886 }
00887 }
00888 #endif
00889
00890 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT
00891 std::string
00892 SimpleMemoryCheck::eventStatOutput(std::string title,
00893 SignificantEvent const& e) const {
00894 std::ostringstream os;
00895 os << " <" << title << ">\n";
00896 os << " " << e.count << ": " << e.event;
00897 os << " vsize " << e.vsize-e.deltaVsize << " + " << e.deltaVsize
00898 << " = " << e.vsize;
00899 os << " rss: " << e.rss << "\n";
00900 os << " </" << title << ">\n";
00901 return os.str();
00902 }
00903
00904 std::string
00905 SimpleMemoryCheck::mallOutput(std::string title, size_t const& n) const {
00906 std::ostringstream os;
00907 os << " <" << title << ">\n";
00908 os << " " << n << "\n";
00909 os << " </" << title << ">\n";
00910 return os.str();
00911 }
00912 #endif
00913
00914 void
00915 SimpleMemoryCheck::updateModuleMemoryStats(SignificantModule& m,
00916 double dv) {
00917 if(count_ < num_to_skip_) {
00918 m.totalEarlyVsize += dv;
00919 if(dv > m.maxEarlyVsize) m.maxEarlyVsize = dv;
00920 } else {
00921 ++m.postEarlyCount;
00922 m.totalDeltaVsize += dv;
00923 if(dv > m.maxDeltaVsize) {
00924 m.maxDeltaVsize = dv;
00925 m.eventMaxDeltaV = currentEventID_;
00926 }
00927 }
00928 }
00929
00930 std::ostream&
00931 operator<< (std::ostream& os,
00932 SimpleMemoryCheck::SignificantEvent const& se) {
00933 os << "[" << se.count << "] "
00934 << se.event << " vsize = " << se.vsize
00935 << " deltaVsize = " << se.deltaVsize
00936 << " rss = " << se.rss << " delta = " << se.deltaRss;
00937
00938 if (se.monitorPssAndPrivate) {
00939 os <<" private = "<<se.privateSize<<" pss = "<<se.pss;
00940 }
00941 return os;
00942 }
00943
00944 std::ostream&
00945 operator<< (std::ostream& os,
00946 SimpleMemoryCheck::SignificantModule const& sm) {
00947 if(sm.postEarlyCount > 0) {
00948 os << "\nPost Early Events: TotalDeltaVsize: " << sm.totalDeltaVsize
00949 << " (avg: " << sm.totalDeltaVsize/sm.postEarlyCount
00950 << "; max: " << sm.maxDeltaVsize
00951 << " during " << sm.eventMaxDeltaV << ")";
00952 }
00953 if(sm.totalEarlyVsize > 0) {
00954 os << "\n Early Events: TotalDeltaVsize: " << sm.totalEarlyVsize
00955 << " (max: " << sm.maxEarlyVsize << ")";
00956 }
00957
00958 return os;
00959 }
00960
00961 }
00962 }
00963