Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/external/bullet/LinearMath/btQuickprof.cpp @ 9341

Last change on this file since 9341 was 8351, checked in by rgrieder, 14 years ago

Merged kicklib2 branch back to trunk (includes former branches ois_update, mac_osx and kicklib).

Notes for updating

Linux:
You don't need an extra package for CEGUILua and Tolua, it's already shipped with CEGUI.
However you do need to make sure that the OgreRenderer is installed too with CEGUI 0.7 (may be a separate package).
Also, Orxonox now recognises if you install the CgProgramManager (a separate package available on newer Ubuntu on Debian systems).

Windows:
Download the new dependency packages versioned 6.0 and use these. If you have problems with that or if you don't like the in game console problem mentioned below, you can download the new 4.3 version of the packages (only available for Visual Studio 2005/2008).

Key new features:

  • *Support for Mac OS X*
  • Visual Studio 2010 support
  • Bullet library update to 2.77
  • OIS library update to 1.3
  • Support for CEGUI 0.7 —> Support for Arch Linux and even SuSE
  • Improved install target
  • Compiles now with GCC 4.6
  • Ogre Cg Shader plugin activated for Linux if available
  • And of course lots of bug fixes

There are also some regressions:

  • No support for CEGUI 0.5, Ogre 1.4 and boost 1.35 - 1.39 any more
  • In game console is not working in main menu for CEGUI 0.7
  • Tolua (just the C lib, not the application) and CEGUILua libraries are no longer in our repository. —> You will need to get these as well when compiling Orxonox
  • And of course lots of new bugs we don't yet know about
  • Property svn:eol-style set to native
File size: 16.2 KB
Line 
1/*
2
3***************************************************************************************************
4**
5** profile.cpp
6**
7** Real-Time Hierarchical Profiling for Game Programming Gems 3
8**
9** by Greg Hjelstrom & Byon Garrabrant
10**
11***************************************************************************************************/
12
13// Credits: The Clock class was inspired by the Timer classes in
14// Ogre (www.ogre3d.org).
15
16#include "btQuickprof.h"
17
18#ifndef BT_NO_PROFILE
19
20
21static btClock gProfileClock;
22
23
24#ifdef __CELLOS_LV2__
25#include <sys/sys_time.h>
26#include <sys/time_util.h>
27#include <stdio.h>
28#endif
29
30#if defined (SUNOS) || defined (__SUNOS__)
31#include <stdio.h> 
32#endif
33
34#if defined(WIN32) || defined(_WIN32)
35
36#define BT_USE_WINDOWS_TIMERS
37#define WIN32_LEAN_AND_MEAN
38#define NOWINRES
39#define NOMCX
40#define NOIME
41
42#ifdef _XBOX
43        #include <Xtl.h>
44#else //_XBOX
45        #include <windows.h>
46#endif //_XBOX
47
48#include <time.h>
49
50
51#else //_WIN32
52#include <sys/time.h>
53#endif //_WIN32
54
55#define mymin(a,b) (a > b ? a : b)
56
57struct btClockData
58{
59
60#ifdef BT_USE_WINDOWS_TIMERS
61        LARGE_INTEGER mClockFrequency;
62        DWORD mStartTick;
63        LONGLONG mPrevElapsedTime;
64        LARGE_INTEGER mStartTime;
65#else
66#ifdef __CELLOS_LV2__
67        uint64_t        mStartTime;
68#else
69        struct timeval mStartTime;
70#endif
71#endif //__CELLOS_LV2__
72
73};
74
75///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
76btClock::btClock()
77{
78        m_data = new btClockData;
79#ifdef BT_USE_WINDOWS_TIMERS
80        QueryPerformanceFrequency(&m_data->mClockFrequency);
81#endif
82        reset();
83}
84
85btClock::~btClock()
86{
87        delete m_data;
88}
89
90btClock::btClock(const btClock& other)
91{
92        m_data = new btClockData;
93        *m_data = *other.m_data;
94}
95
96btClock& btClock::operator=(const btClock& other)
97{
98        *m_data = *other.m_data;
99        return *this;
100}
101
102
103        /// Resets the initial reference time.
104void btClock::reset()
105{
106#ifdef BT_USE_WINDOWS_TIMERS
107        QueryPerformanceCounter(&m_data->mStartTime);
108        m_data->mStartTick = GetTickCount();
109        m_data->mPrevElapsedTime = 0;
110#else
111#ifdef __CELLOS_LV2__
112
113        typedef uint64_t  ClockSize;
114        ClockSize newTime;
115        //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
116        SYS_TIMEBASE_GET( newTime );
117        m_data->mStartTime = newTime;
118#else
119        gettimeofday(&m_data->mStartTime, 0);
120#endif
121#endif
122}
123
124/// Returns the time in ms since the last call to reset or since
125/// the btClock was created.
126unsigned long int btClock::getTimeMilliseconds()
127{
128#ifdef BT_USE_WINDOWS_TIMERS
129        LARGE_INTEGER currentTime;
130        QueryPerformanceCounter(&currentTime);
131        LONGLONG elapsedTime = currentTime.QuadPart - 
132                m_data->mStartTime.QuadPart;
133                // Compute the number of millisecond ticks elapsed.
134        unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 
135                m_data->mClockFrequency.QuadPart);
136                // Check for unexpected leaps in the Win32 performance counter. 
137        // (This is caused by unexpected data across the PCI to ISA
138                // bridge, aka south bridge.  See Microsoft KB274323.)
139                unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
140                signed long msecOff = (signed long)(msecTicks - elapsedTicks);
141                if (msecOff < -100 || msecOff > 100)
142                {
143                        // Adjust the starting time forwards.
144                        LONGLONG msecAdjustment = mymin(msecOff * 
145                                m_data->mClockFrequency.QuadPart / 1000, elapsedTime - 
146                                m_data->mPrevElapsedTime);
147                        m_data->mStartTime.QuadPart += msecAdjustment;
148                        elapsedTime -= msecAdjustment;
149
150                        // Recompute the number of millisecond ticks elapsed.
151                        msecTicks = (unsigned long)(1000 * elapsedTime / 
152                                m_data->mClockFrequency.QuadPart);
153                }
154
155                // Store the current elapsed time for adjustments next time.
156                m_data->mPrevElapsedTime = elapsedTime;
157
158                return msecTicks;
159#else
160
161#ifdef __CELLOS_LV2__
162                uint64_t freq=sys_time_get_timebase_frequency();
163                double dFreq=((double) freq) / 1000.0;
164                typedef uint64_t  ClockSize;
165                ClockSize newTime;
166                SYS_TIMEBASE_GET( newTime );
167                //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
168
169                return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
170#else
171
172                struct timeval currentTime;
173                gettimeofday(&currentTime, 0);
174                return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 + 
175                        (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
176#endif //__CELLOS_LV2__
177#endif
178}
179
180        /// Returns the time in us since the last call to reset or since
181        /// the Clock was created.
182unsigned long int btClock::getTimeMicroseconds()
183{
184#ifdef BT_USE_WINDOWS_TIMERS
185                LARGE_INTEGER currentTime;
186                QueryPerformanceCounter(&currentTime);
187                LONGLONG elapsedTime = currentTime.QuadPart - 
188                        m_data->mStartTime.QuadPart;
189
190                // Compute the number of millisecond ticks elapsed.
191                unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 
192                        m_data->mClockFrequency.QuadPart);
193
194                // Check for unexpected leaps in the Win32 performance counter. 
195                // (This is caused by unexpected data across the PCI to ISA
196                // bridge, aka south bridge.  See Microsoft KB274323.)
197                unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
198                signed long msecOff = (signed long)(msecTicks - elapsedTicks);
199                if (msecOff < -100 || msecOff > 100)
200                {
201                        // Adjust the starting time forwards.
202                        LONGLONG msecAdjustment = mymin(msecOff * 
203                                m_data->mClockFrequency.QuadPart / 1000, elapsedTime - 
204                                m_data->mPrevElapsedTime);
205                        m_data->mStartTime.QuadPart += msecAdjustment;
206                        elapsedTime -= msecAdjustment;
207                }
208
209                // Store the current elapsed time for adjustments next time.
210                m_data->mPrevElapsedTime = elapsedTime;
211
212                // Convert to microseconds.
213                unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / 
214                        m_data->mClockFrequency.QuadPart);
215
216                return usecTicks;
217#else
218
219#ifdef __CELLOS_LV2__
220                uint64_t freq=sys_time_get_timebase_frequency();
221                double dFreq=((double) freq)/ 1000000.0;
222                typedef uint64_t  ClockSize;
223                ClockSize newTime;
224                //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
225                SYS_TIMEBASE_GET( newTime );
226
227                return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
228#else
229
230                struct timeval currentTime;
231                gettimeofday(&currentTime, 0);
232                return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 + 
233                        (currentTime.tv_usec - m_data->mStartTime.tv_usec);
234#endif//__CELLOS_LV2__
235#endif
236}
237
238
239
240
241
242inline void Profile_Get_Ticks(unsigned long int * ticks)
243{
244        *ticks = gProfileClock.getTimeMicroseconds();
245}
246
247inline float Profile_Get_Tick_Rate(void)
248{
249//      return 1000000.f;
250        return 1000.f;
251
252}
253
254
255
256/***************************************************************************************************
257**
258** CProfileNode
259**
260***************************************************************************************************/
261
262/***********************************************************************************************
263 * INPUT:                                                                                      *
264 * name - pointer to a static string which is the name of this profile node                    *
265 * parent - parent pointer                                                                     *
266 *                                                                                             *
267 * WARNINGS:                                                                                   *
268 * The name is assumed to be a static pointer, only the pointer is stored and compared for     *
269 * efficiency reasons.                                                                         *
270 *=============================================================================================*/
271CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
272        Name( name ),
273        TotalCalls( 0 ),
274        TotalTime( 0 ),
275        StartTime( 0 ),
276        RecursionCounter( 0 ),
277        Parent( parent ),
278        Child( NULL ),
279        Sibling( NULL )
280{
281        Reset();
282}
283
284
285void    CProfileNode::CleanupMemory()
286{
287        delete ( Child);
288        Child = NULL;
289        delete ( Sibling);
290        Sibling = NULL;
291}
292
293CProfileNode::~CProfileNode( void )
294{
295        delete ( Child);
296        delete ( Sibling);
297}
298
299
300/***********************************************************************************************
301 * INPUT:                                                                                      *
302 * name - static string pointer to the name of the node we are searching for                   *
303 *                                                                                             *
304 * WARNINGS:                                                                                   *
305 * All profile names are assumed to be static strings so this function uses pointer compares   *
306 * to find the named node.                                                                     *
307 *=============================================================================================*/
308CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
309{
310        // Try to find this sub node
311        CProfileNode * child = Child;
312        while ( child ) {
313                if ( child->Name == name ) {
314                        return child;
315                }
316                child = child->Sibling;
317        }
318
319        // We didn't find it, so add it
320       
321        CProfileNode * node = new CProfileNode( name, this );
322        node->Sibling = Child;
323        Child = node;
324        return node;
325}
326
327
328void    CProfileNode::Reset( void )
329{
330        TotalCalls = 0;
331        TotalTime = 0.0f;
332       
333
334        if ( Child ) {
335                Child->Reset();
336        }
337        if ( Sibling ) {
338                Sibling->Reset();
339        }
340}
341
342
343void    CProfileNode::Call( void )
344{
345        TotalCalls++;
346        if (RecursionCounter++ == 0) {
347                Profile_Get_Ticks(&StartTime);
348        }
349}
350
351
352bool    CProfileNode::Return( void )
353{
354        if ( --RecursionCounter == 0 && TotalCalls != 0 ) { 
355                unsigned long int time;
356                Profile_Get_Ticks(&time);
357                time-=StartTime;
358                TotalTime += (float)time / Profile_Get_Tick_Rate();
359        }
360        return ( RecursionCounter == 0 );
361}
362
363
364/***************************************************************************************************
365**
366** CProfileIterator
367**
368***************************************************************************************************/
369CProfileIterator::CProfileIterator( CProfileNode * start )
370{
371        CurrentParent = start;
372        CurrentChild = CurrentParent->Get_Child();
373}
374
375
376void    CProfileIterator::First(void)
377{
378        CurrentChild = CurrentParent->Get_Child();
379}
380
381
382void    CProfileIterator::Next(void)
383{
384        CurrentChild = CurrentChild->Get_Sibling();
385}
386
387
388bool    CProfileIterator::Is_Done(void)
389{
390        return CurrentChild == NULL;
391}
392
393
394void    CProfileIterator::Enter_Child( int index )
395{
396        CurrentChild = CurrentParent->Get_Child();
397        while ( (CurrentChild != NULL) && (index != 0) ) {
398                index--;
399                CurrentChild = CurrentChild->Get_Sibling();
400        }
401
402        if ( CurrentChild != NULL ) {
403                CurrentParent = CurrentChild;
404                CurrentChild = CurrentParent->Get_Child();
405        }
406}
407
408
409void    CProfileIterator::Enter_Parent( void )
410{
411        if ( CurrentParent->Get_Parent() != NULL ) {
412                CurrentParent = CurrentParent->Get_Parent();
413        }
414        CurrentChild = CurrentParent->Get_Child();
415}
416
417
418/***************************************************************************************************
419**
420** CProfileManager
421**
422***************************************************************************************************/
423
424CProfileNode    CProfileManager::Root( "Root", NULL );
425CProfileNode *  CProfileManager::CurrentNode = &CProfileManager::Root;
426int                             CProfileManager::FrameCounter = 0;
427unsigned long int                       CProfileManager::ResetTime = 0;
428
429
430/***********************************************************************************************
431 * CProfileManager::Start_Profile -- Begin a named profile                                    *
432 *                                                                                             *
433 * Steps one level deeper into the tree, if a child already exists with the specified name     *
434 * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
435 *                                                                                             *
436 * INPUT:                                                                                      *
437 * name - name of this profiling record                                                        *
438 *                                                                                             *
439 * WARNINGS:                                                                                   *
440 * The string used is assumed to be a static string; pointer compares are used throughout      *
441 * the profiling code for efficiency.                                                          *
442 *=============================================================================================*/
443void    CProfileManager::Start_Profile( const char * name )
444{
445        if (name != CurrentNode->Get_Name()) {
446                CurrentNode = CurrentNode->Get_Sub_Node( name );
447        } 
448       
449        CurrentNode->Call();
450}
451
452
453/***********************************************************************************************
454 * CProfileManager::Stop_Profile -- Stop timing and record the results.                       *
455 *=============================================================================================*/
456void    CProfileManager::Stop_Profile( void )
457{
458        // Return will indicate whether we should back up to our parent (we may
459        // be profiling a recursive function)
460        if (CurrentNode->Return()) {
461                CurrentNode = CurrentNode->Get_Parent();
462        }
463}
464
465
466/***********************************************************************************************
467 * CProfileManager::Reset -- Reset the contents of the profiling system                       *
468 *                                                                                             *
469 *    This resets everything except for the tree structure.  All of the timing data is reset.  *
470 *=============================================================================================*/
471void    CProfileManager::Reset( void )
472{ 
473        gProfileClock.reset();
474        Root.Reset();
475    Root.Call();
476        FrameCounter = 0;
477        Profile_Get_Ticks(&ResetTime);
478}
479
480
481/***********************************************************************************************
482 * CProfileManager::Increment_Frame_Counter -- Increment the frame counter                    *
483 *=============================================================================================*/
484void CProfileManager::Increment_Frame_Counter( void )
485{
486        FrameCounter++;
487}
488
489
490/***********************************************************************************************
491 * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset         *
492 *=============================================================================================*/
493float CProfileManager::Get_Time_Since_Reset( void )
494{
495        unsigned long int time;
496        Profile_Get_Ticks(&time);
497        time -= ResetTime;
498        return (float)time / Profile_Get_Tick_Rate();
499}
500
501#include <stdio.h>
502
503void    CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
504{
505        profileIterator->First();
506        if (profileIterator->Is_Done())
507                return;
508
509        float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
510        int i;
511        int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
512        for (i=0;i<spacing;i++) printf(".");
513        printf("----------------------------------\n");
514        for (i=0;i<spacing;i++) printf(".");
515        printf("Profiling: %s (total running time: %.3f ms) ---\n",     profileIterator->Get_Current_Parent_Name(), parent_time );
516        float totalTime = 0.f;
517
518       
519        int numChildren = 0;
520       
521        for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next())
522        {
523                numChildren++;
524                float current_total_time = profileIterator->Get_Current_Total_Time();
525                accumulated_time += current_total_time;
526                float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
527                {
528                        int i;  for (i=0;i<spacing;i++) printf(".");
529                }
530                printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n",i, profileIterator->Get_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
531                totalTime += current_total_time;
532                //recurse into children
533        }
534
535        if (parent_time < accumulated_time)
536        {
537                printf("what's wrong\n");
538        }
539        for (i=0;i<spacing;i++) printf(".");
540        printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:",parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
541       
542        for (i=0;i<numChildren;i++)
543        {
544                profileIterator->Enter_Child(i);
545                dumpRecursive(profileIterator,spacing+3);
546                profileIterator->Enter_Parent();
547        }
548}
549
550
551
552void    CProfileManager::dumpAll()
553{
554        CProfileIterator* profileIterator = 0;
555        profileIterator = CProfileManager::Get_Iterator();
556
557        dumpRecursive(profileIterator,0);
558
559        CProfileManager::Release_Iterator(profileIterator);
560}
561
562
563
564
565#endif //BT_NO_PROFILE
Note: See TracBrowser for help on using the repository browser.