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-2023 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 
39 
40 std::unique_ptr<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 
54 
55  pool_.push_back(info);
56  children_.resize(pool_.size());
57  children_.back().clear(); // safety
58 
59  return info;
60 }
61 
62 
64 (
65  profilingInformation *parent,
66  const std::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_.push_back(info);
82  children_.resize(pool_.size());
83  children_.back().clear(); // safety
84  children_[parentId].push_back(info);
85 
86  return info;
87 }
88 
89 
91 {
92  stack_.push_back(info);
93  times_.push_back(clockValue::now());
94  info->setActive(true); // Mark as on stack
95 }
96 
97 
99 {
100  Information *info = stack_.back();
101  clockValue clockval = times_.back();
102  stack_.pop_back();
103  times_.pop_back();
104 
105  info->update(clockval.elapsed()); // Update elapsed time
106  info->setActive(false); // Mark as off stack
108  return info;
109 }
110 
111 
112 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
115 {
116  return allowed && singleton_;
117 }
118 
121 {
122  allowed = 0;
123 }
124 
125 
127 {
128  if (allowed && singleton_)
129  {
130  return singleton_->writeData(os);
131  }
132 
133  return false;
134 }
135 
136 
138 {
139  if (allowed && singleton_)
140  {
141  return singleton_->regIOobject::write();
142  }
143 
144  return false;
145 }
146 
147 
149 (
150  const IOobject& ioObj,
151  const Time& owner
152 )
153 {
154  if (allowed && !singleton_)
155  {
156  singleton_.reset(new profiling(ioObj, owner));
157  }
158 }
159 
160 
162 (
163  const dictionary& dict,
164  const IOobject& ioObj,
165  const Time& owner
166 )
167 {
168  if (allowed && !singleton_)
169  {
170  singleton_.reset(new profiling(dict, ioObj, owner));
171  }
172 }
173 
174 
175 void Foam::profiling::stop(const Time& owner)
176 {
177  if (singleton_ && &owner == &(singleton_->owner_))
178  {
179  singleton_.reset(nullptr);
180  }
181 }
182 
183 
184 Foam::profilingInformation* Foam::profiling::New(const std::string& descr)
185 {
186  Information *info = nullptr;
187 
188  if (active())
189  {
190  Information *parent = singleton_->stack_.back();
191 
192  info = singleton_->create(parent, descr);
193  singleton_->beginTimer(info);
194 
195  if (singleton_->memInfo_)
196  {
197  singleton_->memInfo_->update();
198 
199  info->maxMem_ = Foam::max
200  (
201  info->maxMem_,
202  singleton_->memInfo_->size()
203  );
204  }
205  }
206 
207  return info;
208 }
209 
210 
211 void Foam::profiling::unstack(const profilingInformation *info)
212 {
213  if (active() && info)
214  {
215  Information *top = singleton_->endTimer();
216 
217  if (info->id() != top->id())
218  {
220  << "Profiling information to unstack has different id than"
221  << " the top of the profiling stack" << nl
222  << " info: " << info->id() << " (" << info->description()
223  << ")\n"
224  << " top: " << top->id() << " (" << top->description()
225  << ")\n" << endl
226  << abort(FatalError);
227  }
228  }
229 }
230 
231 
232 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
233 
235 (
236  const IOobject& io,
237  const Time& owner,
238  const bool allEnabled
239 )
240 :
241  IOdictionary(io),
242  owner_(owner)
243 {
244  if (allEnabled)
245  {
246  sysInfo_.reset(new profilingSysInfo);
247  cpuInfo_.reset(new cpuInfo);
248  memInfo_.reset(new memInfo);
249  }
250 
251  Information *info = this->create();
252  this->beginTimer(info);
253 
254  DetailInfo << "profiling initialized" << nl;
255 }
256 
257 
259 (
260  const dictionary& dict,
261  const IOobject& io,
262  const Time& owner
263 )
264 :
265  profiling(io, owner, false)
266 {
267  {
268  bool on = false;
269 
270  if (dict.readIfPresent("sysInfo", on) && on)
271  {
272  sysInfo_.reset(new profilingSysInfo);
273  }
274  if (dict.readIfPresent("cpuInfo", on) && on)
275  {
276  cpuInfo_.reset(new cpuInfo);
277  }
278  if (dict.readIfPresent("memInfo", on) && on)
279  {
280  memInfo_.reset(new memInfo);
281  }
282  }
283 }
284 
285 
286 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
287 
289 {
290  if (this == singleton_.get())
291  {
292  singleton_.reset(nullptr);
293  }
294 }
295 
296 
297 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
300 {
301  return owner_;
302 }
303 
305 Foam::label Foam::profiling::size() const noexcept
306 {
307  return stack_.size();
308 }
309 
310 
312 {
313  static DynamicList<scalar> elapsed;
314 
315  const clockValue now(clockValue::now());
316 
317  const label nstack = stack_.size();
318 
319  elapsed.resize(nstack+1); // extend for last entry, which has no child.
320 
321  for (label stacki=0; stacki < nstack; ++stacki)
322  {
323  elapsed[stacki] = (now - times_[stacki]);
324  }
325  elapsed.back() = 0;
326 
327  os.beginBlock("profiling");
328 
329  // Active items
330  for (label stacki=0; stacki < nstack; ++stacki)
331  {
332  if (stacki) os << nl; // Extra line between entries
333 
334  stack_[stacki]->write
335  (
336  os,
337  true,
338  elapsed[stacki], // elapsedTime
339  elapsed[stacki+1] // childTimes
340  );
341  }
342 
343  // Non-active items
344  for (const Information& info : pool_)
345  {
346  if (!info.active())
347  {
348  os << nl;
349  info.write(os);
350  }
351  }
352 
353  os.endBlock();
354 
355  if (sysInfo_)
356  {
357  os << nl;
358  sysInfo_->writeEntry("sysInfo", os);
359  }
360 
361  if (cpuInfo_)
362  {
363  os << nl;
364  cpuInfo_->writeEntry("cpuInfo", os);
365  }
366 
367  if (memInfo_)
368  {
369  memInfo_->update();
370  os << nl;
371  memInfo_->writeEntry("memInfo", os);
372  }
373 
374  return os.good();
375 }
376 
377 
379 (
380  IOstreamOption,
381  const bool writeOnProc
382 ) const
383 {
384  return
386  (
387  IOstreamOption(IOstreamOption::ASCII),
388  true // always writeOnProc
389  );
390 }
391 
392 
393 // ************************************************************************* //
label size() const noexcept
The size of the current stack.
Definition: profiling.C:298
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:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
profilingInformation Information
Definition: profiling.H:85
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:50
"ascii" (normal default)
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Definition: DynamicListI.H:353
static bool active() noexcept
True if profiling is allowed and is active.
Definition: profiling.C:107
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool writeNow()
Write profiling information now.
Definition: profiling.C:130
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write using stream options.
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:77
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
static void disable() noexcept
Disallow profiling - turns the InfoSwitch off.
Definition: profiling.C:113
static void unstack(const profilingInformation *info)
Remove the information from the top of the stack.
Definition: profiling.C:204
void beginTimer(Information *info)
Add to stack of active information and begin timer datum.
Definition: profiling.C:83
virtual bool writeData(Ostream &os) const
writeData member function required by regIOobject
Definition: profiling.C:304
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:142
virtual Ostream & endBlock()
Write end block group.
Definition: Ostream.C:108
static int allowed
Flag if profiling is allowed.
Definition: profiling.H:94
static profilingInformation * New(const std::string &descr)
Existing or new element on pool, add to stack.
Definition: profiling.C:177
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 void stop(const Time &owner)
Stop profiling, cleanup pool if possible.
Definition: profiling.C:168
InfoProxy< IOobject > info() const noexcept
Return info proxy, for printing information to a stream.
Definition: IOobject.H:955
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
const direction noexcept
Definition: Scalar.H:258
virtual bool writeObject(IOstreamOption, const bool writeOnProc) const
Write as uncompressed ASCII.
Definition: profiling.C:372
static bool print(Ostream &os)
Print profiling information to specified output.
Definition: profiling.C:119
OBJstream os(runTime.globalPath()/outputName)
void update(const scalar elapsedTime)
Update it with a new timing information.
void setActive(bool state) const
Mark as being active or passive.
Information * endTimer()
Remove from stack of active information and update elapsed time.
Definition: profiling.C:91
~profiling()
Destructor. Top-level clears the singleton.
Definition: profiling.C:281
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:281
T & back()
Access last element of the list, position [size()-1].
Definition: UListI.H:251
virtual Ostream & beginBlock(const keyType &kw)
Write begin block group with the given name.
Definition: Ostream.C:90
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
const Time & owner() const noexcept
The owner of the profiling.
Definition: profiling.C:292
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:172
profiling(const profiling &)=delete
No copy construct.
General system information useful for profiling.
Information * create()
Clear all profiling and restart with new profiling.
Definition: profiling.C:38