From 5e6cfd70b5dcdbede35f11a733e0125ecf49502b Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sun, 8 Jan 2017 12:49:04 -0800 Subject: [PATCH] iOS platform and Android don't have __thread local storage, so avoid multi-threaded profiler on those (only on _WIN32, __linux__ and __APPLE__ and not TARGET_OS_IPHONE Add a Sleep(0) for Windows to yield threads (and not Sleep(1)) --- .../GwenGUISupport/GwenProfileWindow.cpp | 6 +- .../InProcessExampleBrowser.cpp | 3 + .../ExampleBrowser/OpenGLExampleBrowser.cpp | 38 +++++--- .../SharedMemory/PhysicsServerExample.cpp | 32 +++---- examples/Utils/b3Clock.cpp | 12 ++- src/LinearMath/btQuickprof.cpp | 87 +++++++++++++++---- src/LinearMath/btQuickprof.h | 7 ++ src/LinearMath/btThreads.cpp | 17 ---- src/LinearMath/btThreads.h | 2 - 9 files changed, 127 insertions(+), 77 deletions(-) diff --git a/examples/ExampleBrowser/GwenGUISupport/GwenProfileWindow.cpp b/examples/ExampleBrowser/GwenGUISupport/GwenProfileWindow.cpp index c23554f41..cce4ebacf 100644 --- a/examples/ExampleBrowser/GwenGUISupport/GwenProfileWindow.cpp +++ b/examples/ExampleBrowser/GwenGUISupport/GwenProfileWindow.cpp @@ -293,8 +293,10 @@ void processProfileData( MyProfileWindow* profWindow, bool idle) { if (profWindow) { - - profWindow->UpdateText(profWindow->profIter, idle); + if (profWindow->profIter) + { + profWindow->UpdateText(profWindow->profIter, idle); + } } } diff --git a/examples/ExampleBrowser/InProcessExampleBrowser.cpp b/examples/ExampleBrowser/InProcessExampleBrowser.cpp index 0732d39b3..5dde14f30 100644 --- a/examples/ExampleBrowser/InProcessExampleBrowser.cpp +++ b/examples/ExampleBrowser/InProcessExampleBrowser.cpp @@ -255,6 +255,7 @@ void ExampleBrowserThreadFunc(void* userPtr,void* lsMemory) do { + B3_PROFILE("ExampleBrowserThreadFunc"); float deltaTimeInSeconds = clock.getTimeMicroseconds()/1000000.f; { if (deltaTimeInSeconds > 0.1) @@ -263,9 +264,11 @@ void ExampleBrowserThreadFunc(void* userPtr,void* lsMemory) } if (deltaTimeInSeconds < (gMinUpdateTimeMicroSecs/1e6)) { + B3_PROFILE("clock.usleep"); clock.usleep(gMinUpdateTimeMicroSecs/10.); } else { + B3_PROFILE("exampleBrowser->update"); clock.reset(); exampleBrowser->update(deltaTimeInSeconds); } diff --git a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp index 3fe496020..6842e03c2 100644 --- a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp +++ b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp @@ -116,7 +116,6 @@ bool gAllowRetina = true; bool gDisableDemoSelection = false; static class ExampleEntries* gAllExamples=0; bool sUseOpenGL2 = false; -bool drawGUI=true; #ifndef USE_OPENGL3 extern bool useShadowMap; #endif @@ -298,17 +297,20 @@ struct btTimings int m_activeBuffer; btAlignedObjectArray m_timings[1]; }; - -btTimings gTimings[BT_MAX_THREAD_COUNT]; +#ifndef BT_NO_PROFILE +btTimings gTimings[BT_QUICKPROF_MAX_THREAD_COUNT]; +#define MAX_NESTING 1024 +int gStackDepths[BT_QUICKPROF_MAX_THREAD_COUNT] = {0}; +const char* gFuncNames[BT_QUICKPROF_MAX_THREAD_COUNT][MAX_NESTING]; +unsigned long long int gStartTimes[BT_QUICKPROF_MAX_THREAD_COUNT][MAX_NESTING]; +#endif btClock clk; -#define MAX_NESTING 1024 + bool gProfileDisabled = true; -int gStackDepths[BT_MAX_THREAD_COUNT] = {0}; -const char* gFuncNames[BT_MAX_THREAD_COUNT][MAX_NESTING]; -unsigned long long int gStartTimes[BT_MAX_THREAD_COUNT][MAX_NESTING]; + void MyDummyEnterProfileZoneFunc(const char* msg) { @@ -322,8 +324,11 @@ void MyEnterProfileZoneFunc(const char* msg) { if (gProfileDisabled) return; - int threadId = btGetCurrentThreadIndex(); - +#ifndef BT_NO_PROFILE + int threadId = btQuickprofGetCurrentThreadIndex2(); + if (threadId<0) + return; + if (gStackDepths[threadId]>=MAX_NESTING) { btAssert(0); @@ -336,14 +341,18 @@ void MyEnterProfileZoneFunc(const char* msg) gStartTimes[threadId][gStackDepths[threadId]]=1+gStartTimes[threadId][gStackDepths[threadId]-1]; } gStackDepths[threadId]++; +#endif + } void MyLeaveProfileZoneFunc() { if (gProfileDisabled) return; - - int threadId = btGetCurrentThreadIndex(); - +#ifndef BT_NO_PROFILE + int threadId = btQuickprofGetCurrentThreadIndex2(); + if (threadId<0) + return; + if (gStackDepths[threadId]<=0) { return; @@ -356,6 +365,7 @@ void MyLeaveProfileZoneFunc() unsigned long long int endTime = clk.getTimeNanoseconds(); gTimings[threadId].addTiming(name,threadId,startTime,endTime); +#endif //BT_NO_PROFILE } @@ -455,6 +465,7 @@ void MyKeyboardCallback(int key, int state) if (key=='p') { +#ifndef BT_NO_PROFILE if (state) { m_firstTiming = true; @@ -479,7 +490,7 @@ void MyKeyboardCallback(int key, int state) gTimingFile = fopen(fileName,"w"); fprintf(gTimingFile,"{\"traceEvents\":[\n"); //dump the content to file - for (int i=0;i105) - if (skip1>5) - { - BT_PROFILE("b3Clock::usleep(250)"); - b3Clock::usleep(250); - skip1 = 0; - } - } else - { - skip1=0; //process special controller commands, such as //VR controller button press/release and controller motion @@ -450,9 +445,6 @@ void MotionThreadFunc(void* userPtr,void* lsMemory) } - printf("finished, #skip = %d, skip1 = %d\n",skip,skip1); - skip=0; - skip1=0; //do nothing } diff --git a/examples/Utils/b3Clock.cpp b/examples/Utils/b3Clock.cpp index c2db16264..82014e630 100644 --- a/examples/Utils/b3Clock.cpp +++ b/examples/Utils/b3Clock.cpp @@ -187,12 +187,16 @@ double b3Clock::getTimeInSeconds() void b3Clock::usleep(int microSeconds) { #ifdef _WIN32 - int millis = microSeconds/1000; - if (millis < 1) + if (microSeconds==0) { - millis = 1; + Sleep(0); + } else + { + int millis = microSeconds/1000; + if (millis<1) + millis=1; + Sleep(millis); } - Sleep(millis); #else ::usleep(microSeconds); diff --git a/src/LinearMath/btQuickprof.cpp b/src/LinearMath/btQuickprof.cpp index 522dd8bd1..8233daa57 100644 --- a/src/LinearMath/btQuickprof.cpp +++ b/src/LinearMath/btQuickprof.cpp @@ -466,11 +466,10 @@ void CProfileIterator::Enter_Parent( void ) ** ***************************************************************************************************/ -#include "btThreads.h" -CProfileNode gRoots[BT_MAX_THREAD_COUNT]={ +CProfileNode gRoots[BT_QUICKPROF_MAX_THREAD_COUNT]={ CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL),CProfileNode("Root",NULL), @@ -490,7 +489,7 @@ CProfileNode gRoots[BT_MAX_THREAD_COUNT]={ }; -CProfileNode* gCurrentNodes[BT_MAX_THREAD_COUNT]= +CProfileNode* gCurrentNodes[BT_QUICKPROF_MAX_THREAD_COUNT]= { &gRoots[ 0], &gRoots[ 1], &gRoots[ 2], &gRoots[ 3], &gRoots[ 4], &gRoots[ 5], &gRoots[ 6], &gRoots[ 7], @@ -517,13 +516,16 @@ unsigned long int CProfileManager::ResetTime = 0; CProfileIterator * CProfileManager::Get_Iterator( void ) { - int threadIndex = btGetCurrentThreadIndex(); + int threadIndex = btQuickprofGetCurrentThreadIndex2(); + if (threadIndex<0) + return 0; + return new CProfileIterator( &gRoots[threadIndex]); } void CProfileManager::CleanupMemory(void) { - for (int i=0;iGet_Name()) { gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Sub_Node( name ); } @@ -559,7 +564,10 @@ void CProfileManager::Start_Profile( const char * name ) *=============================================================================================*/ void CProfileManager::Stop_Profile( void ) { - int threadIndex = btGetCurrentThreadIndex(); + int threadIndex = btQuickprofGetCurrentThreadIndex2(); + if (threadIndex<0) + return; + // Return will indicate whether we should back up to our parent (we may // be profiling a recursive function) if (gCurrentNodes[threadIndex]->Return()) { @@ -568,14 +576,7 @@ void CProfileManager::Stop_Profile( void ) } -void btEnterProfileZoneDefault(const char* name) -{ - CProfileManager::Start_Profile( name ); -} -void btLeaveProfileZoneDefault() -{ - CProfileManager::Stop_Profile(); -} + @@ -587,8 +588,11 @@ void btLeaveProfileZoneDefault() void CProfileManager::Reset( void ) { gProfileClock.reset(); - gRoots[btGetCurrentThreadIndex()].Reset(); - gRoots[btGetCurrentThreadIndex()].Call(); + int threadIndex = btQuickprofGetCurrentThreadIndex2(); + if (threadIndex<0) + return; + gRoots[threadIndex].Reset(); + gRoots[threadIndex].Call(); FrameCounter = 0; Profile_Get_Ticks(&ResetTime); } @@ -676,18 +680,63 @@ void CProfileManager::dumpAll() } -#else + +unsigned int btQuickprofGetCurrentThreadIndex2() +{ + const unsigned int kNullIndex = ~0U; +#ifdef _WIN32 + __declspec( thread ) static unsigned int sThreadIndex = kNullIndex; +#else +#ifdef __APPLE__ + #if TARGET_OS_IPHONE + unsigned int sThreadIndex = 0; + return -1; + #else + static __thread unsigned int sThreadIndex = kNullIndex; + #endif +#else//__APPLE__ +#if __linux__ + static __thread unsigned int sThreadIndex = kNullIndex; +#else + unsigned int sThreadIndex = 0; + return -1; +#endif +#endif//__APPLE__ + +#endif + static int gThreadCounter=0; + + if ( sThreadIndex == kNullIndex ) + { + sThreadIndex = gThreadCounter++; + } + return sThreadIndex; +} + +void btEnterProfileZoneDefault(const char* name) +{ + CProfileManager::Start_Profile( name ); +} +void btLeaveProfileZoneDefault() +{ + CProfileManager::Stop_Profile(); +} + + +#else void btEnterProfileZoneDefault(const char* name) { } void btLeaveProfileZoneDefault() { } - #endif //BT_NO_PROFILE + + + static btEnterProfileZoneFunc* bts_enterFunc = btEnterProfileZoneDefault; static btLeaveProfileZoneFunc* bts_leaveFunc = btLeaveProfileZoneDefault; diff --git a/src/LinearMath/btQuickprof.h b/src/LinearMath/btQuickprof.h index 664aa4d45..fd0030715 100644 --- a/src/LinearMath/btQuickprof.h +++ b/src/LinearMath/btQuickprof.h @@ -60,6 +60,8 @@ typedef void (btLeaveProfileZoneFunc)(); btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc(); btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc(); + + void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc); void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc); @@ -67,6 +69,11 @@ void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc); //To disable built-in profiling, please comment out next line //#define BT_NO_PROFILE 1 #ifndef BT_NO_PROFILE +//btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined, +//otherwise returns thread index in range [0..maxThreads] +unsigned int btQuickprofGetCurrentThreadIndex2(); +const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT = 64; + #include //@todo remove this, backwards compatibility #include "btAlignedAllocator.h" diff --git a/src/LinearMath/btThreads.cpp b/src/LinearMath/btThreads.cpp index f3501eec9..b72301a2e 100644 --- a/src/LinearMath/btThreads.cpp +++ b/src/LinearMath/btThreads.cpp @@ -226,23 +226,6 @@ bool btSpinMutex::tryLock() return true; } -unsigned int btGetCurrentThreadIndex() -{ - const unsigned int kNullIndex = ~0U; -#ifdef _WIN32 - __declspec( thread ) static unsigned int sThreadIndex = kNullIndex; - -#else - static __thread unsigned int sThreadIndex = kNullIndex; -#endif - static int gThreadCounter=0; - - if ( sThreadIndex == kNullIndex ) - { - sThreadIndex = gThreadCounter++; - } - return sThreadIndex; -} #endif // #if BT_THREADSAFE diff --git a/src/LinearMath/btThreads.h b/src/LinearMath/btThreads.h index 7a29ab4c0..a15e5250b 100644 --- a/src/LinearMath/btThreads.h +++ b/src/LinearMath/btThreads.h @@ -69,8 +69,6 @@ const unsigned int BT_MAX_THREAD_COUNT = 64; SIMD_FORCE_INLINE void btMutexLock( btSpinMutex* ) {} SIMD_FORCE_INLINE void btMutexUnlock( btSpinMutex* ) {} SIMD_FORCE_INLINE bool btMutexTryLock( btSpinMutex* ) {return true;} -unsigned int btGetCurrentThreadIndex(); -const unsigned int BT_MAX_THREAD_COUNT = 64; #endif