profiling.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2009-2016 Bernhard Gschaider
9  Copyright (C) 2016-2018 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "argList.H"
30 #include "profiling.H"
31 #include "profilingInformation.H"
32 #include "profilingSysInfo.H"
33 #include "cpuInfo.H"
34 #include "memInfo.H"
35 #include "demandDrivenData.H"
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 int Foam::profiling::allowed(Foam::debug::infoSwitch("allowProfiling", 1));
40 Foam::profiling* Foam::profiling::singleton_(nullptr);
41 
42 
43 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
44 
46 {
47  // Top-level entry: reset everything
48  pool_.clear();
49  children_.clear();
50  stack_.clear();
51  times_.clear();
52 
53  Information* info = new Information();
54 
55  pool_.append(info);
56  children_.resize(pool_.size());
57  children_.last().clear(); // safety
58 
59  return info;
60 }
61 
62 
64 (
65  profilingInformation *parent,
66  const string& descr
67 )
68 {
69  const label parentId = parent->id();
70 
71  for (Information* child : children_[parentId])
72  {
73  if (descr == child->description())
74  {
75  return child; // Found existing
76  }
77  }
78 
79  Information* info = new Information(parent, descr, pool_.size());
80 
81  pool_.append(info);
82  children_.resize(pool_.size());
83  children_.last().clear(); // safety
84  children_[parentId].append(info);
85 
86  return info;
87 }
88 
89 
91 {
92  stack_.append(info);
93  times_.append(clockValue::now());
94  info->setActive(true); // Mark as on stack
95 }
96 
97 
99 {
100  Information *info = stack_.remove();
101  clockValue clockval = times_.remove();
102 
103  info->update(clockval.elapsed()); // Update elapsed time
104  info->setActive(false); // Mark as off stack
105 
106  return info;
107 }
108 
109 
110 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
111 
113 {
114  return allowed && singleton_;
115 }
116 
117 
119 {
120  allowed = 0;
121 }
122 
123 
125 {
126  if (active())
127  {
128  return singleton_->writeData(os);
129  }
130 
131  return false;
132 }
133 
134 
136 {
137  if (active())
138  {
139  return singleton_->regIOobject::write();
140  }
141 
142  return false;
143 }
144 
145 
147 (
148  const IOobject& ioObj,
149  const Time& owner
150 )
151 {
152  if (allowed && !singleton_)
153  {
154  singleton_ = new profiling(ioObj, owner);
155  }
156 }
157 
158 
160 (
161  const dictionary& dict,
162  const IOobject& ioObj,
163  const Time& owner
164 )
165 {
166  if (allowed && !singleton_)
167  {
168  singleton_ = new profiling(dict, ioObj, owner);
169  }
170 }
171 
172 
173 void Foam::profiling::stop(const Time& owner)
174 {
175  if (singleton_ && &owner == &(singleton_->owner_))
176  {
177  delete singleton_;
178  singleton_ = nullptr;
179  }
180 }
181 
182 
184 {
185  Information *info = nullptr;
186 
187  if (active())
188  {
189  Information *parent = singleton_->stack_.last();
190 
191  info = singleton_->create(parent, descr);
192  singleton_->beginTimer(info);
193 
194  if (singleton_->memInfo_)
195  {
196  info->maxMem_ = Foam::max
197  (
198  info->maxMem_,
199  singleton_->memInfo_->update().size()
200  );
201  }
202  }
203 
204  return info;
205 }
206 
207 
209 {
210  if (active() && info)
211  {
212  Information *top = singleton_->endTimer();
213 
214  if (info->id() != top->id())
215  {
217  << "The profiling information to unstack has different"
218  << " id than on the top of the profiling stack" << nl
219  << " info: " << info->id() << " (" << info->description()
220  << ")\n"
221  << " top: " << top->id() << " (" << top->description()
222  << ")\n" << endl
223  << abort(FatalError);
224  }
225  }
226 }
227 
228 
229 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
230 
231 Foam::profiling::profiling
232 (
233  const IOobject& io,
234  const Time& owner
235 )
236 :
237  IOdictionary(io),
238  owner_(owner),
239  pool_(),
240  children_(),
241  stack_(),
242  times_(),
243  sysInfo_(new profilingSysInfo()),
244  cpuInfo_(new cpuInfo()),
245  memInfo_(new memInfo())
246 {
247  Information *info = this->create(Zero);
248  this->beginTimer(info);
249 
250  DetailInfo << "profiling initialized" << nl;
251 }
252 
253 
254 Foam::profiling::profiling
255 (
256  const dictionary& dict,
257  const IOobject& io,
258  const Time& owner
259 )
260 :
261  IOdictionary(io),
262  owner_(owner),
263  pool_(),
264  children_(),
265  stack_(),
266  times_(),
267  sysInfo_
268  (
269  dict.lookupOrDefault("sysInfo", false)
270  ? new profilingSysInfo() : nullptr
271  ),
272  cpuInfo_
273  (
274  dict.lookupOrDefault("cpuInfo", false)
275  ? new cpuInfo() : nullptr
276  ),
277  memInfo_
278  (
279  dict.lookupOrDefault("memInfo", false)
280  ? new memInfo() : nullptr
281  )
282 {
283  Information *info = this->create(Zero);
284  this->beginTimer(info);
285 
286  DetailInfo << "profiling initialized" << nl;
287 }
288 
289 
290 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
291 
293 {
294  deleteDemandDrivenData(sysInfo_);
295  deleteDemandDrivenData(cpuInfo_);
296  deleteDemandDrivenData(memInfo_);
297 
298  if (singleton_ == this)
299  {
300  singleton_ = nullptr;
301  }
302 }
303 
304 
305 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
306 
308 {
309  return owner_;
310 }
311 
312 
314 {
315  return stack_.size();
316 }
317 
318 
320 {
321  static DynamicList<scalar> elapsed;
322 
323  const clockValue now(clockValue::now());
324 
325  const label nstack = stack_.size();
326 
327  elapsed.resize(nstack+1); // extend for last entry, which has no child.
328 
329  for (label stacki=0; stacki < nstack; ++stacki)
330  {
331  elapsed[stacki] = (now - times_[stacki]);
332  }
333  elapsed.last() = 0;
334 
335  os.beginBlock("profiling");
336 
337  // Active items
338  for (label stacki=0; stacki < nstack; ++stacki)
339  {
340  if (stacki) os << nl; // Extra line between entries
341 
342  stack_[stacki]->write
343  (
344  os,
345  true,
346  elapsed[stacki], // elapsedTime
347  elapsed[stacki+1] // childTimes
348  );
349  }
350 
351  // Non-active items
352  for (const Information& info : pool_)
353  {
354  if (!info.active())
355  {
356  os << nl;
357  info.write(os);
358  }
359  }
360 
361  os.endBlock();
362 
363  if (sysInfo_)
364  {
365  os << nl;
366  os.beginBlock("sysInfo");
367  sysInfo_->write(os);
368  os.endBlock();
369  }
370 
371  if (cpuInfo_)
372  {
373  os << nl;
374  os.beginBlock("cpuInfo");
375  cpuInfo_->write(os);
376  os.endBlock();
377  }
378 
379  if (memInfo_)
380  {
381  memInfo_->update();
382 
383  os << nl;
384  os.beginBlock("memInfo");
385  memInfo_->write(os);
386  os.writeEntry("units", "kB");
387  os.endBlock();
388  }
389 
390  return os.good();
391 }
392 
393 
395 (
399  const bool valid
400 ) const
401 {
403  (
405  ver,
407  true
408  );
409 }
410 
411 
412 // ************************************************************************* //
Foam::IOstreamOption::UNCOMPRESSED
compression = false
Definition: IOstreamOption.H:73
profiling.H
Foam::IOdictionary
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:54
Foam::BitSetOps::create
bitSet create(const label n, const labelHashSet &locations, const bool on=true)
Create a bitSet with length n with the specifed on locations.
Definition: BitOps.C:35
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
Foam::regIOobject::writeObject
virtual bool writeObject(IOstream::streamFormat, IOstream::versionNumber, IOstream::compressionType, const bool valid) const
Write using given format, version and compression.
Definition: regIOobjectWrite.C:39
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::profilingInformation::update
void update(const scalar elapsedTime)
Update it with a new timing information.
Definition: profilingInformation.C:68
Foam::profilingInformation::description
const string & description() const
Definition: profilingInformation.H:155
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::DynamicList< scalar >
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::profilingInformation::id
label id() const
Definition: profilingInformation.H:149
Foam::profilingInformation::setActive
void setActive(bool state) const
Mark as being active or passive)
Definition: profilingInformation.C:82
Foam::profiling::allowed
static int allowed
Flag if profiling is allowed.
Definition: profiling.H:93
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::Ostream::beginBlock
virtual Ostream & beginBlock(const keyType &kw)
Write begin block group with the given name.
Definition: Ostream.C:91
Foam::dictionary::lookupOrDefault
T lookupOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionary.H:1241
Foam::profiling::create
Information * create(const zero)
Clear all profiling and restart with new profiling.
Definition: profiling.C:45
Foam::IOobject::info
InfoProxy< IOobject > info() const
Return info proxy.
Definition: IOobject.H:519
Foam::clockValue::elapsed
clockValue elapsed() const
The time elapsed from now() since the start time.
Definition: clockValue.C:73
Foam::debug::infoSwitch
int infoSwitch(const char *name, const int deflt=0)
Lookup info switch or add default value.
Definition: debug.C:231
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:42
profilingInformation.H
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::IOstreamOption::versionNumber
Representation of a major/minor version number.
Definition: IOstreamOption.H:79
Foam::profiling::stop
static void stop(const Time &owner)
Stop profiling, cleanup pool if possible.
Definition: profiling.C:173
Foam::profilingInformation
Code profiling information in terms of time spent, number of calls etc.
Definition: profilingInformation.H:60
Foam::profiling::active
static bool active()
True if profiling is allowed and is active.
Definition: profiling.C:112
Foam::profiling::writeObject
virtual bool writeObject(IOstream::streamFormat ignoreAlwaysASCII, IOstream::versionNumber ver, IOstream::compressionType ignoreAlwaysUncompressed, const bool valid) const
Write as uncompressed ASCII, using given format.
Definition: profiling.C:395
argList.H
Foam::profiling::owner
const Time & owner() const
The owner of the profiling.
Definition: profiling.C:307
Foam::profiling::endTimer
Information * endTimer()
Remove from stack of active information and update elapsed time.
Definition: profiling.C:98
DetailInfo
#define DetailInfo
Definition: evalEntry.C:36
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::profiling::~profiling
~profiling()
Destructor.
Definition: profiling.C:292
Foam::cpuInfo
General CPU characteristics.
Definition: cpuInfo.H:59
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::profilingSysInfo
General system information useful for profiling.
Definition: profilingSysInfo.H:52
Foam::Ostream::endBlock
virtual Ostream & endBlock()
Write end block group.
Definition: Ostream.C:109
Foam::clockValue
Access to high-resolution clock value with some basic operations.
Definition: clockValue.H:51
Foam::IOstreamOption::streamFormat
streamFormat
Data format (ascii | binary)
Definition: IOstreamOption.H:64
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::memInfo
Memory usage information for the current process, and the system memory that is free.
Definition: memInfo.H:62
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam::profiling::disable
static void disable()
Disallow profiling by forcing the InfoSwitch off.
Definition: profiling.C:118
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::profiling::unstack
static void unstack(const profilingInformation *info)
Remove the information from the top of the stack.
Definition: profiling.C:208
Foam::profiling::beginTimer
void beginTimer(Information *info)
Add to stack of active information and begin timer datum.
Definition: profiling.C:90
Foam::DynamicList::resize
void resize(const label nElem)
Alter addressable list size.
Definition: DynamicListI.H:328
Foam::profiling::initialize
static void initialize(const IOobject &ioObj, const Time &owner)
Singleton to initialize profiling pool, everything enabled.
Definition: profiling.C:147
Foam::profiling::writeData
virtual bool writeData(Ostream &os) const
writeData member function required by regIOobject
Definition: profiling.C:319
Foam::IOstreamOption::ASCII
"ascii"
Definition: IOstreamOption.H:66
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::profiling::New
static profilingInformation * New(const string &descr)
Existing or new element on pool, add to stack.
Definition: profiling.C:183
Foam::profiling::size
label size() const noexcept
The size of the current stack.
Definition: profiling.C:313
Foam::profiling::print
static bool print(Ostream &os)
Print profiling information to specified output.
Definition: profiling.C:124
Foam::Ostream::writeEntry
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:219
Foam::IOstreamOption::compressionType
compressionType
Compression treatment (UNCOMPRESSED | COMPRESSED)
Definition: IOstreamOption.H:71
profilingSysInfo.H
Foam::profiling
Code profiling.
Definition: profiling.H:79
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:216
Foam::profiling::Information
profilingInformation Information
Definition: profiling.H:87
Foam::clockValue::now
static clockValue now()
Return the current time value from the system.
Definition: clockValue.H:78
Foam::zero
A class representing the concept of 0 (zero), which can be used to avoid manipulating objects that ar...
Definition: zero.H:61
Foam::profiling::writeNow
static bool writeNow()
Write profiling information now.
Definition: profiling.C:135