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-2022 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 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 int Foam::profiling::allowed(Foam::debug::infoSwitch("allowProfiling", 1));
39 std::unique_ptr<Foam::profiling> Foam::profiling::singleton_(nullptr);
40 
41 
42 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
43 
45 {
46  // Top-level entry: reset everything
47  pool_.clear();
48  children_.clear();
49  stack_.clear();
50  times_.clear();
51 
53 
54  pool_.append(info);
55  children_.resize(pool_.size());
56  children_.last().clear(); // safety
57 
58  return info;
59 }
60 
61 
63 (
64  profilingInformation *parent,
65  const string& descr
66 )
67 {
68  const label parentId = parent->id();
69 
70  for (Information* child : children_[parentId])
71  {
72  if (descr == child->description())
73  {
74  return child; // Found existing
75  }
76  }
77 
78  Information* info = new Information(parent, descr, pool_.size());
79 
80  pool_.append(info);
81  children_.resize(pool_.size());
82  children_.last().clear(); // safety
83  children_[parentId].append(info);
84 
85  return info;
86 }
87 
88 
90 {
91  stack_.append(info);
92  times_.append(clockValue::now());
93  info->setActive(true); // Mark as on stack
94 }
95 
96 
98 {
99  Information *info = stack_.remove();
100  clockValue clockval = times_.remove();
101 
102  info->update(clockval.elapsed()); // Update elapsed time
103  info->setActive(false); // Mark as off stack
105  return info;
106 }
107 
108 
109 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
112 {
113  return allowed && singleton_;
114 }
115 
118 {
119  allowed = 0;
120 }
121 
122 
124 {
125  if (active())
126  {
127  return singleton_->writeData(os);
128  }
129 
130  return false;
131 }
132 
133 
135 {
136  if (active())
137  {
138  return singleton_->regIOobject::write();
139  }
140 
141  return false;
142 }
143 
144 
146 (
147  const IOobject& ioObj,
148  const Time& owner
149 )
150 {
151  if (allowed && !singleton_)
152  {
153  singleton_.reset(new profiling(ioObj, owner));
154  }
155 }
156 
157 
159 (
160  const dictionary& dict,
161  const IOobject& ioObj,
162  const Time& owner
163 )
164 {
165  if (allowed && !singleton_)
166  {
167  singleton_.reset(new profiling(dict, ioObj, owner));
168  }
169 }
170 
171 
172 void Foam::profiling::stop(const Time& owner)
173 {
174  if (singleton_ && &owner == &(singleton_->owner_))
175  {
176  singleton_.reset(nullptr);
177  }
178 }
179 
180 
182 {
183  Information *info = nullptr;
184 
185  if (active())
186  {
187  Information *parent = singleton_->stack_.last();
188 
189  info = singleton_->create(parent, descr);
190  singleton_->beginTimer(info);
191 
192  if (singleton_->memInfo_)
193  {
194  info->maxMem_ = Foam::max
195  (
196  info->maxMem_,
197  singleton_->memInfo_->update().size()
198  );
199  }
200  }
201 
202  return info;
203 }
204 
205 
206 void Foam::profiling::unstack(const profilingInformation *info)
207 {
208  if (active() && info)
209  {
210  Information *top = singleton_->endTimer();
211 
212  if (info->id() != top->id())
213  {
215  << "Profiling information to unstack has different id than"
216  << " the top of the profiling stack" << nl
217  << " info: " << info->id() << " (" << info->description()
218  << ")\n"
219  << " top: " << top->id() << " (" << top->description()
220  << ")\n" << endl
221  << abort(FatalError);
222  }
223  }
224 }
225 
226 
227 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
228 
229 Foam::profiling::profiling
230 (
231  const IOobject& io,
232  const Time& owner,
233  const bool allEnabled
234 )
235 :
236  IOdictionary(io),
237  owner_(owner),
238  pool_(),
239  children_(),
240  stack_(),
241  times_(),
242  sysInfo_(nullptr),
243  cpuInfo_(nullptr),
244  memInfo_(nullptr)
245 {
246  if (allEnabled)
247  {
248  sysInfo_.reset(new profilingSysInfo);
249  cpuInfo_.reset(new cpuInfo);
250  memInfo_.reset(new memInfo);
251  }
252 
253  Information *info = this->create();
254  this->beginTimer(info);
255 
256  DetailInfo << "profiling initialized" << nl;
257 }
258 
259 
260 Foam::profiling::profiling
261 (
262  const dictionary& dict,
263  const IOobject& io,
264  const Time& owner
265 )
266 :
267  profiling(io, owner, false)
268 {
269  if (dict.getOrDefault("sysInfo", false))
270  {
271  sysInfo_.reset(new profilingSysInfo);
272  }
273  if (dict.getOrDefault("cpuInfo", false))
274  {
275  cpuInfo_.reset(new cpuInfo);
276  }
277  if (dict.getOrDefault("memInfo", false))
278  {
279  memInfo_.reset(new memInfo);
280  }
281 }
282 
283 
284 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
285 
287 {
288  if (this == singleton_.get())
289  {
290  singleton_.reset(nullptr);
291  }
292 }
293 
294 
295 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
297 const Foam::Time& Foam::profiling::owner() const
298 {
299  return owner_;
300 }
301 
303 Foam::label Foam::profiling::size() const noexcept
304 {
305  return stack_.size();
306 }
307 
308 
310 {
311  static DynamicList<scalar> elapsed;
312 
313  const clockValue now(clockValue::now());
314 
315  const label nstack = stack_.size();
316 
317  elapsed.resize(nstack+1); // extend for last entry, which has no child.
318 
319  for (label stacki=0; stacki < nstack; ++stacki)
320  {
321  elapsed[stacki] = (now - times_[stacki]);
322  }
323  elapsed.last() = 0;
324 
325  os.beginBlock("profiling");
326 
327  // Active items
328  for (label stacki=0; stacki < nstack; ++stacki)
329  {
330  if (stacki) os << nl; // Extra line between entries
331 
332  stack_[stacki]->write
333  (
334  os,
335  true,
336  elapsed[stacki], // elapsedTime
337  elapsed[stacki+1] // childTimes
338  );
339  }
340 
341  // Non-active items
342  for (const Information& info : pool_)
343  {
344  if (!info.active())
345  {
346  os << nl;
347  info.write(os);
348  }
349  }
350 
351  os.endBlock();
352 
353  if (sysInfo_)
354  {
355  os << nl;
356  os.beginBlock("sysInfo");
357  sysInfo_->write(os);
358  os.endBlock();
359  }
360 
361  if (cpuInfo_)
362  {
363  os << nl;
364  os.beginBlock("cpuInfo");
365  cpuInfo_->write(os);
366  os.endBlock();
367  }
368 
369  if (memInfo_)
370  {
371  memInfo_->update();
372 
373  os << nl;
374  os.beginBlock("memInfo");
375  memInfo_->write(os);
376  os.writeEntry("units", "kB");
377  os.endBlock();
378  }
379 
380  return os.good();
381 }
382 
383 
385 (
386  IOstreamOption,
387  const bool valid
388 ) const
389 {
390  return
392  (
393  IOstreamOption(IOstreamOption::ASCII),
394  true
395  );
396 }
397 
398 
399 // ************************************************************************* //
label size() const noexcept
The size of the current stack.
Definition: profiling.C:296
dictionary dict
clockValue elapsed() const
The time duration elapsed until now() since the start point.
Definition: clockValueI.H:69
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
profilingInformation Information
Definition: profiling.H:86
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
"ascii" (normal default)
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Definition: DynamicListI.H:346
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
virtual bool writeObject(IOstreamOption, const bool valid) const
Write as uncompressed ASCII.
Definition: profiling.C:378
static bool writeNow()
Write profiling information now.
Definition: profiling.C:127
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:312
int infoSwitch(const char *name, const int deflt=0)
Lookup info switch or add default value.
Definition: debug.C:228
Code profiling.
Definition: profiling.H:78
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
static void disable()
Disallow profiling by forcing the InfoSwitch off.
Definition: profiling.C:110
static void unstack(const profilingInformation *info)
Remove the information from the top of the stack.
Definition: profiling.C:199
void beginTimer(Information *info)
Add to stack of active information and begin timer datum.
Definition: profiling.C:82
virtual bool writeData(Ostream &os) const
writeData member function required by regIOobject
Definition: profiling.C:302
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
void update()
Update to the current now() time from the system.
Definition: clockValueI.H:57
static clockValue now()
The current clock value from the system.
Definition: clockValueI.H:23
static void initialize(const IOobject &ioObj, const Time &owner)
Singleton to initialize profiling pool, everything enabled.
Definition: profiling.C:139
virtual Ostream & endBlock()
Write end block group.
Definition: Ostream.C:98
static int allowed
Flag if profiling is allowed.
Definition: profiling.H:95
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Access to high-resolution clock value with some basic operations. Used to calculate time durations...
Definition: clockValue.H:49
#define DetailInfo
Definition: evalEntry.C:30
errorManip< error > abort(error &err)
Definition: errorManip.H:139
static profilingInformation * New(const string &descr)
Existing or new element on pool, add to stack.
Definition: profiling.C:174
static void stop(const Time &owner)
Stop profiling, cleanup pool if possible.
Definition: profiling.C:165
static bool active()
True if profiling is allowed and is active.
Definition: profiling.C:104
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:55
const direction noexcept
Definition: Scalar.H:258
static bool print(Ostream &os)
Print profiling information to specified output.
Definition: profiling.C:116
OBJstream os(runTime.globalPath()/outputName)
Memory usage information for the current process, and the system memory that is free.
Definition: memInfo.H:58
void setActive(bool state) const
Mark as being active or passive)
T & last()
Access last element of the list, position [size()-1].
Definition: UList.H:812
Information * endTimer()
Remove from stack of active information and update elapsed time.
Definition: profiling.C:90
const Time & owner() const
The owner of the profiling.
Definition: profiling.C:290
~profiling()
Destructor. Top-level clears the singleton.
Definition: profiling.C:279
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:274
virtual Ostream & beginBlock(const keyType &kw)
Write begin block group with the given name.
Definition: Ostream.C:80
InfoProxy< IOobject > info() const
Return info proxy, for printing information to a stream.
Definition: IOobject.H:865
virtual bool writeObject(IOstreamOption streamOpt, const bool valid) const
Write using stream options.
Code profiling information in terms of time spent, number of calls etc.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
General system information useful for profiling.
Information * create()
Clear all profiling and restart with new profiling.
Definition: profiling.C:37