Commit fa10d97b authored by Mark Olesen's avatar Mark Olesen
Browse files

COMP: avoid nested classes for profiling (related to issue #441)

- nested classes can't be forward declared and thus less flexible
  than desired
parent 27776b09
......@@ -4,7 +4,9 @@ global/global.Cver
global/argList/argList.C
global/clock/clock.C
global/profiling/profiling.C
global/profiling/profilingInformation.C
global/profiling/profilingSysInfo.C
global/profiling/profilingTrigger.C
global/etcFiles/etcFiles.C
bools = primitives/bools
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2009-2016 Bernhard Gschaider
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -24,38 +24,53 @@ License
\*---------------------------------------------------------------------------*/
#include "profiling.H"
#include "profilingInformation.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 * * * * * * * * * * * * * //
Foam::profiling* Foam::profiling::pool_(0);
Foam::label Foam::profiling::Information::nextId_(0);
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::profilingInformation* Foam::profiling::find(const string& name)
{
StorageContainer::iterator iter = hash_.find(name);
return (iter != hash_.end() ? iter() : 0);
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::label Foam::profiling::Information::getNextId()
Foam::profilingInformation* Foam::profiling::store(profilingInformation *info)
{
return nextId_++;
hash_.insert(info->description(), info);
return info;
}
void Foam::profiling::Information::raiseID(label maxVal)
void Foam::profiling::push(profilingInformation *info, clockTime& timer)
{
if (nextId_ < maxVal)
{
nextId_ = maxVal;
}
stack_.push(info);
timers_.set(info->id(), &timer);
info->push(); // mark as on stack
}
Foam::profilingInformation* Foam::profiling::pop()
{
profilingInformation *info = stack_.pop();
timers_.erase(info->id());
info->pop(); // mark as off stack
return info;
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
bool Foam::profiling::active()
{
return pool_;
......@@ -98,17 +113,17 @@ void Foam::profiling::initialize
{
pool_ = new profiling(ioObj, owner);
Information *info = pool_->store
profilingInformation *info = pool_->store
(
new Information()
new profilingInformation()
);
pool_->push(info, pool_->clockTime_);
Info<< "profiling initialized" << nl;
}
// silently ignore multiple initialization
// eg, decomposePar use multiple simultaneous Times
// silently ignore multiple initializations
// eg, decomposePar uses multiple simultaneous Times
}
......@@ -123,17 +138,17 @@ void Foam::profiling::initialize
{
pool_ = new profiling(dict, ioObj, owner);
Information *info = pool_->store
profilingInformation *info = pool_->store
(
new Information()
new profilingInformation()
);
pool_->push(info, pool_->clockTime_);
Info<< "profiling initialized" << nl;
}
// silently ignore multiple initialization
// eg, decomposePar use multiple simultaneous Times
// silently ignore multiple initializations
// eg, decomposePar uses multiple simultaneous Times
}
......@@ -147,23 +162,22 @@ void Foam::profiling::stop(const Time& owner)
}
Foam::profiling::Information* Foam::profiling::New
Foam::profilingInformation* Foam::profiling::New
(
const string& name,
const string& descr,
clockTime& timer
)
{
Information *info = 0;
profilingInformation *info = 0;
if (pool_)
{
info = pool_->find(name);
profilingInformation *parent = pool_->stack_.top();
info = pool_->find(descr);
if (!info)
{
info = pool_->store
(
new Information(pool_->stack_.top(), name)
);
info = pool_->store(new profilingInformation(descr, parent));
}
pool_->push(info, timer);
......@@ -182,11 +196,11 @@ Foam::profiling::Information* Foam::profiling::New
}
void Foam::profiling::unstack(const Information *info)
void Foam::profiling::unstack(const profilingInformation *info)
{
if (pool_ && info)
{
Information *top = pool_->pop();
profilingInformation *top = pool_->pop();
if (info->id() != top->id())
{
......@@ -217,7 +231,7 @@ Foam::profiling::profiling
hash_(),
stack_(),
timers_(),
sysInfo_(new sysInfo()),
sysInfo_(new profilingSysInfo()),
cpuInfo_(new cpuInfo()),
memInfo_(new memInfo())
{}
......@@ -239,7 +253,7 @@ Foam::profiling::profiling
sysInfo_
(
dict.lookupOrDefault<Switch>("sysInfo", true)
? new sysInfo() : 0
? new profilingSysInfo() : 0
),
cpuInfo_
(
......@@ -254,50 +268,6 @@ Foam::profiling::profiling
{}
Foam::profiling::Information::Information()
:
id_(getNextId()),
description_("application::main"),
parent_(this),
calls_(0),
totalTime_(0),
childTime_(0),
maxMem_(0),
onStack_(false)
{}
Foam::profiling::Information::Information
(
Information *parent,
const string& descr
)
:
id_(getNextId()),
description_(descr),
parent_(parent),
calls_(0),
totalTime_(0),
childTime_(0),
maxMem_(0),
onStack_(false)
{}
Foam::profiling::Trigger::Trigger(const char* name)
:
clock_(),
ptr_(profiling::New(name, clock_))
{}
Foam::profiling::Trigger::Trigger(const string& name)
:
clock_(),
ptr_(profiling::New(name, clock_))
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::profiling::~profiling()
......@@ -309,21 +279,11 @@ Foam::profiling::~profiling()
if (pool_ == this)
{
pool_ = 0;
Information::nextId_ = 0;
profilingInformation::nextId_ = 0;
}
}
Foam::profiling::Information::~Information()
{}
Foam::profiling::Trigger::~Trigger()
{
stop();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::Time& Foam::profiling::owner() const
......@@ -337,25 +297,6 @@ Foam::label Foam::profiling::size() const
}
Foam::profiling::Information* Foam::profiling::find(const string& name)
{
StorageContainer::iterator iter = hash_.find(name);
return (iter != hash_.end() ? iter() : 0);
}
void Foam::profiling::Information::update(const scalar& elapsed)
{
++calls_;
totalTime_ += elapsed;
if (id_ != parent().id())
{
parent().childTime_ += elapsed;
}
}
bool Foam::profiling::writeData(Ostream& os) const
{
os.beginBlock("profiling");
......@@ -370,7 +311,7 @@ bool Foam::profiling::writeData(Ostream& os) const
scalar oldElapsed = 0;
forAllConstIter(StackContainer, stack_, iter)
{
const Information *info = *iter;
const profilingInformation *info = *iter;
scalar elapsed = timers_[info->id()]->elapsedTime();
if (nTrigger++)
......@@ -391,7 +332,7 @@ bool Foam::profiling::writeData(Ostream& os) const
forAllConstIter(StorageContainer, hash_, iter)
{
const Information *info = iter();
const profilingInformation *info = iter();
if (!info->onStack())
{
......@@ -458,106 +399,4 @@ bool Foam::profiling::writeObject
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::profiling::Information* Foam::profiling::store(Information *info)
{
hash_.insert(info->description(), info);
return info;
}
void Foam::profiling::push(Information *info, clockTime& timer)
{
stack_.push(info);
timers_.set(info->id(), &timer);
info->push(); // mark as on stack
}
Foam::profiling::Information* Foam::profiling::pop()
{
Information *info = stack_.pop();
timers_.erase(info->id());
info->pop(); // mark as off stack
return info;
}
bool Foam::profiling::Trigger::running() const
{
return ptr_;
}
void Foam::profiling::Trigger::stop()
{
if (ptr_)
{
ptr_->update(clock_.elapsedTime());
profiling::unstack(ptr_);
// pointer is managed by pool storage -> thus no delete here
}
ptr_ = 0;
}
void Foam::profiling::Information::push() const
{
onStack_ = true;
}
void Foam::profiling::Information::pop() const
{
onStack_ = false;
}
Foam::Ostream& Foam::profiling::Information::write
(
Ostream& os,
const bool offset,
const scalar& elapsedTime,
const scalar& childTimes
) const
{
// write in dictionary format
os.beginBlock(word("trigger" + Foam::name(id_)));
os.writeEntry("id", id_);
if (id_ != parent().id())
{
os.writeEntry("parentId", parent().id());
}
os.writeEntry("description", description());
os.writeEntry("calls", calls() + (offset ? 1 : 0));
os.writeEntry("totalTime", totalTime() + elapsedTime);
os.writeEntry("childTime", childTime() + childTimes);
if (maxMem_)
{
os.writeEntry("maxMem", maxMem_);
}
os.writeEntry("onStack", Switch(onStack()));
os.endBlock();
return os;
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<
(
Ostream& os,
const profiling::Information& info
)
{
return info.write(os);
}
// ************************************************************************* //
......@@ -52,6 +52,7 @@ SourceFiles
#ifndef profiling_H
#define profiling_H
#include "profilingTrigger.H"
#include "HashPtrTable.H"
#include "LIFOStack.H"
#include "Map.H"
......@@ -65,9 +66,9 @@ namespace Foam
// Forward declaration of classes
class Ostream;
class dictionary;
class cpuInfo;
class memInfo;
class profilingSysInfo;
/*---------------------------------------------------------------------------*\
Class profiling Declaration
......@@ -79,14 +80,20 @@ class profiling
{
public:
// Forward declarations of components
// Public typedefs
class Information;
class Trigger;
class sysInfo;
typedef profilingInformation Information;
typedef profilingTrigger Trigger;
private:
// Private typedefs
typedef profilingSysInfo sysInfo;
typedef HashPtrTable<Information, string> StorageContainer;
typedef LIFOStack<Information*> StackContainer;
// Private Static Data Members
//- Only one global pool object is possible
......@@ -95,10 +102,6 @@ private:
// Private Data Members
typedef HashPtrTable<Information, string> StorageContainer;
typedef LIFOStack<Information*> StackContainer;
//- The owner of the profiling
const Time& owner_;
......@@ -137,16 +140,22 @@ protected:
// Friendship
friend class profilingTrigger;
friend class Time;
// Constructors
//- Construct IO object, everything enabled
profiling(const IOobject&, const Time&);
profiling(const IOobject& io, const Time& owner);
//- Construct IO object with finer control over behaviour
profiling(const dictionary&, const IOobject&, const Time&);
profiling
(
const dictionary& dict,
const IOobject& io,
const Time& owner
);
//- Destructor
......@@ -155,38 +164,51 @@ protected:
// Protected Member Functions
//- Find profiling information element or null on failure
Information* find(const string& name);
//- Find named profiling information element or null on failure
profilingInformation* find(const string& name);
//- Add to hashed storage,
// returns pointer to newly stored element for chaining
Information* store(Information*);
profilingInformation* store(profilingInformation* info);
//- Add to stack and set timer lookup (based on Id)
void push(Information*, clockTime& timer);
void push(profilingInformation* info, clockTime& timer);
//- Remove from stack and remove timer lookup (based on Id).
// Returns pointer to profiling information element
Information* pop();
profilingInformation* pop();
// Static control elements
//- Singleton to initialize profiling pool, everything enabled
static void initialize(const IOobject&, const Time&);
static void initialize
(
const IOobject& ioObj,
const Time& owner
);
//- Singleton to initialize profiling pool with finer control
static void initialize(const dictionary&, const IOobject&, const Time&);
static void initialize
(
const dictionary& dict,
const IOobject& ioObj,
const Time& owner
);
//- Stop profiling, cleanup pool if possible
static void stop(const Time&);
static void stop(const Time& owner);
//- Existing or new element on pool, add to stack.
// Returns null if profiling has not been initialized
static Information* New(const string& name, clockTime& timer);
static profilingInformation* New
(
const string& descr,
clockTime& timer
);
//- Remove the information from the top of the stack
static void unstack(const Information*);
static void unstack(const profilingInformation* info);
public:
......@@ -197,7 +219,7 @@ public:
//- Print profiling information to specified output
// Forwards to writeData member of top-level object
static bool print(Ostream&);
static bool print(Ostream& os);
//- Write profiling information now
static bool writeNow();
......@@ -209,10 +231,10 @@ public:
const Time& owner() const;
//- The size of the current stack
Foam::label size() const;
label size() const;
//- writeData member function required by regIOobject
virtual bool writeData(Ostream&) const;
virtual bool writeData(Ostream& os) const;
//- Write as uncompressed ASCII, using given format
virtual bool writeObject
......@@ -224,274 +246,12 @@ public:
};
// Forward declaration of friend functions and operators
Ostream& operator<<(Ostream& os, const profiling::Information& info);
/*---------------------------------------------------------------------------*\
Class profiling::Information Declaration
\*---------------------------------------------------------------------------*/
class profiling::Information
{
// Private Static Data Members
//- Counter to generate the ids
static label nextId_;
//- get a new ID and update the counter
static label getNextId();
//- raise the next possible ID (to avoid ID-clashes during reading)
static void raiseID(label maxVal);
// Private Data Members
//- Unique id to identify it
const label id_;
//- What this timer does
const string description_;
//- Pointer to the parent object (or self for top-level)
Information* parent_;
//- Nr of times this was called
long calls_;
//- Total time spent
scalar totalTime_;
//- Time spent in children
scalar childTime_;
//- Max memory usage on call.
// Only valid when the calling profiling has memInfo active.
mutable int maxMem_;
//- Is this information currently on the stack?
mutable bool onStack_;
// Private Member Functions