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 ProcInfo SimpleMemoryCheck::fetch() {
00072 return piFetcher_.fetch();
00073 }
00074
00075 smapsInfo SimpleMemoryCheck::fetchSmaps() {
00076 smapsInfo ret;
00077 ret.private_ = 0;
00078 ret.pss_ = 0;
00079 #ifdef LINUX
00080 fseek(smapsFile_, 0, SEEK_SET);
00081 ssize_t read;
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 while ((read = getline(&smapsLineBuffer_, &smapsLineBufferLen_, smapsFile_)) != -1) {
00092 if(read > 14) {
00093
00094 if(0==strncmp("Private_",smapsLineBuffer_,8)) {
00095 unsigned int value = atoi(smapsLineBuffer_+14);
00096
00097 ret.private_ += static_cast<double>(value)/1024.;
00098 } else if(0==strncmp("Pss:",smapsLineBuffer_,4)) {
00099 unsigned int value = atoi(smapsLineBuffer_+4);
00100
00101 ret.pss_ += static_cast<double>(value)/1024.;
00102 }
00103 }
00104 }
00105 #endif
00106 return ret;
00107 }
00108
00109 double SimpleMemoryCheck::averageGrowthRate(double current, double past, int count) {
00110 return(current-past)/(double)count;
00111 }
00112
00113 SimpleMemoryCheck::SimpleMemoryCheck(ParameterSet const& iPS,
00114 ActivityRegistry&iReg)
00115 : a_()
00116 , b_()
00117 , current_(&a_)
00118 , previous_(&b_)
00119 , pg_size_(sysconf(_SC_PAGESIZE))
00120 , num_to_skip_(iPS.getUntrackedParameter<int>("ignoreTotal"))
00121 , showMallocInfo_(iPS.getUntrackedParameter<bool>("showMallocInfo"))
00122 , oncePerEventMode_(iPS.getUntrackedParameter<bool>("oncePerEventMode"))
00123 , jobReportOutputOnly_(iPS.getUntrackedParameter<bool>("jobReportOutputOnly"))
00124 , monitorPssAndPrivate_(iPS.getUntrackedParameter<bool>("monitorPssAndPrivate"))
00125 , count_()
00126 , smapsFile_(0)
00127 , smapsLineBuffer_(NULL)
00128 , smapsLineBufferLen_(0)
00129 , growthRateVsize_()
00130 , growthRateRss_()
00131 , moduleSummaryRequested_(iPS.getUntrackedParameter<bool>("moduleMemorySummary")) {
00132
00133
00134 std::ostringstream ost;
00135
00136 openFiles();
00137 iReg.watchPostForkReacquireResources(this,&SimpleMemoryCheck::postFork);
00138
00139 if(!oncePerEventMode_) {
00140 iReg.watchPreSourceConstruction(this, &SimpleMemoryCheck::preSourceConstruction);
00141 iReg.watchPostSourceConstruction(this, &SimpleMemoryCheck::postSourceConstruction);
00142 iReg.watchPostSource(this, &SimpleMemoryCheck::postSource);
00143 iReg.watchPostModuleConstruction(this, &SimpleMemoryCheck::postModuleConstruction);
00144 iReg.watchPostModuleBeginJob(this, &SimpleMemoryCheck::postModuleBeginJob);
00145 iReg.watchPostProcessEvent(this, &SimpleMemoryCheck::postEventProcessing);
00146 iReg.watchPostModule(this, &SimpleMemoryCheck::postModule);
00147 iReg.watchPostBeginJob(this, &SimpleMemoryCheck::postBeginJob);
00148 iReg.watchPostEndJob(this, &SimpleMemoryCheck::postEndJob);
00149 } else {
00150 iReg.watchPostProcessEvent(this, &SimpleMemoryCheck::postEventProcessing);
00151 iReg.watchPostEndJob(this, &SimpleMemoryCheck::postEndJob);
00152 }
00153 if(moduleSummaryRequested_) {
00154 iReg.watchPreProcessEvent(this, &SimpleMemoryCheck::preEventProcessing);
00155 iReg.watchPreModule(this, &SimpleMemoryCheck::preModule);
00156 if(oncePerEventMode_) {
00157 iReg.watchPostModule(this, &SimpleMemoryCheck::postModule);
00158 }
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 #ifndef __SANITIZE_ADDRESS__
00171 typedef MallocOpts::opt_type opt_type;
00172 MallocOptionSetter& mopts = getGlobalOptionSetter();
00173
00174 opt_type
00175 p_mmap_max = iPS.getUntrackedParameter<int>("M_MMAP_MAX"),
00176 p_trim_thr = iPS.getUntrackedParameter<int>("M_TRIM_THRESHOLD"),
00177 p_top_pad = iPS.getUntrackedParameter<int>("M_TOP_PAD"),
00178 p_mmap_thr = iPS.getUntrackedParameter<int>("M_MMAP_THRESHOLD");
00179
00180 if(p_mmap_max >= 0) mopts.set_mmap_max(p_mmap_max);
00181 if(p_trim_thr >= 0) mopts.set_trim_thr(p_trim_thr);
00182 if(p_top_pad >= 0) mopts.set_top_pad(p_top_pad);
00183 if(p_mmap_thr >= 0) mopts.set_mmap_thr(p_mmap_thr);
00184
00185 mopts.adjustMallocParams();
00186
00187 if(mopts.hasErrors()) {
00188 LogWarning("MemoryCheck")
00189 << "ERROR: Problem with setting malloc options\n"
00190 << mopts.error_message();
00191 }
00192
00193 if(iPS.getUntrackedParameter<bool>("dump") == true) {
00194 MallocOpts mo = mopts.get();
00195 LogWarning("MemoryCheck")
00196 << "Malloc options: " << mo << "\n";
00197 }
00198 #endif
00199 }
00200
00201 SimpleMemoryCheck::~SimpleMemoryCheck() {
00202 #ifdef LINUX
00203 if(0 != smapsFile_) {
00204 fclose(smapsFile_);
00205 }
00206 #endif
00207 if (smapsLineBuffer_) {
00208
00209 free(smapsLineBuffer_);
00210 }
00211 }
00212
00213 void SimpleMemoryCheck::fillDescriptions(ConfigurationDescriptions& descriptions) {
00214 ParameterSetDescription desc;
00215 desc.addUntracked<int>("ignoreTotal", 1);
00216 desc.addUntracked<bool>("showMallocInfo", false);
00217 desc.addUntracked<bool>("oncePerEventMode", false);
00218 desc.addUntracked<bool>("jobReportOutputOnly", false);
00219 desc.addUntracked<bool>("monitorPssAndPrivate", false);
00220 desc.addUntracked<bool>("moduleMemorySummary", false);
00221 desc.addUntracked<int>("M_MMAP_MAX", -1);
00222 desc.addUntracked<int>("M_TRIM_THRESHOLD", -1);
00223 desc.addUntracked<int>("M_TOP_PAD", -1);
00224 desc.addUntracked<int>("M_MMAP_THRESHOLD", -1);
00225 desc.addUntracked<bool>("dump", false);
00226 descriptions.add("SimpleMemoryCheck", desc);
00227 }
00228
00229 void SimpleMemoryCheck::openFiles() {
00230 #ifdef LINUX
00231 if (monitorPssAndPrivate_) {
00232 std::ostringstream smapsNameOst;
00233 smapsNameOst <<"/proc/"<<getpid()<<"/smaps";
00234 if((smapsFile_ =fopen(smapsNameOst.str().c_str(), "r"))==0) {
00235 throw Exception(errors::Configuration) <<"Failed to open smaps file "<<smapsNameOst.str()<<std::endl;
00236 }
00237 }
00238 #endif
00239 }
00240
00241 void SimpleMemoryCheck::postBeginJob() {
00242 growthRateVsize_ = current_->vsize;
00243 growthRateRss_ = current_->rss;
00244 }
00245
00246 void SimpleMemoryCheck::preSourceConstruction(ModuleDescription const& md) {
00247 updateAndPrint("pre-ctor", md.moduleLabel(), md.moduleName());
00248 }
00249
00250
00251 void SimpleMemoryCheck::postSourceConstruction(ModuleDescription const& md) {
00252 updateAndPrint("ctor", md.moduleLabel(), md.moduleName());
00253 }
00254
00255 void SimpleMemoryCheck::postSource() {
00256 updateAndPrint("module", "source", "source");
00257 }
00258
00259 void SimpleMemoryCheck::postModuleConstruction(ModuleDescription const& md) {
00260 updateAndPrint("ctor", md.moduleLabel(), md.moduleName());
00261 }
00262
00263 void SimpleMemoryCheck::postModuleBeginJob(ModuleDescription const& md) {
00264 updateAndPrint("beginJob", md.moduleLabel(), md.moduleName());
00265 }
00266
00267 void SimpleMemoryCheck::postEndJob() {
00268 if(not jobReportOutputOnly_) {
00269 LogAbsolute("MemoryReport")
00270 << "MemoryReport> Peak virtual size " << eventT1_.vsize << " Mbytes"
00271 << "\n"
00272 << " Key events increasing vsize: \n"
00273 << eventL2_ << "\n"
00274 << eventL1_ << "\n"
00275 << eventM_ << "\n"
00276 << eventR1_ << "\n"
00277 << eventR2_ << "\n"
00278 << eventT3_ << "\n"
00279 << eventT2_ << "\n"
00280 << eventT1_ ;
00281 }
00282 if(moduleSummaryRequested_ and not jobReportOutputOnly_) {
00283 LogAbsolute mmr("ModuleMemoryReport");
00284
00285
00286 mmr << "ModuleMemoryReport> Each line has module label and: \n";
00287 mmr << " (after early ignored events) \n";
00288 mmr <<
00289 " count of times module executed; average increase in vsize \n";
00290 mmr <<
00291 " maximum increase in vsize; event on which maximum occurred \n";
00292 mmr << " (during early ignored events) \n";
00293 mmr << " total and maximum vsize increases \n \n";
00294 for(SignificantModulesMap::iterator im = modules_.begin();
00295 im != modules_.end(); ++im) {
00296 SignificantModule const& m = im->second;
00297 if(m.totalDeltaVsize == 0 && m.totalEarlyVsize == 0) continue;
00298 mmr << im->first << ": ";
00299 mmr << "n = " << m.postEarlyCount;
00300 if(m.postEarlyCount > 0) {
00301 mmr << " avg = " << m.totalDeltaVsize/m.postEarlyCount;
00302 }
00303 mmr << " max = " << m.maxDeltaVsize << " " << m.eventMaxDeltaV;
00304 if(m.totalEarlyVsize > 0) {
00305 mmr << " early total: " << m.totalEarlyVsize;
00306 mmr << " max: " << m.maxEarlyVsize;
00307 }
00308 mmr << "\n";
00309 }
00310 }
00311
00312 Service<JobReport> reportSvc;
00313
00314 #define SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
00315 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
00316
00317 std::map<std::string, std::string> reportData;
00318
00319 if(eventL2_.vsize > 0)
00320 eventStatOutput("LargeVsizeIncreaseEventL2", eventL2_, reportData);
00321 if(eventL1_.vsize > 0)
00322 eventStatOutput("LargeVsizeIncreaseEventL1", eventL1_, reportData);
00323 if(eventM_.vsize > 0)
00324 eventStatOutput("LargestVsizeIncreaseEvent", eventM_, reportData);
00325 if(eventR1_.vsize > 0)
00326 eventStatOutput("LargeVsizeIncreaseEventR1", eventR1_, reportData);
00327 if(eventR2_.vsize > 0)
00328 eventStatOutput("LargeVsizeIncreaseEventR2", eventR2_, reportData);
00329 if(eventT3_.vsize > 0)
00330 eventStatOutput("ThirdLargestVsizeEventT3", eventT3_, reportData);
00331 if(eventT2_.vsize > 0)
00332 eventStatOutput("SecondLargestVsizeEventT2", eventT2_, reportData);
00333 if(eventT1_.vsize > 0)
00334 eventStatOutput("LargestVsizeEventT1", eventT1_, reportData);
00335
00336 if(eventRssT3_.rss > 0)
00337 eventStatOutput("ThirdLargestRssEvent", eventRssT3_, reportData);
00338 if(eventRssT2_.rss > 0)
00339 eventStatOutput("SecondLargestRssEvent", eventRssT2_, reportData);
00340 if(eventRssT1_.rss > 0)
00341 eventStatOutput("LargestRssEvent", eventRssT1_, reportData);
00342 if(eventDeltaRssT3_.deltaRss > 0)
00343 eventStatOutput("ThirdLargestIncreaseRssEvent", eventDeltaRssT3_, reportData);
00344 if(eventDeltaRssT2_.deltaRss > 0)
00345 eventStatOutput("SecondLargestIncreaseRssEvent", eventDeltaRssT2_, reportData);
00346 if(eventDeltaRssT1_.deltaRss > 0)
00347 eventStatOutput("LargestIncreaseRssEvent", eventDeltaRssT1_, reportData);
00348
00349 #ifdef __linux__
00350 struct mallinfo minfo = mallinfo();
00351 reportData.insert(
00352 std::make_pair("HEAP_ARENA_SIZE_BYTES", i2str(minfo.arena)));
00353 reportData.insert(
00354 std::make_pair("HEAP_ARENA_N_UNUSED_CHUNKS", i2str(minfo.ordblks)));
00355 reportData.insert(
00356 std::make_pair("HEAP_TOP_FREE_BYTES", i2str(minfo.keepcost)));
00357 reportData.insert(
00358 std::make_pair("HEAP_MAPPED_SIZE_BYTES", i2str(minfo.hblkhd)));
00359 reportData.insert(
00360 std::make_pair("HEAP_MAPPED_N_CHUNKS", i2str(minfo.hblks)));
00361 reportData.insert(
00362 std::make_pair("HEAP_USED_BYTES", i2str(minfo.uordblks)));
00363 reportData.insert(
00364 std::make_pair("HEAP_UNUSED_BYTES", i2str(minfo.fordblks)));
00365 #endif
00366
00367
00368 reportData.insert(
00369 std::make_pair("AverageGrowthRateVsize", d2str(averageGrowthRate(current_->vsize, growthRateVsize_, count_))));
00370 reportData.insert(
00371 std::make_pair("PeakValueVsize", d2str(eventT1_.vsize)));
00372 reportData.insert(
00373 std::make_pair("AverageGrowthRateRss", d2str(averageGrowthRate(current_->rss, growthRateRss_, count_))));
00374 reportData.insert(
00375 std::make_pair("PeakValueRss", d2str(eventRssT1_.rss)));
00376
00377 if(moduleSummaryRequested_) {
00378 for(SignificantModulesMap::iterator im = modules_.begin();
00379 im != modules_.end(); ++im) {
00380 SignificantModule const& m = im->second;
00381 if(m.totalDeltaVsize == 0 && m.totalEarlyVsize == 0) continue;
00382 std::string label = im->first+":";
00383 reportData.insert(std::make_pair(label+"PostEarlyCount", i2str(m.postEarlyCount)));
00384 if(m.postEarlyCount > 0) {
00385 reportData.insert(std::make_pair(label+"AverageDeltaVsize",
00386 d2str(m.totalDeltaVsize/m.postEarlyCount)));
00387 }
00388 reportData.insert(std::make_pair(label+"MaxDeltaVsize", d2str(m.maxDeltaVsize)));
00389 if(m.totalEarlyVsize > 0) {
00390 reportData.insert(std::make_pair(label+"TotalEarlyVsize", d2str(m.totalEarlyVsize)));
00391 reportData.insert(std::make_pair(label+"MaxEarlyDeltaVsize", d2str(m.maxEarlyVsize)));
00392 }
00393 }
00394 }
00395
00396 std::map<std::string, std::string> reportMemoryProperties;
00397
00398 if(FILE* fmeminfo = fopen("/proc/meminfo", "r")) {
00399 char buf[128];
00400 char space[] = " ";
00401 size_t value;
00402
00403 while(fgets(buf, sizeof(buf), fmeminfo)) {
00404 char* token = NULL;
00405 token = strtok(buf, space);
00406 if(token != NULL) {
00407 value = atol(strtok(NULL, space));
00408 std::string category = token;
00409 reportMemoryProperties.insert(std::make_pair(category.substr(0, strlen(token)-1), i2str(value)));
00410 }
00411 }
00412
00413 fclose(fmeminfo);
00414 }
00415
00416
00417 reportSvc->reportPerformanceSummary("ApplicationMemory", reportData);
00418 reportSvc->reportPerformanceSummary("SystemMemory", reportMemoryProperties);
00419 #endif
00420
00421 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT
00422 std::vector<std::string> reportData;
00423
00424 if(eventL2_.vsize > 0) reportData.push_back(
00425 eventStatOutput("LargeVsizeIncreaseEventL2", eventL2_));
00426 if(eventL1_.vsize > 0) reportData.push_back(
00427 eventStatOutput("LargeVsizeIncreaseEventL1", eventL1_));
00428 if(eventM_.vsize > 0) reportData.push_back(
00429 eventStatOutput("LargestVsizeIncreaseEvent", eventM_));
00430 if(eventR1_.vsize > 0) reportData.push_back(
00431 eventStatOutput("LargeVsizeIncreaseEventR1", eventR1_));
00432 if(eventR2_.vsize > 0) reportData.push_back(
00433 eventStatOutput("LargeVsizeIncreaseEventR2", eventR2_));
00434 if(eventT3_.vsize > 0) reportData.push_back(
00435 eventStatOutput("ThirdLargestVsizeEventT3", eventT3_));
00436 if(eventT2_.vsize > 0) reportData.push_back(
00437 eventStatOutput("SecondLargestVsizeEventT2", eventT2_));
00438 if(eventT1_.vsize > 0) reportData.push_back(
00439 eventStatOutput("LargestVsizeEventT1", eventT1_));
00440
00441 if(eventRssT3_.rss > 0)
00442 eventStatOutput("ThirdLargestRssEvent", eventRssT3_, reportData);
00443 if(eventRssT2_.rss > 0)
00444 eventStatOutput("SecondLargestRssEvent", eventRssT2_, reportData);
00445 if(eventRssT1_.rss > 0)
00446 eventStatOutput("LargestRssEvent", eventRssT1_, reportData);
00447 if(eventDeltaRssT3_.deltaRss > 0)
00448 eventStatOutput("ThirdLargestIncreaseRssEvent", eventDeltaRssT3_, reportData);
00449 if(eventDeltaRssT2_.deltaRss > 0)
00450 eventStatOutput("SecondLargestIncreaseRssEvent", eventDeltaRssT2_, reportData);
00451 if(eventDeltaRssT1_.deltaRss > 0)
00452 eventStatOutput("LargestIncreaseRssEvent", eventDeltaRssT1_, reportData);
00453
00454 struct mallinfo minfo = mallinfo();
00455 reportData.push_back(
00456 mallOutput("HEAP_ARENA_SIZE_BYTES", minfo.arena));
00457 reportData.push_back(
00458 mallOutput("HEAP_ARENA_N_UNUSED_CHUNKS", minfo.ordblks));
00459 reportData.push_back(
00460 mallOutput("HEAP_TOP_FREE_BYTES", minfo.keepcost));
00461 reportData.push_back(
00462 mallOutput("HEAP_MAPPED_SIZE_BYTES", minfo.hblkhd));
00463 reportData.push_back(
00464 mallOutput("HEAP_MAPPED_N_CHUNKS", minfo.hblks));
00465 reportData.push_back(
00466 mallOutput("HEAP_USED_BYTES", minfo.uordblks));
00467 reportData.push_back(
00468 mallOutput("HEAP_UNUSED_BYTES", minfo.fordblks));
00469
00470
00471 reportData.insert(
00472 std::make_pair("AverageGrowthRateVsize", d2str(averageGrowthRate(current_->vsize, growthRateVsize_, count_))));
00473 reportData.insert(
00474 std::make_pair("PeakValueVsize", d2str(eventT1_.vsize)));
00475 reportData.insert(
00476 std::make_pair("AverageGrowthRateRss", d2str(averageGrowthRate(current_->rss, growthRateRss_, count_))));
00477 reportData.insert(
00478 std::make_pair("PeakValueRss", d2str(eventRssT1_.rss)));
00479
00480 reportSvc->reportMemoryInfo(reportData);
00481
00482 #endif
00483 }
00484
00485 void SimpleMemoryCheck::preEventProcessing(EventID const& iID, Timestamp const&) {
00486 currentEventID_ = iID;
00487 }
00488
00489 void SimpleMemoryCheck::postEventProcessing(Event const& e, EventSetup const&) {
00490 ++count_;
00491 update();
00492 if (monitorPssAndPrivate_) {
00493 currentSmaps_ = fetchSmaps();
00494 }
00495 updateEventStats(e.id());
00496 if(oncePerEventMode_) {
00497
00498 updateMax();
00499 andPrint("event", "", "");
00500 }
00501 }
00502
00503 void SimpleMemoryCheck::preModule(ModuleDescription const&) {
00504 update();
00505 moduleEntryVsize_ = current_->vsize;
00506 }
00507
00508 void SimpleMemoryCheck::postModule(ModuleDescription const& md) {
00509 if(!oncePerEventMode_) {
00510 updateAndPrint("module", md.moduleLabel(), md.moduleName());
00511 } else if(moduleSummaryRequested_) {
00512 update();
00513 }
00514 if(moduleSummaryRequested_) {
00515 double dv = current_->vsize - moduleEntryVsize_;
00516 std::string label = md.moduleLabel();
00517 updateModuleMemoryStats (modules_[label], dv);
00518 }
00519 }
00520
00521 void SimpleMemoryCheck::postFork(unsigned int, unsigned int) {
00522 #ifdef LINUX
00523 if(0 != smapsFile_) {
00524 fclose(smapsFile_);
00525 }
00526 openFiles();
00527 #endif
00528 }
00529
00530 void SimpleMemoryCheck::update() {
00531 std::swap(current_, previous_);
00532 *current_ = fetch();
00533 }
00534
00535 void SimpleMemoryCheck::updateMax() {
00536 if((*current_ > max_) || oncePerEventMode_) {
00537 if(count_ >= num_to_skip_) {
00538 }
00539 max_ = *current_;
00540 }
00541 }
00542
00543 void SimpleMemoryCheck::updateEventStats(EventID const& e) {
00544 if(count_ < num_to_skip_) return;
00545 if(count_ == num_to_skip_) {
00546 eventT1_.set(0, 0, e, this);
00547 eventM_.set (0, 0, e, this);
00548 eventRssT1_.set(0, 0, e, this);
00549 eventDeltaRssT1_.set(0, 0, e, this);
00550 return;
00551 }
00552 double vsize = current_->vsize;
00553 double deltaVsize = vsize - eventT1_.vsize;
00554
00555
00556 if(vsize > eventT1_.vsize) {
00557 double deltaRss = current_->rss - eventT1_.rss;
00558 eventT3_ = eventT2_;
00559 eventT2_ = eventT1_;
00560 eventT1_.set(deltaVsize, deltaRss, e, this);
00561 } else if(vsize > eventT2_.vsize) {
00562 double deltaRss = current_->rss - eventT1_.rss;
00563 eventT3_ = eventT2_;
00564 eventT2_.set(deltaVsize, deltaRss, e, this);
00565 } else if(vsize > eventT3_.vsize) {
00566 double deltaRss = current_->rss - eventT1_.rss;
00567 eventT3_.set(deltaVsize, deltaRss, e, this);
00568 }
00569
00570 if(deltaVsize > eventM_.deltaVsize) {
00571 double deltaRss = current_->rss - eventM_.rss;
00572 if(eventL1_.deltaVsize >= eventR1_.deltaVsize) {
00573 eventL2_ = eventL1_;
00574 } else {
00575 eventL2_ = eventR1_;
00576 }
00577 eventL1_ = eventM_;
00578 eventM_.set(deltaVsize, deltaRss, e, this);
00579 eventR1_ = SignificantEvent();
00580 eventR2_ = SignificantEvent();
00581 } else if(deltaVsize > eventR1_.deltaVsize) {
00582 double deltaRss = current_->rss - eventM_.rss;
00583 eventR2_ = eventR1_;
00584 eventR1_.set(deltaVsize, deltaRss, e, this);
00585 } else if(deltaVsize > eventR2_.deltaVsize) {
00586 double deltaRss = current_->rss - eventR1_.rss;
00587 eventR2_.set(deltaVsize, deltaRss, e, this);
00588 }
00589
00590
00591 double rss = current_->rss;
00592 double deltaRss = rss - eventRssT1_.rss;
00593
00594 if(rss > eventRssT1_.rss) {
00595 eventRssT3_ = eventRssT2_;
00596 eventRssT2_ = eventRssT1_;
00597 eventRssT1_.set(deltaVsize, deltaRss, e, this);
00598 } else if(rss > eventRssT2_.rss) {
00599 eventRssT3_ = eventRssT2_;
00600 eventRssT2_.set(deltaVsize, deltaRss, e, this);
00601 } else if(rss > eventRssT3_.rss) {
00602 eventRssT3_.set(deltaVsize, deltaRss, e, this);
00603 }
00604 if(deltaRss > eventDeltaRssT1_.deltaRss) {
00605 eventDeltaRssT3_ = eventDeltaRssT2_;
00606 eventDeltaRssT2_ = eventDeltaRssT1_;
00607 eventDeltaRssT1_.set(deltaVsize, deltaRss, e, this);
00608 } else if(deltaRss > eventDeltaRssT2_.deltaRss) {
00609 eventDeltaRssT3_ = eventDeltaRssT2_;
00610 eventDeltaRssT2_.set(deltaVsize, deltaRss, e, this);
00611 } else if(deltaRss > eventDeltaRssT3_.deltaRss) {
00612 eventDeltaRssT3_.set(deltaVsize, deltaRss, e, this);
00613 }
00614 }
00615
00616 void SimpleMemoryCheck::andPrint(std::string const& type,
00617 std::string const& mdlabel, std::string const& mdname) const {
00618 if(not jobReportOutputOnly_ && ((*current_ > max_) || oncePerEventMode_)) {
00619 if(count_ >= num_to_skip_) {
00620 double deltaVSIZE = current_->vsize - max_.vsize;
00621 double deltaRSS = current_->rss - max_.rss;
00622 if(!showMallocInfo_) {
00623 LogWarning("MemoryCheck")
00624 << "MemoryCheck: " << type << " "
00625 << mdname << ":" << mdlabel
00626 << " VSIZE " << current_->vsize << " " << deltaVSIZE
00627 << " RSS " << current_->rss << " " << deltaRSS
00628 << "\n";
00629 } else {
00630 #ifdef __linux__
00631 struct mallinfo minfo = mallinfo();
00632 #endif
00633 LogWarning("MemoryCheck")
00634 << "MemoryCheck: " << type << " "
00635 << mdname << ":" << mdlabel
00636 << " VSIZE " << current_->vsize << " " << deltaVSIZE
00637 << " RSS " << current_->rss << " " << deltaRSS
00638 #ifdef __linux__
00639 << " HEAP-ARENA [ SIZE-BYTES " << minfo.arena
00640 << " N-UNUSED-CHUNKS " << minfo.ordblks
00641 << " TOP-FREE-BYTES " << minfo.keepcost << " ]"
00642 << " HEAP-MAPPED [ SIZE-BYTES " << minfo.hblkhd
00643 << " N-CHUNKS " << minfo.hblks << " ]"
00644 << " HEAP-USED-BYTES " << minfo.uordblks
00645 << " HEAP-UNUSED-BYTES " << minfo.fordblks
00646 #endif
00647 << "\n";
00648 }
00649 }
00650 }
00651 }
00652
00653 void SimpleMemoryCheck::updateAndPrint(std::string const& type,
00654 std::string const& mdlabel, std::string const& mdname) {
00655 update();
00656 andPrint(type, mdlabel, mdname);
00657 updateMax();
00658 }
00659
00660 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
00661 void
00662 SimpleMemoryCheck::eventStatOutput(std::string title,
00663 SignificantEvent const& e,
00664 std::map<std::string, std::string>& m) const {
00665 { std::ostringstream os;
00666 os << title << "-a-COUNT";
00667 m.insert(std::make_pair(os.str(), i2str(e.count))); }
00668 { std::ostringstream os;
00669 os << title << "-b-RUN";
00670 m.insert(std::make_pair(os.str(), d2str(static_cast<double>(e.event.run())))); }
00671 { std::ostringstream os;
00672 os << title << "-c-EVENT";
00673 m.insert(std::make_pair(os.str(), d2str(static_cast<double>(e.event.event())))); }
00674 { std::ostringstream os;
00675 os << title << "-d-VSIZE";
00676 m.insert(std::make_pair(os.str(), d2str(e.vsize))); }
00677 { std::ostringstream os;
00678 os << title << "-e-DELTV";
00679 m.insert(std::make_pair(os.str(), d2str(e.deltaVsize))); }
00680 { std::ostringstream os;
00681 os << title << "-f-RSS";
00682 m.insert(std::make_pair(os.str(), d2str(e.rss))); }
00683 if (monitorPssAndPrivate_) {
00684 { std::ostringstream os;
00685 os << title << "-g-PRIVATE";
00686 m.insert(std::make_pair(os.str(), d2str(e.privateSize))); }
00687 { std::ostringstream os;
00688 os << title << "-h-PSS";
00689 m.insert(std::make_pair(os.str(), d2str(e.pss))); }
00690 }
00691 }
00692 #endif
00693
00694 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT
00695 std::string
00696 SimpleMemoryCheck::eventStatOutput(std::string title,
00697 SignificantEvent const& e) const {
00698 std::ostringstream os;
00699 os << " <" << title << ">\n";
00700 os << " " << e.count << ": " << e.event;
00701 os << " vsize " << e.vsize-e.deltaVsize << " + " << e.deltaVsize
00702 << " = " << e.vsize;
00703 os << " rss: " << e.rss << "\n";
00704 os << " </" << title << ">\n";
00705 return os.str();
00706 }
00707
00708 std::string
00709 SimpleMemoryCheck::mallOutput(std::string title, size_t const& n) const {
00710 std::ostringstream os;
00711 os << " <" << title << ">\n";
00712 os << " " << n << "\n";
00713 os << " </" << title << ">\n";
00714 return os.str();
00715 }
00716 #endif
00717
00718 void
00719 SimpleMemoryCheck::updateModuleMemoryStats(SignificantModule& m,
00720 double dv) {
00721 if(count_ < num_to_skip_) {
00722 m.totalEarlyVsize += dv;
00723 if(dv > m.maxEarlyVsize) m.maxEarlyVsize = dv;
00724 } else {
00725 ++m.postEarlyCount;
00726 m.totalDeltaVsize += dv;
00727 if(dv > m.maxDeltaVsize) {
00728 m.maxDeltaVsize = dv;
00729 m.eventMaxDeltaV = currentEventID_;
00730 }
00731 }
00732 }
00733
00734 std::ostream&
00735 operator<< (std::ostream& os,
00736 SimpleMemoryCheck::SignificantEvent const& se) {
00737 os << "[" << se.count << "] "
00738 << se.event << " vsize = " << se.vsize
00739 << " deltaVsize = " << se.deltaVsize
00740 << " rss = " << se.rss << " delta = " << se.deltaRss;
00741
00742 if (se.monitorPssAndPrivate) {
00743 os <<" private = "<<se.privateSize<<" pss = "<<se.pss;
00744 }
00745 return os;
00746 }
00747
00748 std::ostream&
00749 operator<< (std::ostream& os,
00750 SimpleMemoryCheck::SignificantModule const& sm) {
00751 if(sm.postEarlyCount > 0) {
00752 os << "\nPost Early Events: TotalDeltaVsize: " << sm.totalDeltaVsize
00753 << " (avg: " << sm.totalDeltaVsize/sm.postEarlyCount
00754 << "; max: " << sm.maxDeltaVsize
00755 << " during " << sm.eventMaxDeltaV << ")";
00756 }
00757 if(sm.totalEarlyVsize > 0) {
00758 os << "\n Early Events: TotalDeltaVsize: " << sm.totalEarlyVsize
00759 << " (max: " << sm.maxEarlyVsize << ")";
00760 }
00761
00762 return os;
00763 }
00764
00765 }
00766 }
00767