167 vsize =
t->current_->vsize;
169 rss =
t->current_->rss;
174 pss =
t->currentSmaps_.pss_;
245 void set(
double deltaV,
bool early);
281 std::ostringstream
t;
287 std::ostringstream
t;
316 ret.private_ +=
static_cast<double>(
value) / 1024.;
320 ret.pss_ +=
static_cast<double>(
value) / 1024.;
329 return (current - past) / (double)
count;
337 pg_size_(sysconf(_SC_PAGESIZE))
339 num_to_skip_(iPS.getUntrackedParameter<
int>(
"ignoreTotal")),
340 showMallocInfo_(iPS.getUntrackedParameter<
bool>(
"showMallocInfo")),
341 oncePerEventMode_(iPS.getUntrackedParameter<
bool>(
"oncePerEventMode")),
342 printEachTime_(oncePerEventMode_
or iPS.getUntrackedParameter<
bool>(
"printEachSample")),
343 jobReportOutputOnly_(iPS.getUntrackedParameter<
bool>(
"jobReportOutputOnly")),
344 monitorPssAndPrivate_(iPS.getUntrackedParameter<
bool>(
"monitorPssAndPrivate")),
346 sampleEveryNSeconds_(iPS.getUntrackedParameter<unsigned
int>(
"sampleEveryNSeconds")),
348 smapsLineBuffer_(nullptr),
349 smapsLineBufferLen_(0),
352 moduleSummaryRequested_(iPS.getUntrackedParameter<
bool>(
"moduleMemorySummary")),
353 measurementUnderway_(
false) {
356 std::ostringstream ost;
363 <<
"'sampleEventNSeconds' and 'oncePerEventMode' cannot be used together";
367 <<
"'sampleEventNSeconds' and 'moduleSummaryRequested' cannot be used together";
421 desc.addUntracked<
int>(
"ignoreTotal", 1)
422 ->setComment(
"Number of events/samples to finish before starting measuring and reporting.");
423 desc.addUntracked<
unsigned int>(
"sampleEveryNSeconds", 0)
425 "Use a special thread to sample memory at the set rate. A value of 0 means no sampling. This option " 426 "cannot be used with 'oncePerEventMode' or 'moduleMemorySummary'.");
427 desc.addUntracked<
bool>(
"printEachSample",
false)
428 ->setComment(
"If sampling on, print each sample taken else will print only when sample is the largest seen.");
429 desc.addUntracked<
bool>(
"showMallocInfo",
false);
430 desc.addUntracked<
bool>(
"oncePerEventMode",
false)
432 "Only check memory at the end of each event. Not as useful in multi-threaded job as other running events " 434 desc.addUntracked<
bool>(
"jobReportOutputOnly",
false);
435 desc.addUntracked<
bool>(
"monitorPssAndPrivate",
false);
436 desc.addUntracked<
bool>(
"moduleMemorySummary",
false)
438 "Track significant memory events for each module. This does not work well in multi-threaded jobs.");
439 descriptions.
add(
"SimpleMemoryCheck",
desc);
445 std::ostringstream smapsNameOst;
446 smapsNameOst <<
"/proc/" << getpid() <<
"/smaps";
447 if ((
smapsFile_ = fopen(smapsNameOst.str().c_str(),
"r")) ==
nullptr) {
460 bool expected =
false;
462 std::shared_ptr<void> guard(
463 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
469 bool expected =
false;
471 std::shared_ptr<void> guard(
472 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
478 bool expected =
false;
480 std::shared_ptr<void> guard(
481 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
487 bool expected =
false;
489 std::shared_ptr<void> guard(
490 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
496 bool expected =
false;
498 std::shared_ptr<void> guard(
499 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
528 <<
"MemoryReport> Peak virtual size " <<
eventT1_.
vsize <<
" Mbytes" 530 <<
" Key events increasing vsize: \n" 540 "\n Key events increasing rss:\n" 553 mmr <<
"ModuleMemoryReport> Each line has module label and: \n";
554 mmr <<
" (after early ignored events) \n";
555 mmr <<
" count of times module executed; average increase in vsize \n";
556 mmr <<
" maximum increase in vsize; event on which maximum occurred \n";
557 mmr <<
" (during early ignored events) \n";
558 mmr <<
" total and maximum vsize increases \n \n";
559 for (SignificantModulesMap::iterator im =
modules_.begin(); im !=
modules_.end(); ++im) {
561 if (
m.totalDeltaVsize == 0 &&
m.totalEarlyVsize == 0)
563 mmr << im->first <<
": ";
564 mmr <<
"n = " <<
m.postEarlyCount;
565 if (
m.postEarlyCount > 0) {
566 mmr <<
" avg = " <<
m.totalDeltaVsize /
m.postEarlyCount;
568 mmr <<
" max = " <<
m.maxDeltaVsize <<
" " <<
m.eventMaxDeltaV;
569 if (
m.totalEarlyVsize > 0) {
570 mmr <<
" early total: " <<
m.totalEarlyVsize;
571 mmr <<
" max: " <<
m.maxEarlyVsize;
579 #define SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT 580 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT 582 std::map<std::string, std::string> reportData;
615 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 33) 616 struct mallinfo2 minfo = mallinfo2();
618 struct mallinfo minfo = mallinfo();
620 reportData.insert(std::make_pair(
"HEAP_ARENA_SIZE_BYTES",
std::to_string(minfo.arena)));
621 reportData.insert(std::make_pair(
"HEAP_ARENA_N_UNUSED_CHUNKS",
std::to_string(minfo.ordblks)));
622 reportData.insert(std::make_pair(
"HEAP_TOP_FREE_BYTES",
std::to_string(minfo.keepcost)));
623 reportData.insert(std::make_pair(
"HEAP_MAPPED_SIZE_BYTES",
std::to_string(minfo.hblkhd)));
624 reportData.insert(std::make_pair(
"HEAP_MAPPED_N_CHUNKS",
std::to_string(minfo.hblks)));
625 reportData.insert(std::make_pair(
"HEAP_USED_BYTES",
std::to_string(minfo.uordblks)));
626 reportData.insert(std::make_pair(
"HEAP_UNUSED_BYTES",
std::to_string(minfo.fordblks)));
630 reportData.insert(std::make_pair(
"AverageGrowthRateVsize",
638 for (SignificantModulesMap::iterator im =
modules_.begin(); im !=
modules_.end(); ++im) {
640 if (
m.totalDeltaVsize == 0 &&
m.totalEarlyVsize == 0)
643 reportData.insert(std::make_pair(
label +
"PostEarlyCount",
i2str(
m.postEarlyCount)));
644 if (
m.postEarlyCount > 0) {
645 reportData.insert(std::make_pair(
label +
"AverageDeltaVsize",
d2str(
m.totalDeltaVsize /
m.postEarlyCount)));
647 reportData.insert(std::make_pair(
label +
"MaxDeltaVsize",
d2str(
m.maxDeltaVsize)));
648 if (
m.totalEarlyVsize > 0) {
649 reportData.insert(std::make_pair(
label +
"TotalEarlyVsize",
d2str(
m.totalEarlyVsize)));
650 reportData.insert(std::make_pair(
label +
"MaxEarlyDeltaVsize",
d2str(
m.maxEarlyVsize)));
655 std::map<std::string, std::string> reportMemoryProperties;
657 if (FILE* fmeminfo = fopen(
"/proc/meminfo",
"r")) {
661 while (fgets(
buf,
sizeof(
buf), fmeminfo)) {
663 char*
token =
nullptr;
664 token = strtok_r(
buf, space, &saveptr);
665 if (
token !=
nullptr) {
666 value = atol(strtok_r(
nullptr, space, &saveptr));
676 reportSvc->reportPerformanceSummary(
"ApplicationMemory", reportData);
677 reportSvc->reportPerformanceSummary(
"SystemMemory", reportMemoryProperties);
680 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT 681 std::vector<std::string> reportData;
713 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 33) 714 struct mallinfo2 minfo = mallinfo2();
716 struct mallinfo minfo = mallinfo();
718 reportData.push_back(
mallOutput(
"HEAP_ARENA_SIZE_BYTES", minfo.arena));
719 reportData.push_back(
mallOutput(
"HEAP_ARENA_N_UNUSED_CHUNKS", minfo.ordblks));
720 reportData.push_back(
mallOutput(
"HEAP_TOP_FREE_BYTES", minfo.keepcost));
721 reportData.push_back(
mallOutput(
"HEAP_MAPPED_SIZE_BYTES", minfo.hblkhd));
722 reportData.push_back(
mallOutput(
"HEAP_MAPPED_N_CHUNKS", minfo.hblks));
723 reportData.push_back(
mallOutput(
"HEAP_USED_BYTES", minfo.uordblks));
724 reportData.push_back(
mallOutput(
"HEAP_UNUSED_BYTES", minfo.fordblks));
727 reportData.insert(std::make_pair(
"AverageGrowthRateVsize",
734 reportSvc->reportMemoryInfo(reportData);
741 bool expected =
false;
743 std::shared_ptr<void> guard(
744 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
759 bool expectedMeasurementUnderway =
false;
760 if (
measurementUnderway_.compare_exchange_strong(expectedMeasurementUnderway,
true, std::memory_order_acq_rel)) {
761 std::shared_ptr<void> guard(
762 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
763 bool expectedModuleMeasurementUnderway =
false;
777 bool expected =
false;
779 std::shared_ptr<void> guard(
780 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
792 std::shared_ptr<void> guardModuleMeasurementUnderway(
794 bool expected =
false;
796 std::shared_ptr<void> guardMeasurementUnderway(
797 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
909 LogWarning(
"MemoryCheck") <<
"MemoryCheck: " <<
type <<
" " << mdname <<
":" << mdlabel <<
" VSIZE " 914 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 33) 915 struct mallinfo2 minfo = mallinfo2();
917 struct mallinfo minfo = mallinfo();
920 LogWarning(
"MemoryCheck") <<
"MemoryCheck: " <<
type <<
" " << mdname <<
":" << mdlabel <<
" VSIZE " 924 <<
" HEAP-ARENA [ SIZE-BYTES " << minfo.arena <<
" N-UNUSED-CHUNKS " 925 << minfo.ordblks <<
" TOP-FREE-BYTES " << minfo.keepcost <<
" ]" 926 <<
" HEAP-MAPPED [ SIZE-BYTES " << minfo.hblkhd <<
" N-CHUNKS " << minfo.hblks
928 <<
" HEAP-USED-BYTES " << minfo.uordblks <<
" HEAP-UNUSED-BYTES " 945 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT 948 std::map<std::string, std::string>&
m)
const {
950 std::ostringstream
os;
952 m.insert(std::make_pair(
os.str(),
i2str(
e.count)));
955 std::ostringstream
os;
957 m.insert(std::make_pair(
os.str(),
d2str(static_cast<double>(
e.event.run()))));
960 std::ostringstream
os;
962 m.insert(std::make_pair(
os.str(),
d2str(static_cast<double>(
e.event.event()))));
965 std::ostringstream
os;
967 m.insert(std::make_pair(
os.str(),
d2str(
e.vsize)));
970 std::ostringstream
os;
972 m.insert(std::make_pair(
os.str(),
d2str(
e.deltaVsize)));
975 std::ostringstream
os;
977 m.insert(std::make_pair(
os.str(),
d2str(
e.rss)));
981 std::ostringstream
os;
983 m.insert(std::make_pair(
os.str(),
d2str(
e.privateSize)));
986 std::ostringstream
os;
988 m.insert(std::make_pair(
os.str(),
d2str(
e.pss)));
994 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT 996 std::ostringstream
os;
998 os <<
" " <<
e.count <<
": " <<
e.event;
999 os <<
" vsize " <<
e.vsize -
e.deltaVsize <<
" + " <<
e.deltaVsize <<
" = " <<
e.vsize;
1000 os <<
" rss: " <<
e.rss <<
"\n";
1001 os <<
" </" <<
title <<
">\n";
1006 std::ostringstream
os;
1008 os <<
" " <<
n <<
"\n";
1009 os <<
" </" <<
title <<
">\n";
1018 m.totalEarlyVsize += dv;
1019 if (dv >
m.maxEarlyVsize)
1020 m.maxEarlyVsize = dv;
1023 m.totalDeltaVsize += dv;
1024 if (dv >
m.maxDeltaVsize) {
1025 m.maxDeltaVsize = dv;
1026 m.eventMaxDeltaV = currentEventID;
1033 <<
" rss = " << se.
rss <<
" delta = " << se.
deltaRss;
1042 if (
sm.postEarlyCount > 0) {
1043 os <<
"\nPost Early Events: TotalDeltaVsize: " <<
sm.totalDeltaVsize
1044 <<
" (avg: " <<
sm.totalDeltaVsize /
sm.postEarlyCount <<
"; max: " <<
sm.maxDeltaVsize <<
" during " 1045 <<
sm.eventMaxDeltaV <<
")";
1047 if (
sm.totalEarlyVsize > 0) {
1048 os <<
"\n Early Events: TotalDeltaVsize: " <<
sm.totalEarlyVsize <<
" (max: " <<
sm.maxEarlyVsize <<
")";
1057 #if defined(__linux__)
void watchPostModuleConstruction(PostModuleConstruction::slot_type const &iSlot)
static std::string i2str(int i)
void watchPreEvent(PreEvent::slot_type const &iSlot)
SignificantEvent eventDeltaRssT1_
void preSourceConstruction(const ModuleDescription &)
std::atomic< bool > stopThread_
std::pair< ALIstring, ALIstring > pss
std::atomic< edm::EventID > mostRecentlyStartedEvent_
friend std::ostream & operator<<(std::ostream &os, SimpleMemoryCheck::SignificantEvent const &se)
size_t smapsLineBufferLen_
void watchPostEndJob(PostEndJob::slot_type const &iSlot)
edm::propagate_const< ProcInfo * > current_
std::atomic< bool > measurementUnderway_
SignificantEvent eventT1_
void watchPreModuleEvent(PreModuleEvent::slot_type const &iSlot)
void updateEventStats(edm::EventID const &e)
ProcInfoFetcher piFetcher_
ret
prodAgent to be discontinued
void watchPostEvent(PostEvent::slot_type const &iSlot)
std::atomic< bool > moduleMeasurementUnderway_
std::string eventStatOutput(std::string title, SignificantEvent const &e) const
void watchPreSourceConstruction(PreSourceConstruction::slot_type const &iSlot)
void watchPostSourceConstruction(PostSourceConstruction::slot_type const &iSlot)
SignificantEvent eventRssT2_
SignificantEvent eventL1_
void watchPostModuleEvent(PostModuleEvent::slot_type const &iSlot)
void watchPostSourceEvent(PostSourceEvent::slot_type const &iSlot)
std::string const & moduleName() const
SignificantEvent eventT3_
constexpr std::shared_ptr< T > & get_underlying_safe(propagate_const< std::shared_ptr< T >> &iP)
ModuleDescription const * moduleDescription() const noexcept
edm::EventID eventMaxDeltaV
void swap(Association< C > &lhs, Association< C > &rhs)
static std::string to_string(const XMLCh *ch)
std::atomic< unsigned int > moduleStreamID_
char *& smapsLineBuffer()
void free(void *ptr) noexcept
SignificantEvent eventRssT3_
edm::propagate_const< FILE * > smapsFile_
std::map< std::string, SignificantModule > SignificantModulesMap
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
StreamID const & streamID() const
bool operator==(const smapsInfo &p) const
friend struct SignificantEvent
std::ostream & operator<<(std::ostream &os, SimpleMemoryCheck::SignificantEvent const &se)
void set(double deltaV, double deltaR, edm::EventID const &e, SimpleMemoryCheck *t)
edm::propagate_const< ProcInfo * > previous_
bool monitorPssAndPrivate_
SignificantEvent eventR1_
SignificantEvent eventDeltaRssT3_
bool moduleSummaryRequested_
smapsInfo(double private_sz, double pss_sz)
bool jobReportOutputOnly_
#define DEFINE_FWK_SERVICE(type)
void updateAndPrint(const std::string &type, const std::string &mdlabel, const std::string &mdname)
void andPrint(const std::string &type, const std::string &mdlabel, const std::string &mdname) const
unsigned int sampleEveryNSeconds_
SignificantEvent eventR2_
void preModule(StreamContext const &, ModuleCallingContext const &)
char const * smapsLineBuffer() const
std::optional< std::thread > samplingThread_
static std::string d2str(double d)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void updateModuleMemoryStats(SignificantModule &m, double dv, edm::EventID const &)
void watchPreEndJob(PreEndJob::slot_type const &iSlot)
void startSamplingThread()
std::atomic< int > count_
SignificantEvent eventL2_
SignificantEvent eventDeltaRssT2_
void postEvent(StreamContext const &)
ALPAKA_FN_ACC int sm(int ieta, int iphi)
edm::propagate_const< char * > smapsLineBuffer_
EventID const & eventID() const
void watchPostModuleBeginJob(PostModuleBeginJob::slot_type const &iSlot)
void postSourceConstruction(const ModuleDescription &)
Log< level::System, true > LogAbsolute
SignificantEvent eventT2_
void postSourceEvent(StreamID)
void stopSamplingThread()
void postModuleBeginJob(const ModuleDescription &)
unsigned int value() const
std::string mallOutput(std::string title, size_t const &n) const
double averageGrowthRate(double current, double past, int count)
Log< level::Warning, false > LogWarning
SimpleMemoryCheck(const ParameterSet &, ActivityRegistry &)
bool operator>(const smapsInfo &p) const
SignificantModulesMap modules_
SignificantEvent eventRssT1_
void postModule(StreamContext const &, ModuleCallingContext const &)
std::string const & moduleLabel() const
void postModuleConstruction(const ModuleDescription &)
bool monitorPssAndPrivate
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void watchPostBeginJob(PostBeginJob::slot_type const &iSlot)
convenience function for attaching to signal
std::atomic< unsigned int > moduleID_