Commit 6b9d6c17 authored by mark's avatar mark
Browse files

ENH: add some system information when outputting profiling

- basic cpuInfo (model identification, MHz, etc)
- process memInfo

- profiling is activated via the case system/controlDict by
  adding a "profiling" sub-dictionary.

  Simply add the following (everything enabled):

      profiling
      {}

  Which corresponds to the longer form:

      profiling
      {
          active      true;  // default: true
          cpuInfo     true;  // default: true
          memInfo     true;  // default: true
          sysInfo     true;  // default: true
      }

  This can be used to selectively disable any extra information
  (eg, you don't want anyone else to know what hardware was used).
parent 9afc8dbb
Test-sysInfo.C
EXE = $(FOAM_USER_APPBIN)/Test-sysInfo
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Description
\*---------------------------------------------------------------------------*/
#include "ProfilingSysInfo.H"
#include "IOstreams.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
Profiling::sysInfo().write(Info);
return 0;
}
// ************************************************************************* //
......@@ -4,6 +4,7 @@ global/global.Cver
global/argList/argList.C
global/clock/clock.C
global/profiling/Profiling.C
global/profiling/ProfilingSysInfo.C
bools = primitives/bools
$(bools)/bool/bool.C
......
......@@ -337,10 +337,17 @@ void Foam::Time::setControls()
void Foam::Time::setMonitoring()
{
// initialize profiling on request
if (controlDict_.lookupOrDefault<Switch>("profiling", false))
// skip if 'active' keyword is explicitly set to false
const dictionary* profilingDict = controlDict_.subDictPtr("profiling");
if
(
profilingDict
&& profilingDict->lookupOrDefault<Switch>("active", true)
)
{
Profiling::initialize
(
*profilingDict,
IOobject
(
"profiling",
......
......@@ -24,8 +24,13 @@ License
\*---------------------------------------------------------------------------*/
#include "Profiling.H"
#include "ProfilingSysInfo.H"
#include "cpuInfo.H"
#include "memInfo.H"
#include "OSspecific.H"
#include "IOstreams.H"
#include "dictionary.H"
#include "demandDrivenData.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
......@@ -36,6 +41,17 @@ Foam::label Foam::Profiling::Information::nextId_(0);
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// file-scope function
template<class T>
inline static void writeEntry
(
Foam::Ostream& os, const Foam::word& key, const T& value
)
{
os.writeKeyword(key) << value << Foam::token::END_STATEMENT << '\n';
}
Foam::label Foam::Profiling::Information::getNextId()
{
return nextId_++;
......@@ -72,6 +88,34 @@ void Foam::Profiling::initialize
);
pool_->push(info, pool_->clockTime_);
Info<< "Profiling initialized" << nl;
}
}
void Foam::Profiling::initialize
(
const dictionary& dict,
const IOobject& ioObj,
const Time& owner
)
{
if (pool_)
{
WarningInFunction
<< "Already initialized" << endl;
}
else
{
pool_ = new Profiling(dict, ioObj, owner);
Information *info = pool_->store
(
new Information()
);
pool_->push(info, pool_->clockTime_);
Info<< "Profiling initialized" << nl;
}
}
......@@ -146,7 +190,41 @@ Foam::Profiling::Profiling
clockTime_(),
hash_(),
stack_(),
timers_()
timers_(),
sysInfo_(new sysInfo()),
cpuInfo_(new cpuInfo()),
memInfo_(new memInfo())
{}
Foam::Profiling::Profiling
(
const dictionary& dict,
const IOobject& io,
const Time& owner
)
:
regIOobject(io),
owner_(owner),
clockTime_(),
hash_(),
stack_(),
timers_(),
sysInfo_
(
dict.lookupOrDefault<Switch>("sysInfo", true)
? new sysInfo() : 0
),
cpuInfo_
(
dict.lookupOrDefault<Switch>("cpuInfo", true)
? new cpuInfo() : 0
),
memInfo_
(
dict.lookupOrDefault<Switch>("memInfo", true)
? new memInfo() : 0
)
{}
......@@ -196,6 +274,10 @@ Foam::Profiling::Trigger::Trigger(const string& name)
Foam::Profiling::~Profiling()
{
deleteDemandDrivenData(sysInfo_);
deleteDemandDrivenData(cpuInfo_);
deleteDemandDrivenData(memInfo_);
if (pool_ == this)
{
pool_ = 0;
......@@ -281,6 +363,34 @@ bool Foam::Profiling::writeData(Ostream& os) const
os << decrIndent
<< indent << token::END_LIST << token::END_STATEMENT << nl;
if (sysInfo_)
{
os << nl;
os.beginBlock("sysInfo") << nl; // FUTURE: without nl
sysInfo_->write(os);
os.endBlock() << nl; // FUTURE: without nl
}
if (cpuInfo_)
{
os << nl;
os.beginBlock("cpuInfo") << nl; // FUTURE: without nl
cpuInfo_->write(os);
os.endBlock() << nl; // FUTURE: without nl
}
if (memInfo_)
{
memInfo_->update();
os << nl;
os.beginBlock("memInfo") << nl; // FUTURE: without nl
memInfo_->write(os);
writeEntry(os, "units", "kB");
os.endBlock() << nl; // FUTURE: without nl
}
return os;
}
......@@ -312,6 +422,12 @@ Foam::Profiling::Information* Foam::Profiling::pop()
}
bool Foam::Profiling::Trigger::running() const
{
return ptr_;
}
void Foam::Profiling::Trigger::stop()
{
if (ptr_)
......@@ -324,14 +440,15 @@ void Foam::Profiling::Trigger::stop()
}
// file-scope function
template<class T>
inline static void writeEntry
(
Foam::Ostream& os, const Foam::word& key, const T& value
)
void Foam::Profiling::Information::push() const
{
os.writeKeyword(key) << value << Foam::token::END_STATEMENT << '\n';
onStack_ = true;
}
void Foam::Profiling::Information::pop() const
{
onStack_ = false;
}
......@@ -366,6 +483,7 @@ Foam::Ostream& Foam::Profiling::Information::write
return os;
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<
......
......@@ -27,6 +27,22 @@ Class
Description
Code profiling.
This is typically activated from within the system/controlDict as follows:
\code
profiling
{
active true; // default: true
cpuInfo true; // default: true
memInfo true; // default: true
sysInfo true; // default: true
}
\endcode
or simply using all defaults:
\code
profiling
{}
\endcode
SourceFiles
Profiling.C
......@@ -48,6 +64,9 @@ namespace Foam
// Forward declaration of classes
class Ostream;
class dictionary;
class cpuInfo;
class memInfo;
/*---------------------------------------------------------------------------*\
Class Profiling Declaration
......@@ -63,6 +82,7 @@ public:
class Information;
class Trigger;
class sysInfo;
private:
......@@ -93,6 +113,15 @@ private:
//- Note the timers (by Id) for the correct stack-output
Map<clockTime*> timers_;
//- General system information (optional)
sysInfo* sysInfo_;
//- CPU-Information (optional)
cpuInfo* cpuInfo_;
//- MEM-Information (optional)
memInfo* memInfo_;
// Private Member Functions
......@@ -112,9 +141,12 @@ protected:
// Constructors
//- Construct IO object
//- Construct IO object, everything enabled
Profiling(const IOobject&, const Time&);
//- Construct IO object with finer control over behaviour
Profiling(const dictionary&, const IOobject&, const Time&);
//- Destructor
~Profiling();
......@@ -139,9 +171,12 @@ protected:
// Static control elements
//- Singleton to initialize profiling pool
//- Singleton to initialize profiling pool, everything enabled
static void initialize(const IOobject&, const Time&);
//- Singleton to initialize profiling pool with finer control
static void initialize(const dictionary&, const IOobject&, const Time&);
//- Stop profiling, cleanup pool if possible
static void stop(const Time&);
......@@ -243,17 +278,10 @@ protected:
// Member Functions
//- Mark as being on the stack
void push() const
{
onStack_ = true;
}
void push() const;
//- Mark as being off the stack
void pop() const
{
onStack_ = false;
}
void pop() const;
//- Write the profiling times, optionally with additional values
......@@ -382,10 +410,7 @@ public:
// Access
//- True if the triggered profiling is active
inline bool running() const
{
return ptr_;
}
bool running() const;
// Edit
......
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "ProfilingSysInfo.H"
#include "demandDrivenData.H"
#include "foamVersion.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// file-scope function
template<class T>
inline static void writeEntry
(
Foam::Ostream& os, const Foam::word& key, const T& value
)
{
os.writeKeyword(key) << value << Foam::token::END_STATEMENT << '\n';
}
// file-scope function
inline static void printEnv
(
Foam::Ostream& os, const Foam::word& key, const Foam::word& envName
)
{
const std::string value = getEnv(envName);
if (!value.empty())
{
writeEntry(os, key, value);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::Profiling::sysInfo::sysInfo()
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::Profiling::sysInfo::~sysInfo()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::Ostream& Foam::Profiling::sysInfo::write
(
Ostream& os
) const
{
writeEntry(os, "host", hostName(false)); // short name
writeEntry(os, "date", clock::dateTime());
// compile-time information
writeEntry(os, "version", std::string(FOAMversion));
writeEntry(os, "build", std::string(FOAMbuild));
printEnv(os, "arch", "WM_ARCH");
printEnv(os, "compilerType", "WM_COMPILER_TYPE");
printEnv(os, "compiler", "WM_COMPILER");
printEnv(os, "mplib", "WM_MPLIB");
printEnv(os, "options", "WM_OPTIONS");
return os;
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::Profiling::SysInfo
Description
General system information
SourceFiles
ProfilingSysInfo.C
\*---------------------------------------------------------------------------*/
#ifndef ProfilingSysInfo_H
#define ProfilingSysInfo_H
#include "Profiling.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class Ostream;
/*---------------------------------------------------------------------------*\
Class Profiling::sysInfo Declaration
\*---------------------------------------------------------------------------*/
class Profiling::sysInfo
{
// Private Static Data Members
// Private Data Members
// Private Member Functions
//- Disallow default bitwise copy construct
sysInfo(const sysInfo&) = delete;
//- Disallow default bitwise assignment
void operator=(const sysInfo&) = delete;
protected:
// Friendship
friend class Profiling;
// Member Functions
public:
// Constructors
//- Construct from components
sysInfo();
//- Destructor
~sysInfo();
// Member Functions
// Access
// Edit
//- Update it with a new timing information
void update();
//- Write the profiling times, optionally with additional values
// Use dictionary format.
Ostream& write(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment