Duckcpp 2.1.0
Duckcpp is a high-performance c++ graphics engine.
Loading...
Searching...
No Matches
IProfiler.hpp
1// This file is part of the "Irrlicht Engine".
2// For conditions of distribution and use, see copyright notice in duckcpp/duckcpp.hpp
3// Written by Michael Zeilfelder
4
5#ifndef DCPP_I_PROFILER_HPP_INCLUDED
6#define DCPP_I_PROFILER_HPP_INCLUDED
7
8#include <duckcpp/core/engine/DcppCompileConfig.hpp>
9#include <duckcpp/core/engine/irrString.hpp>
10#include <duckcpp/core/engine/irrArray.hpp>
11#include <duckcpp/core/engine/ITimer.hpp>
12#include <limits.h> // for INT_MAX (we should have a INT32_MAX...)
13
14namespace dcpp
15{
16
17class ITimer;
18
21{
22public:
23 friend class IProfiler;
24
25public:
27 {
28 GroupIndex = 0;
29 reset();
30 }
31
32public:
33 bool operator<(const SProfileData& pd) const
34 {
35 return Id < pd.Id;
36 }
37
38 bool operator==(const SProfileData& pd) const
39 {
40 return Id == pd.Id;
41 }
42
43 dcpp::uint32_kt getGroupIndex() const
44 {
45 return GroupIndex;
46 }
47
48 const dcpp::nub::wstring& getName() const
49 {
50 return Name;
51 }
52
55 {
56 return CountCalls;
57 }
58
61 {
62 return LongestTime;
63 }
64
67 {
68 return TimeSum;
69 }
70
71private:
72
73 // just to be used for searching as it does no initialization besides id
74 SProfileData(dcpp::uint32_kt id) : Id(id) {}
75
76 void reset()
77 {
78 CountCalls = 0;
79 LongestTime = 0;
80 TimeSum = 0;
81 LastTimeStarted = 0;
82 StartStopCounter = 0;
83 }
84
86 dcpp::uint32_kt GroupIndex;
88
89 dcpp::int32_kt StartStopCounter; // 0 means stopped > 0 means it runs.
90 dcpp::uint32_kt CountCalls;
91 dcpp::uint32_kt LongestTime;
92 dcpp::uint32_kt TimeSum;
93
94 dcpp::uint32_kt LastTimeStarted;
95};
96
98// Implementer notes:
99// The design is all about allowing to use the central start/stop mechanism with minimal time overhead.
100// This is why the class works without a virtual functions interface contrary to the usual Duckcpp design.
101// And also why it works with id's instead of strings in the start/stop functions even if it makes using
102// the class slightly harder.
103// The class comes without reference-counting because the profiler instance is never released (TBD).
105{
106public:
108 IProfiler() : Timer(0), NextAutoId(INT_MAX)
109 {}
110
111 virtual ~IProfiler()
112 {}
113
115
120 inline void add(dcpp::int32_kt id, const dcpp::nub::wstring &name, const dcpp::nub::wstring &groupName);
121
123
127 inline dcpp::int32_kt add(const dcpp::nub::wstring &name, const dcpp::nub::wstring &groupName);
128
131 {
132 return ProfileDatas.size();
133 }
134
136
139 inline bool findDataIndex(dcpp::uint32_kt & result, const dcpp::nub::wstring &name) const;
140
142
144 {
145 return ProfileDatas[index];
146 }
147
149
152
154
156 {
157 return ProfileGroups.size();
158 }
159
161
162 inline const SProfileData& getGroupData(dcpp::uint32_kt index) const
163 {
164 return ProfileGroups[index];
165 }
166
168
171 inline bool findGroupIndex(dcpp::uint32_kt & result, const dcpp::nub::wstring &name) const;
172
173
175
178 inline void start(dcpp::int32_kt id);
179
181
185 inline void stop(dcpp::int32_kt id);
186
188 inline void resetDataById(dcpp::int32_kt id);
189
191 inline void resetDataByIndex(dcpp::uint32_kt index);
192
194 inline void resetGroup(dcpp::uint32_kt index);
195
197
198 inline void resetAll();
199
201
204 virtual void printAll(dcpp::nub::wstring &result, bool includeOverview=false,bool suppressUncalled=true) const = 0;
205
207
209 virtual void printGroup(dcpp::nub::wstring &result, dcpp::uint32_kt groupIndex, bool suppressUncalled) const = 0;
210
211protected:
212
213 inline dcpp::uint32_kt addGroup(const dcpp::nub::wstring &name);
214
215 // I would prefer using dcpp::os::Timer, but os.h is not in the public interface so far.
216 // Timer must be initialized by the implementation.
217 ITimer * Timer;
219 dcpp::nub::array<SProfileData> ProfileGroups;
220
221private:
222 dcpp::int32_kt NextAutoId; // for giving out id's automatically
223};
224
226
230DUCKCPP_API IProfiler& IRRCALLCONV getProfiler();
231
233
237{
238public:
240
243 : Id(id), Profiler(getProfiler())
244 {
245 Profiler.start(Id);
246 }
247
249
254 : Id(id), Profiler(getProfiler())
255 {
256 Profiler.add(Id, name, groupName);
257 Profiler.start(Id);
258 }
259
261
265 : Profiler(getProfiler())
266 {
267 Id = Profiler.add(name, groupName);
268 Profiler.start(Id);
269 }
270
272 {
273 Profiler.stop(Id);
274 }
275
276protected:
278 IProfiler& Profiler;
279};
280
281
282// IMPLEMENTATION for in-line stuff
283
285{
286 dcpp::int32_kt idx = ProfileDatas.binary_search(SProfileData(id));
287 if ( idx >= 0 && Timer )
288 {
289 ++ProfileDatas[idx].StartStopCounter;
290 if (ProfileDatas[idx].StartStopCounter == 1 )
291 ProfileDatas[idx].LastTimeStarted = Timer->getRealTime();
292 }
293}
294
296{
297 if ( Timer )
298 {
299 const dcpp::uint32_kt timeNow = Timer->getRealTime();
300 const dcpp::int32_kt idx = ProfileDatas.binary_search(SProfileData(id));
301 if ( idx >= 0 )
302 {
303 SProfileData &data = ProfileDatas[idx];
304 --ProfileDatas[idx].StartStopCounter;
305 if ( data.LastTimeStarted != 0 && ProfileDatas[idx].StartStopCounter == 0)
306 {
307 // update data for this id
308 ++data.CountCalls;
309 const dcpp::uint32_kt diffTime = timeNow - data.LastTimeStarted;
310 data.TimeSum += diffTime;
311 if ( diffTime > data.LongestTime )
312 data.LongestTime = diffTime;
313 data.LastTimeStarted = 0;
314
315 // update data of it's group
316 SProfileData & group = ProfileGroups[data.GroupIndex];
317 ++group.CountCalls;
318 group.TimeSum += diffTime;
319 if ( diffTime > group.LongestTime )
320 group.LongestTime = diffTime;
321 group.LastTimeStarted = 0;
322 }
323 else if ( ProfileDatas[idx].StartStopCounter < 0 )
324 {
325 // ignore additional stop calls
326 ProfileDatas[idx].StartStopCounter = 0;
327 }
328 }
329 }
330}
331
333{
334 dcpp::uint32_kt index;
335 if ( findDataIndex(index, name) )
336 {
337 add( ProfileDatas[index].Id, name, groupName );
338 return ProfileDatas[index].Id;
339 }
340 else
341 {
342 const dcpp::int32_kt id = NextAutoId;
343 --NextAutoId;
344 add( id, name, groupName );
345 return id;
346 }
347}
348
350{
351 dcpp::uint32_kt groupIdx;
352 if ( !findGroupIndex(groupIdx, groupName) )
353 {
354 groupIdx = addGroup(groupName);
355 }
356
357 SProfileData data(id);
358 dcpp::int32_kt idx = ProfileDatas.binary_search(data);
359 if ( idx < 0 )
360 {
361 data.reset();
362 data.GroupIndex = groupIdx;
363 data.Name = name;
364
365 ProfileDatas.push_back(data);
366 ProfileDatas.sort();
367 }
368 else
369 {
370 // only reset on group changes, otherwise we want to keep the data or coding PProfileScope would become tricky.
371 if ( groupIdx != ProfileDatas[idx].GroupIndex )
372 {
374 ProfileDatas[idx].GroupIndex = groupIdx;
375 }
376 ProfileDatas[idx].Name = name;
377 }
378}
379
380dcpp::uint32_kt IProfiler::addGroup(const dcpp::nub::wstring &name)
381{
382 SProfileData group;
383 group.Id = -1; // Id for groups doesn't matter so far
384 group.Name = name;
385 ProfileGroups.push_back(group);
386 return ProfileGroups.size()-1;
387}
388
390{
391 for ( dcpp::uint32_kt i=0; i < ProfileDatas.size(); ++i )
392 {
393 if ( ProfileDatas[i].Name == name )
394 {
395 result = i;
396 return true;
397 }
398 }
399
400 return false;
401}
402
404{
405 SProfileData data(id);
406 const dcpp::int32_kt idx = ProfileDatas.binary_search(data);
407 if ( idx >= 0 )
408 return &ProfileDatas[idx];
409 return NULL;
410}
411
413{
414 for ( dcpp::uint32_kt i=0; i < ProfileGroups.size(); ++i )
415 {
416 if ( ProfileGroups[i].Name == name )
417 {
418 result = i;
419 return true;
420 }
421 }
422
423 return false;
424}
425
427{
428 dcpp::int32_kt idx = ProfileDatas.binary_search(SProfileData(id));
429 if ( idx >= 0 )
430 {
432 }
433}
434
436{
437 SProfileData &data = ProfileDatas[index];
438
439 SProfileData & group = ProfileGroups[data.GroupIndex];
440 group.CountCalls -= data.CountCalls;
441 group.TimeSum -= data.TimeSum;
442
443 data.reset();
444}
445
448{
449 for ( dcpp::uint32_kt i=0; i<ProfileDatas.size(); ++i )
450 {
451 if ( ProfileDatas[i].GroupIndex == index )
452 ProfileDatas[i].reset();
453 }
454 if ( index < ProfileGroups.size() )
455 ProfileGroups[index].reset();
456}
457
459{
460 for ( dcpp::uint32_kt i=0; i<ProfileDatas.size(); ++i )
461 {
462 ProfileDatas[i].reset();
463 }
464
465 for ( dcpp::uint32_kt i=0; i<ProfileGroups.size(); ++i )
466 {
467 ProfileGroups[i].reset();
468 }
469}
470
475#ifdef _DCPP_COMPILE_WITH_PROFILING_
476 #define DCPP_PROFILE(X) X
477#else
478 #define DCPP_PROFILE(X)
479#endif // DCPP_PROFILE
480
481} // namespace dcpp
482
483#endif // DCPP_I_PROFILER_HPP_INCLUDED
Code-profiler. Please check the example in the Duckcpp examples folder about how to use it.
Definition IProfiler.hpp:105
dcpp::uint32_kt getProfileDataCount() const
Return the number of profile data blocks. There is one for each id.
Definition IProfiler.hpp:130
void start(dcpp::int32_kt id)
Start profile-timing for the given id.
Definition IProfiler.hpp:284
bool findGroupIndex(dcpp::uint32_kt &result, const dcpp::nub::wstring &name) const
Find the group index by the group-name.
Definition IProfiler.hpp:412
bool findDataIndex(dcpp::uint32_kt &result, const dcpp::nub::wstring &name) const
Search for the index of the profile data by name.
Definition IProfiler.hpp:389
void resetGroup(dcpp::uint32_kt index)
Reset profile data for a whole group.
Definition IProfiler.hpp:447
IProfiler()
Constructor. You could use this to create a new profiler, but usually getProfiler() is used to access...
Definition IProfiler.hpp:108
void add(dcpp::int32_kt id, const dcpp::nub::wstring &name, const dcpp::nub::wstring &groupName)
Add an id with given name and group which can be used for profiling with start/stop.
Definition IProfiler.hpp:349
void stop(dcpp::int32_kt id)
Stop profile-timing for the given id.
Definition IProfiler.hpp:295
dcpp::uint32_kt getGroupCount() const
Get the number of profile groups. Will be at least 1.
Definition IProfiler.hpp:155
virtual void printAll(dcpp::nub::wstring &result, bool includeOverview=false, bool suppressUncalled=true) const =0
Write all profile-data into a string.
const SProfileData * getProfileDataById(dcpp::uint32_kt id)
Get the profile data.
Definition IProfiler.hpp:403
void resetAll()
Reset all profile data.
Definition IProfiler.hpp:458
const SProfileData & getProfileDataByIndex(dcpp::uint32_kt index) const
Get the profile data.
Definition IProfiler.hpp:143
void resetDataById(dcpp::int32_kt id)
Reset profile data for the given id.
Definition IProfiler.hpp:426
const SProfileData & getGroupData(dcpp::uint32_kt index) const
Get profile data for a group.
Definition IProfiler.hpp:162
void resetDataByIndex(dcpp::uint32_kt index)
Reset profile data for the given index.
Definition IProfiler.hpp:435
virtual void printGroup(dcpp::nub::wstring &result, dcpp::uint32_kt groupIndex, bool suppressUncalled) const =0
Write the profile data of one group into a string.
Interface for getting and manipulating the virtual time.
Definition ITimer.hpp:15
virtual dcpp::uint32_kt getRealTime() const =0
Returns current real time in milliseconds of the system.
Class where the objects profile their own life-time.
Definition IProfiler.hpp:237
PProfileScope(dcpp::int32_kt id, const dcpp::nub::wstring &name, const dcpp::nub::wstring &groupName)
Object will create the given name, groupName combination for the id if it doesn't exist already.
Definition IProfiler.hpp:253
PProfileScope(dcpp::int32_kt id)
Construct with an known id.
Definition IProfiler.hpp:242
PProfileScope(const dcpp::nub::wstring &name, const dcpp::nub::wstring &groupName)
Object will create an id for the given name, groupName combination if they don't exist already.
Definition IProfiler.hpp:264
Used to store the profile data (and also used for profile group data).
Definition IProfiler.hpp:21
dcpp::uint32_kt getCallsCounter() const
Each time profiling for this data is stopped it increases the counter by 1.
Definition IProfiler.hpp:54
dcpp::uint32_kt getTimeSum() const
Time spend between start/stop.
Definition IProfiler.hpp:66
dcpp::uint32_kt getLongestTime() const
Longest time a profile call for this id took from start until it was stopped again.
Definition IProfiler.hpp:60
Axis aligned bounding box in 3d dimensional space.
Definition aabbox3d.hpp:22
void reset(T x, T y, T z)
Resets the bounding box to a one-point box.
Definition aabbox3d.hpp:50
As of Duckcpp 1.6, position2d is a synonym for vector2d.
Definition shared_device.hpp:34
unsigned int uint32_kt
32 bit unsigned variable.
Definition irrTypes.hpp:64
signed int int32_kt
32 bit signed variable.
Definition irrTypes.hpp:72
DUCKCPP_API IProfiler &IRRCALLCONV getProfiler()
Access the Duckcpp profiler object.

Duckcpp    @cppfx.xyz