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