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

ENH: use unique_ptr for memory management of profiling

- makes it easier to distinguish between pointers referring to pool
  data versus pointers actually holding storage, avoids
  manual demand-driven deletion and autoPtr.

ENH: simplify/improve Pstream profiling

- times now double (not scalar) for consistency with what cpuTime
  delivers

- use bool to track suspend state
parent b64ada3d
......@@ -31,10 +31,8 @@ License
#include "argList.H"
#include "HashSet.H"
#include "profiling.H"
#include "demandDrivenData.H"
#include "IOdictionary.H"
#include "registerSwitch.H"
#include <sstream>
// * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
......@@ -762,7 +760,7 @@ Foam::autoPtr<Foam::Time> Foam::Time::New(const argList& args)
Foam::Time::~Time()
{
deleteDemandDrivenData(loopProfiling_);
loopProfiling_.reset(nullptr);
forAllReverse(controlDict_.watchIndices(), i)
{
......@@ -889,7 +887,7 @@ Foam::Time::stopAtControls Foam::Time::stopAt() const
bool Foam::Time::run() const
{
deleteDemandDrivenData(loopProfiling_);
loopProfiling_.reset(nullptr);
bool isRunning = value() < (endTime_ - 0.5*deltaT_);
......@@ -948,8 +946,10 @@ bool Foam::Time::run() const
// (re)trigger profiling
if (profiling::active())
{
loopProfiling_ =
new profilingTrigger("time.run() " + objectRegistry::name());
loopProfiling_.reset
(
new profilingTrigger("time.run() " + objectRegistry::name())
);
}
}
......
......@@ -133,7 +133,7 @@ private:
// Private data
//- Profiling trigger for time-loop (for run, loop)
mutable profilingTrigger* loopProfiling_;
mutable std::unique_ptr<profilingTrigger> loopProfiling_;
//- Any loaded dynamic libraries. Make sure to construct before
// reading controlDict.
......
......@@ -32,17 +32,16 @@ License
#include "profilingSysInfo.H"
#include "cpuInfo.H"
#include "memInfo.H"
#include "demandDrivenData.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::profiling::allowed(Foam::debug::infoSwitch("allowProfiling", 1));
Foam::profiling* Foam::profiling::singleton_(nullptr);
std::unique_ptr<Foam::profiling> Foam::profiling::singleton_(nullptr);
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::profilingInformation* Foam::profiling::create(const zero)
Foam::profilingInformation* Foam::profiling::create()
{
// Top-level entry: reset everything
pool_.clear();
......@@ -50,7 +49,7 @@ Foam::profilingInformation* Foam::profiling::create(const zero)
stack_.clear();
times_.clear();
Information* info = new Information();
Information* info = new Information;
pool_.append(info);
children_.resize(pool_.size());
......@@ -151,7 +150,7 @@ void Foam::profiling::initialize
{
if (allowed && !singleton_)
{
singleton_ = new profiling(ioObj, owner);
singleton_.reset(new profiling(ioObj, owner));
}
}
......@@ -165,7 +164,7 @@ void Foam::profiling::initialize
{
if (allowed && !singleton_)
{
singleton_ = new profiling(dict, ioObj, owner);
singleton_.reset(new profiling(dict, ioObj, owner));
}
}
......@@ -174,8 +173,7 @@ void Foam::profiling::stop(const Time& owner)
{
if (singleton_ && &owner == &(singleton_->owner_))
{
delete singleton_;
singleton_ = nullptr;
singleton_.reset(nullptr);
}
}
......@@ -214,8 +212,8 @@ void Foam::profiling::unstack(const profilingInformation *info)
if (info->id() != top->id())
{
FatalErrorInFunction
<< "The profiling information to unstack has different"
<< " id than on the top of the profiling stack" << nl
<< "Profiling information to unstack has different id than"
<< " the top of the profiling stack" << nl
<< " info: " << info->id() << " (" << info->description()
<< ")\n"
<< " top: " << top->id() << " (" << top->description()
......@@ -231,7 +229,8 @@ void Foam::profiling::unstack(const profilingInformation *info)
Foam::profiling::profiling
(
const IOobject& io,
const Time& owner
const Time& owner,
const bool allEnabled
)
:
IOdictionary(io),
......@@ -240,11 +239,18 @@ Foam::profiling::profiling
children_(),
stack_(),
times_(),
sysInfo_(new profilingSysInfo()),
cpuInfo_(new cpuInfo()),
memInfo_(new memInfo())
sysInfo_(nullptr),
cpuInfo_(nullptr),
memInfo_(nullptr)
{
Information *info = this->create(Zero);
if (allEnabled)
{
sysInfo_.reset(new profilingSysInfo);
cpuInfo_.reset(new cpuInfo);
memInfo_.reset(new memInfo);
}
Information *info = this->create();
this->beginTimer(info);
DetailInfo << "profiling initialized" << nl;
......@@ -258,32 +264,20 @@ Foam::profiling::profiling
const Time& owner
)
:
IOdictionary(io),
owner_(owner),
pool_(),
children_(),
stack_(),
times_(),
sysInfo_
(
dict.getOrDefault("sysInfo", false)
? new profilingSysInfo() : nullptr
),
cpuInfo_
(
dict.getOrDefault("cpuInfo", false)
? new cpuInfo() : nullptr
),
memInfo_
(
dict.getOrDefault("memInfo", false)
? new memInfo() : nullptr
)
profiling(io, owner, false)
{
Information *info = this->create(Zero);
this->beginTimer(info);
DetailInfo << "profiling initialized" << nl;
if (dict.getOrDefault("sysInfo", false))
{
sysInfo_.reset(new profilingSysInfo);
}
if (dict.getOrDefault("cpuInfo", false))
{
cpuInfo_.reset(new cpuInfo);
}
if (dict.getOrDefault("memInfo", false))
{
memInfo_.reset(new memInfo);
}
}
......@@ -291,13 +285,9 @@ Foam::profiling::profiling
Foam::profiling::~profiling()
{
deleteDemandDrivenData(sysInfo_);
deleteDemandDrivenData(cpuInfo_);
deleteDemandDrivenData(memInfo_);
if (singleton_ == this)
if (this == singleton_.get())
{
singleton_ = nullptr;
singleton_.reset(nullptr);
}
}
......
......@@ -30,7 +30,7 @@ Class
Description
Code profiling.
This is typically activated from within the system/controlDict as follows
This is typically activated from within system/controlDict as follows
(defaults shown):
\code
profiling
......@@ -61,17 +61,20 @@ SourceFiles
#include "PtrDynList.H"
#include "Time.H"
#include "clockTime.H"
#include <memory>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
// Forward Declarations
class Ostream;
class cpuInfo;
class memInfo;
class profilingInformation;
class profilingSysInfo;
class profilingTrigger;
/*---------------------------------------------------------------------------*\
Class profiling Declaration
......@@ -88,14 +91,15 @@ public:
typedef profilingInformation Information;
typedef profilingTrigger Trigger;
// Static data members
// Static Data Members
//- Flag if profiling is allowed
static int allowed;
private:
// Private classes, typedefs
// Private Typedefs
typedef profilingSysInfo sysInfo;
......@@ -103,7 +107,7 @@ private:
// Private Static Data Members
//- Only one global object is possible
static profiling* singleton_;
static std::unique_ptr<profiling> singleton_;
// Private Data Members
......@@ -111,7 +115,7 @@ private:
//- The owner of the profiling
const Time& owner_;
//- Storage of profiling information
//- Storage of profiling information (memory management)
PtrDynList<Information> pool_;
//- Parent/child relationships for lookup purposes
......@@ -124,13 +128,13 @@ private:
DynamicList<clockValue> times_;
//- General system information (optional)
sysInfo* sysInfo_;
std::unique_ptr<sysInfo> sysInfo_;
//- CPU-Information (optional)
cpuInfo* cpuInfo_;
std::unique_ptr<cpuInfo> cpuInfo_;
//- MEM-Information (optional)
memInfo* memInfo_;
std::unique_ptr<memInfo> memInfo_;
// Private Member Functions
......@@ -153,7 +157,12 @@ protected:
// Constructors
//- Construct IO object, everything enabled
profiling(const IOobject& io, const Time& owner);
profiling
(
const IOobject& io,
const Time& owner,
const bool allEnabled = true
);
//- Construct IO object with finer control over behaviour
profiling
......@@ -164,15 +173,11 @@ protected:
);
//- Destructor
~profiling();
// Protected Member Functions
//- Clear all profiling and restart with new profiling
// \return pointer to stored information element
Information* create(const zero);
Information* create();
//- Get or create named profiling information element with the
//- specified parent.
......@@ -218,8 +223,13 @@ protected:
//- Remove the information from the top of the stack
static void unstack(const profilingInformation* info);
public:
//- Destructor. Top-level clears the singleton.
~profiling();
// Static Member Functions
//- True if profiling is allowed and is active
......
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2009-2016 Bernhard Gschaider
Copyright (C) 2016-2018 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -27,8 +27,8 @@ License
\*---------------------------------------------------------------------------*/
#include "profilingInformation.H"
#include "Switch.H"
#include "IOstreams.H"
#include "Switch.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
......@@ -93,8 +93,6 @@ Foam::Ostream& Foam::profilingInformation::write
const scalar childTimes
) const
{
// write in dictionary format
os.beginBlock(word("trigger" + Foam::name(id_)));
os.writeEntry("id", id_);
......@@ -104,7 +102,7 @@ Foam::Ostream& Foam::profilingInformation::write
os.writeEntry("totalTime", totalTime() + elapsedTime);
os.writeEntry("childTime", childTime() + childTimes);
os.writeEntryIfDifferent<int>("maxMem", 0, maxMem_);
os.writeEntry("active", Switch(active()));
os.writeEntry("active", Switch::name(active()));
os.endBlock();
......@@ -112,7 +110,7 @@ Foam::Ostream& Foam::profilingInformation::write
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const profilingInformation& info)
{
......
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2009-2016 Bernhard Gschaider
Copyright (C) 2016-2017 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -47,12 +47,8 @@ SourceFiles
namespace Foam
{
// Forward declarations
class profilingInformation;
class Ostream;
Ostream& operator<<(Ostream& os, const profilingInformation& info);
// Forward Declarations
class profiling;
/*---------------------------------------------------------------------------*\
Class profilingInformation Declaration
......@@ -60,7 +56,7 @@ Ostream& operator<<(Ostream& os, const profilingInformation& info);
class profilingInformation
{
// Private Data Members
// Private Data
//- Unique id to identify it
const label id_;
......@@ -88,43 +84,30 @@ class profilingInformation
mutable bool active_;
// Private Member Functions
//- No copy construct
profilingInformation(const profilingInformation&) = delete;
//- No copy assignment
void operator=(const profilingInformation&) = delete;
protected:
// Friendship
//- Allow creation of master-element, setActive etc.
friend class profiling;
// Constructors
//- Construct null - only the master-element
//- Default construct - only the master-element
profilingInformation();
// Member Functions
// Protected Member Functions
//- Mark as being active or passive)
void setActive(bool state) const;
//- Write the profiling times, optionally with additional values
// Use dictionary format.
Ostream& write
(
Ostream& os,
const bool offset = false,
const scalar elapsedTime = 0,
const scalar childTime = 0
) const;
//- No copy construct
profilingInformation(const profilingInformation&) = delete;
//- No copy assignment
void operator=(const profilingInformation&) = delete;
public:
......@@ -147,49 +130,42 @@ public:
// Access
inline label id() const
label id() const
{
return id_;
}
inline const string& description() const
const string& description() const
{
return description_;
}
inline profilingInformation& parent() const
profilingInformation& parent() const
{
return *parent_;
}
inline label calls() const
label calls() const
{
return calls_;
}
inline scalar totalTime() const
scalar totalTime() const
{
return totalTime_;
}
inline scalar childTime() const
scalar childTime() const
{
return childTime_;
}
inline int maxMem() const
int maxMem() const
{
return maxMem_;
}
inline bool active() const
bool active() const
{
return active_;
}
......@@ -201,23 +177,32 @@ public:
void update(const scalar elapsedTime);
// IOstream Operators
// Write
friend Ostream& operator<<
//- Write the profiling times, optionally with additional values
// Uses dictionary format.
Ostream& write
(
Ostream& os,
const profilingInformation& info
);
const bool offset = false,
const scalar elapsedTime = 0,
const scalar childTime = 0
) const;
};
// Global Operators
Ostream& operator<<(Ostream& os, const profilingInformation& info);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
......@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -29,11 +29,11 @@ License
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
Foam::autoPtr<Foam::cpuTime> Foam::profilingPstream::timer_(nullptr);
std::unique_ptr<Foam::cpuTime> Foam::profilingPstream::timer_(nullptr);
Foam::autoPtr<Foam::cpuTime> Foam::profilingPstream::suspend_(nullptr);
Foam::profilingPstream::timingList Foam::profilingPstream::times_(Zero);
Foam::FixedList<Foam::scalar, 5> Foam::profilingPstream::times_(Zero);
bool Foam::profilingPstream::suspend_(false);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
......@@ -56,14 +56,9 @@ Foam::profilingPstream::~profilingPstream()
void Foam::profilingPstream::enable()
{
if (timer_.valid())
if (timer_)
{
timer_->resetCpuTime(); // Not really needed ...
}
else if (suspend_.valid())
{
suspend_.swap(timer_);
timer_->resetCpuTime(); // Not really needed ...
timer_->resetCpuTime(); // Not necessarily required ...
}
else
{
......@@ -71,31 +66,14 @@ void Foam::profilingPstream::enable()
times_ = Zero;
}
suspend_.clear();
suspend_ = false;
}
void Foam::profilingPstream::disable()
{
timer_.clear();
suspend_.clear();
}
void Foam::profilingPstream::suspend()
{
suspend_.clear();
suspend_.swap(timer_);
}
void Foam::profilingPstream::resume()
{
if (suspend_.valid())
{
timer_.clear();
timer_.swap(suspend_);
}
timer_.reset(nullptr);
suspend_ =