source: nrEngine/include/Profiler.h @ 1

Revision 1, 10.5 KB checked in by art, 13 years ago (diff)
Line 
1/***************************************************************************
2 *                                                                         *
3 *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
4 *       mailto: <tevs@mpi-sb.mpg.de>                                      *
5 *                                                                         *
6 *   This program is free software; you can redistribute it and/or modify  *
7 *   it under the terms of the GNU General Public License as published by  *
8 *   the Free Software Foundation; either version 2 of the License, or     *
9 *   (at your option) any later version.                                   *
10 *                                                                         *
11 ***************************************************************************/
12
13/*
14 * The code is borrowed from Ogre-Engine.
15 * Many of the ideas for the profiler were borrowed from
16 * "Real-Time In-Game Profiling" by Steve Rabin which can be found in Game Programming
17 * Gems 1.
18 */
19
20#ifndef __NR_ENGINE_PROFILER_H_
21#define __NR_ENGINE_PROFILER_H_
22
23//----------------------------------------------------------------------------------
24// Includes
25//----------------------------------------------------------------------------------
26#include "Prerequisities.h"
27#include "Log.h"
28
29//----------------------------------------------------------------------------------
30// Defines
31//
32// If you want to profile your application, so use these macros and define NR_PROFILING
33//----------------------------------------------------------------------------------
34#ifdef NR_APP_PROFILING
35#   define NR_Profile( a )      ::nrEngine::Profile __nr_profile_instance( (a), false )
36#   define NR_ProfileBegin( a ) ::nrEngine::Engine::sProfiler()->beginProfile( (a), false )
37#   define NR_ProfileEnd( a )   ::nrEngine::Engine::sProfiler()->endProfile( (a), false )
38#else
39#   define NR_Profile( a )
40#   define NR_ProfileBegin( a )
41#   define NR_ProfileEnd( a )
42#endif
43
44
45
46//----------------------------------------------------------------------------------
47// This macros is used to profile the engine and not the application
48// Actually it is the same macro but here we separate the engine profiling from
49// application profiling, so the user can either enable or disable one of them
50//----------------------------------------------------------------------------------
51#ifdef NR_ENGINE_PROFILING
52#   define _nrEngineProfile( a )      Profile __nr_profile_instance( (a), true )
53#   define _nrEngineProfileBegin( a ) Engine::sProfiler()->beginProfile( (a), true )
54#   define _nrEngineProfileEnd( a )   Engine::sProfiler()->endProfile( (a), true )
55#else
56#   define _nrEngineProfile( a )
57#   define _nrEngineProfileBegin( a )
58#   define _nrEngineProfileEnd( a )
59#endif
60
61
62namespace nrEngine{
63
64        //! Single profile processed by the profiler
65        /**
66         * Our profiler does store such kind of profiles and manage them.
67         * Use macro NR_Profile(name)  instead of instantiating this objects
68         * directly. <br>
69         * Using of such kind of macros does help to profile a single scope:
70         * i.e.:
71         * <code>
72         * {
73         *              NR_Profile("Scope");
74         *              ....
75         * }
76         * </code>
77         * \ingroup gp
78         **/
79        class _NRExport Profile {
80                public:
81                       
82                        /**
83                         * Create an instance of this class and start profiling for this profile.
84                         **/
85                        Profile(const ::std::string& name, bool isSystemProfile = false);
86                       
87                        /**
88                         * Release used memory and stop the profiler for this profile.
89                         **/
90                        ~Profile();
91                       
92                private:
93                       
94                        //! Name of the profile, must be unique
95                        std::string mName;
96
97                        //! Is this is a system profile
98                        bool mSystemProfile;
99                       
100        };
101       
102       
103        //! The profiler allows you to measure the performance of your code
104        /**
105         * Profiler is a singleton object which is created by
106         * initializing the engine. Profiler does use a time source provide
107         * system time to allow to measure the time differencies.<br>
108         *
109         * Profiling is done stack wise. It means every time you starting
110         * a profile it will go onto the stack. Every time the profile is ending
111         * top most profile from the stack is removed and statistics is computed for it.
112         * Every time the stack is empty we compute the whole statistics for each profiles.
113         * The time in that the stack is not empty is called frame. We assume that you always
114         * profiles framewise.
115         *
116         * \ingroup gp
117         **/
118        class _NRExport Profiler {
119                public:
120
121                        /**
122                         * Begin of profiling. Please use NR_ProfileBegin(name) macro
123                         * instead of this function, so it can be removed in the release
124                         * version of you application
125                         *
126                         * \param name Unique name of the profile
127                         **/
128                        void beginProfile(const ::std::string& name, bool isSystemProfile = false);
129                         
130                        /**
131                         * End a profiling for the given profiling scope/name
132                         * Please use NR_ProfileEnd(name) macro instead of directly
133                         * calling this function.
134                         *
135                         * \param name Unique name of the profile
136                         **/
137                        void endProfile(const ::std::string& name, bool isSystemProfile = false);
138                       
139                        /**
140                         * Reset the profiler, so we clear all currently using
141                         * profilers.
142                         **/
143                        void reset();
144                       
145                        /**
146                         * Log current profile statistics to the log
147                         **/           
148                        void logResults(Log::LogTarget lt = Log::LOG_APP);
149                                       
150                        /**
151                         * Enable the profiling
152                         **/
153                        NR_FORCEINLINE void enable() { setEnable ( true );  }
154                       
155                        /**
156                         * Disable profiling
157                         **/
158                        NR_FORCEINLINE void disable(){ setEnable ( false ); }
159                       
160                        /**
161                         * Is profiler enabled
162                         **/
163                        NR_FORCEINLINE bool isEnabled() { return mEnabled; }
164                       
165                        /**
166                         * Set profiler enable/disable state
167                         **/
168                        void setEnable(bool enable);
169                                 
170                        /**
171                         * Enable or disable profiling of the system components.
172                         * If you enable this all engine components calling the profiler
173                         * will be counted in the statistics. Otherwise the engine
174                         * does not produce any profile information
175                         **/
176                        NR_FORCEINLINE void setEnableEngineProfiling(bool e) { mEngineProfileEnabled = e;}
177
178                        /**
179                         * Get information about engine profiling status. If true, so engine's
180                         * components are getting profiled. Otherwise no.
181                         **/
182                        NR_FORCEINLINE bool isEnabledEngineProfiling() const { return mEngineProfileEnabled; }
183                       
184                private:
185                                 
186                        //! Only engine can create instance of profiler
187                        friend class Engine;
188
189                        /**
190                         * Create a profiler object and use the given time source
191                         * to retrive the time. Engine will create the object
192                         * by itself and will specify a system time source object
193                         * instance for profiler using
194                         **/
195                        Profiler(SharedPtr<TimeSource> timeSource);
196
197                        /**
198                         * Virtual destructor of the profiler object that allows you
199                         * to derive your own profiler classes to overwrite some
200                         * methods of the defulat one
201                         **/
202                        ~Profiler();
203
204                        //! Time source used to retrieve time
205                        SharedPtr<TimeSource>           mTimeSource;
206
207                       
208                        //! Represents an individual profile call
209                        struct ProfileInstance {
210       
211                                //! The name of the profile
212                                ::std::string           name;
213       
214                                //! The name of the parent, empty string if root
215                                ::std::string           parent;
216
217                                //! Define if the profile is a system profile
218                                bool                            isSystemProfile;
219                               
220                                //! The time this profile was started
221                                float64                         currTime;
222       
223                                //! Represents the total time of all child profiles to subtract from this profile
224                                float64                         accum;
225       
226                                /// The hierarchical level of this profile, 0 being the root profile
227                                uint32                          hierarchicalLvl;
228                        };
229                       
230                        //! Represents the total timing information of a profile since profiles can be called more than once each frame
231                        struct ProfileFrame {
232                               
233                                //! The name of the profile
234                                ::std::string   name;
235                       
236                                //! The time this profile has taken this frame
237                                float64                 frameTime;
238                       
239                                //! The number of times this profile was called this frame
240                                uint32                  calls;
241                       
242                                //! The hierarchical level of this profile, 0 being the main loop
243                                uint32                  hierarchicalLvl;
244                       
245                                //! The total time incl. children this profile has taken this frame
246                                float64                 frameTotalTime;
247                               
248                        };
249                       
250                        //! Represents a history of each profile during the duration of the app
251                        struct ProfileHistory {
252       
253                                //! The name of the profile
254                                ::std::string   name;
255
256                                //! is system profile
257                                bool isSystemProfile;
258                               
259                                //! The current percentage of frame time this profile has taken
260                                float32 currentTime; // %
261       
262                                //! The maximum percentage of frame time this profile has taken
263                                float32 maxTime; // %
264       
265                                //! The minimum percentage of frame time this profile has taken
266                                float32 minTime; // %
267       
268                                //! The number of times this profile has been called this frame
269                                uint32  numCallsThisFrame;
270       
271                                //! The total percentage of frame time this profile has taken (used to calculate average)
272                                float32 totalTime; // %
273       
274                                //! The total number of times this profile was called (used to calculate average)
275                                uint32  totalCalls;
276       
277                                //! The hierarchical level of this profile, 0 being the root profile
278                                uint32  hierarchicalLvl;
279       
280                                //! Time of the profile has taken for running
281                                float32 realTime;
282                               
283                                //! Total time incl. children of the profile
284                                float32 realTotalTime;
285                               
286                                //! Giving order on the profiles, to allows sorting
287                                bool operator <(const ProfileHistory& p);
288                               
289                        };
290                               
291                       
292                        typedef ::std::list<ProfileInstance>            ProfileStack;
293                        typedef ::std::list<ProfileFrame>                       ProfileFrameList;
294                        typedef ::std::list<ProfileHistory>                     ProfileHistoryList;
295                        typedef ::std::map< ::std::string, ProfileHistoryList::iterator> ProfileHistoryMap;
296                        typedef ::std::map< ::std::string, bool>                DisabledProfileMap;
297
298                        //! A stack for each individual profile per frame
299                        ProfileStack mProfiles;
300       
301                        //! Accumulates the results of each profile per frame (since a profile can be called more than once a frame)
302                        ProfileFrameList mProfileFrame;
303       
304                        //! Keeps track of the statistics of each profile
305                        ProfileHistoryList mProfileHistory;
306       
307                        //! We use this for quick look-ups of profiles in the history list
308                        ProfileHistoryMap mProfileHistoryMap;
309
310                        //! The total time each frame takes
311                        float64 mTotalFrameTime;
312
313                        //! Wether we should profile the engine subsystem
314                        bool mEngineProfileEnabled;
315                       
316                        //! Whether this profiler is enabled
317                        bool mEnabled;
318       
319                        //! Keeps track of whether this profiler has received a request to be enabled/disabled
320                        bool mEnableStateChangePending;
321       
322                        //! Keeps track of the new enabled/disabled state that the user has requested which will be applied after the frame ends
323                        bool mNewEnableState;
324
325                        void processFrameStats();
326                        void changeEnableState();
327
328                        void logLine(const char* name, float32 min, float32 max, float32 frameTime, float32 totalTime, uint32 totalCalls);
329
330        };
331
332}; // end namespace
333
334#endif
335
Note: See TracBrowser for help on using the repository browser.