ENH: improvements in profiling (issue #648)

- include amount of free system memory in profiling, which can give an
  indication of when swapping is about to start

- profilingSummary utility to collect profiling from parallel
  calculations. Collects profiling information from processor
  directories and summarize the time spent and number of calls as (max
  avg min) values.
This commit is contained in:
Mark Olesen
2017-12-01 15:44:20 +01:00
parent e83a9db2ea
commit 8fc6bd17c9
15 changed files with 573 additions and 141 deletions

View File

@ -36,83 +36,14 @@ Foam::memInfo::memInfo()
:
peak_(0),
size_(0),
rss_(0)
rss_(0),
free_(0)
{
update();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::memInfo::~memInfo()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
//
// Parse the following type of content.
//
// ===========================
// VmPeak: 15920 kB
// VmSize: 15916 kB
// VmLck: 0 kB
// VmPin: 0 kB
// VmHWM: 6972 kB
// VmRSS: 6972 kB
// VmLib: 2208 kB
// VmPTE: 52 kB
// VmPMD: 12 kB
// VmSwap: 0 kB
const Foam::memInfo& Foam::memInfo::update()
{
// Clear (invalidate) values first
peak_ = size_ = rss_ = 0;
std::string line;
unsigned nKeys = 0;
std::ifstream is("/proc/" + std::to_string(Foam::pid()) + "/status");
while (is.good() && nKeys < 3) // Stop after getting the known keys
{
std::getline(is, line);
const auto keyLen = line.find(':');
if (keyLen == std::string::npos)
{
continue;
}
// Value is after the ':', but skip any leading whitespace since
// strtoi will do it anyhow
const auto begVal = line.find_first_not_of("\t :", keyLen);
if (begVal == std::string::npos)
{
continue;
}
const std::string key = line.substr(0, keyLen);
if (key == "VmPeak")
{
peak_ = std::stoi(line.substr(begVal));
++nKeys;
}
else if (key == "VmSize")
{
size_ = std::stoi(line.substr(begVal));
++nKeys;
}
else if (key == "VmRSS")
{
rss_ = std::stoi(line.substr(begVal));
++nKeys;
}
}
return *this;
}
bool Foam::memInfo::valid() const
{
@ -120,11 +51,116 @@ bool Foam::memInfo::valid() const
}
void Foam::memInfo::clear()
{
peak_ = size_ = rss_ = 0;
free_ = 0;
}
const Foam::memInfo& Foam::memInfo::update()
{
clear();
std::string line;
// "/proc/PID/status"
// ===========================
// VmPeak: 15920 kB
// VmSize: 15916 kB
// VmLck: 0 kB
// VmPin: 0 kB
// VmHWM: 6972 kB
// VmRSS: 6972 kB
// ...
// Stop parsing when known keys have been extracted
{
std::ifstream is("/proc/" + std::to_string(Foam::pid()) + "/status");
for
(
unsigned nkeys = 3;
nkeys && is.good() && std::getline(is, line);
/*nil*/
)
{
const auto delim = line.find(':');
if (delim == std::string::npos)
{
continue;
}
const std::string key(line.substr(0, delim));
// std::stoi() skips whitespace before using as many digits as
// possible. So just need to skip over the ':' and let stoi do
// the rest
if (key == "VmPeak")
{
peak_ = std::stoi(line.substr(delim+1));
--nkeys;
}
else if (key == "VmSize")
{
size_ = std::stoi(line.substr(delim+1));
--nkeys;
}
else if (key == "VmRSS")
{
rss_ = std::stoi(line.substr(delim+1));
--nkeys;
}
}
}
// "/proc/meminfo"
// ===========================
// MemTotal: 65879268 kB
// MemFree: 51544256 kB
// MemAvailable: 58999636 kB
// Buffers: 2116 kB
// ...
// Stop parsing when known keys have been extracted
{
std::ifstream is("/proc/meminfo");
for
(
unsigned nkeys = 1;
nkeys && is.good() && std::getline(is, line);
/*nil*/
)
{
const auto delim = line.find(':');
if (delim == std::string::npos)
{
continue;
}
const std::string key = line.substr(0, delim);
// std::stoi() skips whitespace before using as many digits as
// possible. So just need to skip over the ':' and let stoi do
// the rest
if (key == "MemFree")
{
free_ = std::stoi(line.substr(delim+1));
--nkeys;
}
}
}
return *this;
}
void Foam::memInfo::write(Ostream& os) const
{
os.writeEntry("size", size_);
os.writeEntry("peak", peak_);
os.writeEntry("rss", rss_);
os.writeEntry("free", free_);
}
@ -133,7 +169,7 @@ void Foam::memInfo::write(Ostream& os) const
Foam::Istream& Foam::operator>>(Istream& is, memInfo& m)
{
is.readBegin("memInfo");
is >> m.peak_ >> m.size_ >> m.rss_;
is >> m.peak_ >> m.size_ >> m.rss_ >> m.free_;
is.readEnd("memInfo");
is.check(FUNCTION_NAME);
@ -146,7 +182,8 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const memInfo& m)
os << token::BEGIN_LIST
<< m.peak_ << token::SPACE
<< m.size_ << token::SPACE
<< m.rss_
<< m.rss_ << token::SPACE
<< m.free_
<< token::END_LIST;
os.check(FUNCTION_NAME);

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -25,10 +25,11 @@ Class
Foam::memInfo
Description
Memory usage information for the process running this object.
Memory usage information for the current process, and the system memory
that is free.
Note
Uses the information from /proc/PID/status
Uses the information from /proc/PID/status and from /proc/meminfo
SourceFiles
memInfo.C
@ -69,26 +70,33 @@ class memInfo
//- Resident set size of the process (VmRSS in /proc/PID/status)
int rss_;
//- System memory free (MemFree in /proc/meminfo)
int free_;
public:
// Constructors
//- Construct null
//- Construct and populate with values
memInfo();
//- Destructor
~memInfo();
~memInfo() = default;
// Member Functions
//- Update according to /proc/PID/status contents
//- True if the memory information appears valid
bool valid() const;
//- Reset to zero
void clear();
//- Update according to /proc/PID/status and /proc/memory contents
const memInfo& update();
// Access
//- Peak memory (VmPeak in /proc/PID/status) at last update()
inline int peak() const
{
@ -107,8 +115,11 @@ public:
return rss_;
}
//- True if the memory information appears valid
bool valid() const;
//- System memory free (MemFree in /proc/meminfo)
inline int free() const
{
return free_;
}
// Write