55 #include <boost/lexical_cast.hpp>
164 vsize =
t->current_->vsize;
166 rss =
t->current_->rss;
171 pss =
t->currentSmaps_.pss_;
242 void set(
double deltaV,
bool early);
278 std::ostringstream
t;
284 std::ostringstream
t;
313 ret.private_ += static_cast<double>(
value) / 1024.;
317 ret.pss_ += static_cast<double>(
value) / 1024.;
326 return (current - past) / (double)
count;
334 pg_size_(sysconf(_SC_PAGESIZE))
336 num_to_skip_(iPS.getUntrackedParameter<
int>(
"ignoreTotal")),
337 showMallocInfo_(iPS.getUntrackedParameter<
bool>(
"showMallocInfo")),
338 oncePerEventMode_(iPS.getUntrackedParameter<
bool>(
"oncePerEventMode")),
339 jobReportOutputOnly_(iPS.getUntrackedParameter<
bool>(
"jobReportOutputOnly")),
340 monitorPssAndPrivate_(iPS.getUntrackedParameter<
bool>(
"monitorPssAndPrivate")),
343 smapsLineBuffer_(nullptr),
344 smapsLineBufferLen_(0),
347 moduleSummaryRequested_(iPS.getUntrackedParameter<
bool>(
"moduleMemorySummary")),
348 measurementUnderway_(
false) {
351 std::ostringstream ost;
385 #ifndef __SANITIZE_ADDRESS__
411 LogWarning(
"MemoryCheck") <<
"Malloc options: " << mo <<
"\n";
430 desc.addUntracked<
int>(
"ignoreTotal", 1);
431 desc.addUntracked<
bool>(
"showMallocInfo",
false);
432 desc.addUntracked<
bool>(
"oncePerEventMode",
false);
433 desc.addUntracked<
bool>(
"jobReportOutputOnly",
false);
434 desc.addUntracked<
bool>(
"monitorPssAndPrivate",
false);
435 desc.addUntracked<
bool>(
"moduleMemorySummary",
false);
436 desc.addUntracked<
int>(
"M_MMAP_MAX", -1);
437 desc.addUntracked<
int>(
"M_TRIM_THRESHOLD", -1);
438 desc.addUntracked<
int>(
"M_TOP_PAD", -1);
439 desc.addUntracked<
int>(
"M_MMAP_THRESHOLD", -1);
440 desc.addUntracked<
bool>(
"dump",
false);
441 descriptions.
add(
"SimpleMemoryCheck",
desc);
447 std::ostringstream smapsNameOst;
448 smapsNameOst <<
"/proc/" << getpid() <<
"/smaps";
449 if ((
smapsFile_ = fopen(smapsNameOst.str().c_str(),
"r")) ==
nullptr) {
462 bool expected =
false;
464 std::shared_ptr<void> guard(
465 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
471 bool expected =
false;
473 std::shared_ptr<void> guard(
474 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
480 bool expected =
false;
482 std::shared_ptr<void> guard(
483 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
489 bool expected =
false;
491 std::shared_ptr<void> guard(
492 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
498 bool expected =
false;
500 std::shared_ptr<void> guard(
501 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
509 <<
"MemoryReport> Peak virtual size " <<
eventT1_.
vsize <<
" Mbytes"
511 <<
" Key events increasing vsize: \n"
525 mmr <<
"ModuleMemoryReport> Each line has module label and: \n";
526 mmr <<
" (after early ignored events) \n";
527 mmr <<
" count of times module executed; average increase in vsize \n";
528 mmr <<
" maximum increase in vsize; event on which maximum occurred \n";
529 mmr <<
" (during early ignored events) \n";
530 mmr <<
" total and maximum vsize increases \n \n";
531 for (SignificantModulesMap::iterator im =
modules_.begin(); im !=
modules_.end(); ++im) {
533 if (
m.totalDeltaVsize == 0 &&
m.totalEarlyVsize == 0)
535 mmr << im->first <<
": ";
536 mmr <<
"n = " <<
m.postEarlyCount;
537 if (
m.postEarlyCount > 0) {
538 mmr <<
" avg = " <<
m.totalDeltaVsize /
m.postEarlyCount;
540 mmr <<
" max = " <<
m.maxDeltaVsize <<
" " <<
m.eventMaxDeltaV;
541 if (
m.totalEarlyVsize > 0) {
542 mmr <<
" early total: " <<
m.totalEarlyVsize;
543 mmr <<
" max: " <<
m.maxEarlyVsize;
551 #define SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
552 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
554 std::map<std::string, std::string> reportData;
587 struct mallinfo minfo = mallinfo();
588 reportData.insert(std::make_pair(
"HEAP_ARENA_SIZE_BYTES",
i2str(minfo.arena)));
589 reportData.insert(std::make_pair(
"HEAP_ARENA_N_UNUSED_CHUNKS",
i2str(minfo.ordblks)));
590 reportData.insert(std::make_pair(
"HEAP_TOP_FREE_BYTES",
i2str(minfo.keepcost)));
591 reportData.insert(std::make_pair(
"HEAP_MAPPED_SIZE_BYTES",
i2str(minfo.hblkhd)));
592 reportData.insert(std::make_pair(
"HEAP_MAPPED_N_CHUNKS",
i2str(minfo.hblks)));
593 reportData.insert(std::make_pair(
"HEAP_USED_BYTES",
i2str(minfo.uordblks)));
594 reportData.insert(std::make_pair(
"HEAP_UNUSED_BYTES",
i2str(minfo.fordblks)));
598 reportData.insert(std::make_pair(
"AverageGrowthRateVsize",
606 for (SignificantModulesMap::iterator im =
modules_.begin(); im !=
modules_.end(); ++im) {
608 if (
m.totalDeltaVsize == 0 &&
m.totalEarlyVsize == 0)
611 reportData.insert(std::make_pair(
label +
"PostEarlyCount",
i2str(
m.postEarlyCount)));
612 if (
m.postEarlyCount > 0) {
613 reportData.insert(std::make_pair(
label +
"AverageDeltaVsize",
d2str(
m.totalDeltaVsize /
m.postEarlyCount)));
615 reportData.insert(std::make_pair(
label +
"MaxDeltaVsize",
d2str(
m.maxDeltaVsize)));
616 if (
m.totalEarlyVsize > 0) {
617 reportData.insert(std::make_pair(
label +
"TotalEarlyVsize",
d2str(
m.totalEarlyVsize)));
618 reportData.insert(std::make_pair(
label +
"MaxEarlyDeltaVsize",
d2str(
m.maxEarlyVsize)));
623 std::map<std::string, std::string> reportMemoryProperties;
625 if (FILE* fmeminfo = fopen(
"/proc/meminfo",
"r")) {
629 while (fgets(
buf,
sizeof(
buf), fmeminfo)) {
631 char*
token =
nullptr;
632 token = strtok_r(
buf, space, &saveptr);
633 if (
token !=
nullptr) {
634 value = atol(strtok_r(
nullptr, space, &saveptr));
644 reportSvc->reportPerformanceSummary(
"ApplicationMemory", reportData);
645 reportSvc->reportPerformanceSummary(
"SystemMemory", reportMemoryProperties);
648 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT
649 std::vector<std::string> reportData;
681 struct mallinfo minfo = mallinfo();
682 reportData.push_back(
mallOutput(
"HEAP_ARENA_SIZE_BYTES", minfo.arena));
683 reportData.push_back(
mallOutput(
"HEAP_ARENA_N_UNUSED_CHUNKS", minfo.ordblks));
684 reportData.push_back(
mallOutput(
"HEAP_TOP_FREE_BYTES", minfo.keepcost));
685 reportData.push_back(
mallOutput(
"HEAP_MAPPED_SIZE_BYTES", minfo.hblkhd));
686 reportData.push_back(
mallOutput(
"HEAP_MAPPED_N_CHUNKS", minfo.hblks));
687 reportData.push_back(
mallOutput(
"HEAP_USED_BYTES", minfo.uordblks));
688 reportData.push_back(
mallOutput(
"HEAP_UNUSED_BYTES", minfo.fordblks));
691 reportData.insert(std::make_pair(
"AverageGrowthRateVsize",
698 reportSvc->reportMemoryInfo(reportData);
705 bool expected =
false;
707 std::shared_ptr<void> guard(
708 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
723 bool expectedMeasurementUnderway =
false;
724 if (
measurementUnderway_.compare_exchange_strong(expectedMeasurementUnderway,
true, std::memory_order_acq_rel)) {
725 std::shared_ptr<void> guard(
726 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
727 bool expectedModuleMeasurementUnderway =
false;
741 bool expected =
false;
743 std::shared_ptr<void> guard(
744 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
756 std::shared_ptr<void> guardModuleMeasurementUnderway(
758 bool expected =
false;
760 std::shared_ptr<void> guardMeasurementUnderway(
761 nullptr, [
this](
void const*) {
measurementUnderway_.store(
false, std::memory_order_release); });
869 LogWarning(
"MemoryCheck") <<
"MemoryCheck: " <<
type <<
" " << mdname <<
":" << mdlabel <<
" VSIZE "
874 struct mallinfo minfo = mallinfo();
876 LogWarning(
"MemoryCheck") <<
"MemoryCheck: " <<
type <<
" " << mdname <<
":" << mdlabel <<
" VSIZE "
880 <<
" HEAP-ARENA [ SIZE-BYTES " << minfo.arena <<
" N-UNUSED-CHUNKS "
881 << minfo.ordblks <<
" TOP-FREE-BYTES " << minfo.keepcost <<
" ]"
882 <<
" HEAP-MAPPED [ SIZE-BYTES " << minfo.hblkhd <<
" N-CHUNKS " << minfo.hblks
884 <<
" HEAP-USED-BYTES " << minfo.uordblks <<
" HEAP-UNUSED-BYTES "
901 #ifdef SIMPLE_MEMORY_CHECK_ORIGINAL_XML_OUTPUT
904 std::map<std::string, std::string>&
m)
const {
906 std::ostringstream os;
907 os <<
title <<
"-a-COUNT";
908 m.insert(std::make_pair(os.str(),
i2str(
e.count)));
911 std::ostringstream os;
912 os <<
title <<
"-b-RUN";
913 m.insert(std::make_pair(os.str(),
d2str(static_cast<double>(
e.event.run()))));
916 std::ostringstream os;
917 os <<
title <<
"-c-EVENT";
918 m.insert(std::make_pair(os.str(),
d2str(static_cast<double>(
e.event.event()))));
921 std::ostringstream os;
922 os <<
title <<
"-d-VSIZE";
923 m.insert(std::make_pair(os.str(),
d2str(
e.vsize)));
926 std::ostringstream os;
927 os <<
title <<
"-e-DELTV";
928 m.insert(std::make_pair(os.str(),
d2str(
e.deltaVsize)));
931 std::ostringstream os;
932 os <<
title <<
"-f-RSS";
933 m.insert(std::make_pair(os.str(),
d2str(
e.rss)));
937 std::ostringstream os;
938 os <<
title <<
"-g-PRIVATE";
939 m.insert(std::make_pair(os.str(),
d2str(
e.privateSize)));
942 std::ostringstream os;
943 os <<
title <<
"-h-PSS";
944 m.insert(std::make_pair(os.str(),
d2str(
e.pss)));
950 #ifdef SIMPLE_MEMORY_CHECK_DIFFERENT_XML_OUTPUT
952 std::ostringstream os;
953 os <<
" <" <<
title <<
">\n";
954 os <<
" " <<
e.count <<
": " <<
e.event;
955 os <<
" vsize " <<
e.vsize -
e.deltaVsize <<
" + " <<
e.deltaVsize <<
" = " <<
e.vsize;
956 os <<
" rss: " <<
e.rss <<
"\n";
957 os <<
" </" <<
title <<
">\n";
962 std::ostringstream os;
963 os <<
" <" <<
title <<
">\n";
964 os <<
" " <<
n <<
"\n";
965 os <<
" </" <<
title <<
">\n";
974 m.totalEarlyVsize += dv;
975 if (dv >
m.maxEarlyVsize)
976 m.maxEarlyVsize = dv;
979 m.totalDeltaVsize += dv;
980 if (dv >
m.maxDeltaVsize) {
981 m.maxDeltaVsize = dv;
982 m.eventMaxDeltaV = currentEventID;
989 <<
" rss = " << se.
rss <<
" delta = " << se.
deltaRss;
1013 #if defined(__linux__)