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))
This commit is contained in:
Erwin Coumans
2017-01-08 12:49:04 -08:00
parent 04d78cccfb
commit 5e6cfd70b5
9 changed files with 127 additions and 77 deletions

View File

@@ -293,8 +293,10 @@ void processProfileData( MyProfileWindow* profWindow, bool idle)
{ {
if (profWindow) if (profWindow)
{ {
if (profWindow->profIter)
profWindow->UpdateText(profWindow->profIter, idle); {
profWindow->UpdateText(profWindow->profIter, idle);
}
} }
} }

View File

@@ -255,6 +255,7 @@ void ExampleBrowserThreadFunc(void* userPtr,void* lsMemory)
do do
{ {
B3_PROFILE("ExampleBrowserThreadFunc");
float deltaTimeInSeconds = clock.getTimeMicroseconds()/1000000.f; float deltaTimeInSeconds = clock.getTimeMicroseconds()/1000000.f;
{ {
if (deltaTimeInSeconds > 0.1) if (deltaTimeInSeconds > 0.1)
@@ -263,9 +264,11 @@ void ExampleBrowserThreadFunc(void* userPtr,void* lsMemory)
} }
if (deltaTimeInSeconds < (gMinUpdateTimeMicroSecs/1e6)) if (deltaTimeInSeconds < (gMinUpdateTimeMicroSecs/1e6))
{ {
B3_PROFILE("clock.usleep");
clock.usleep(gMinUpdateTimeMicroSecs/10.); clock.usleep(gMinUpdateTimeMicroSecs/10.);
} else } else
{ {
B3_PROFILE("exampleBrowser->update");
clock.reset(); clock.reset();
exampleBrowser->update(deltaTimeInSeconds); exampleBrowser->update(deltaTimeInSeconds);
} }

View File

@@ -116,7 +116,6 @@ bool gAllowRetina = true;
bool gDisableDemoSelection = false; bool gDisableDemoSelection = false;
static class ExampleEntries* gAllExamples=0; static class ExampleEntries* gAllExamples=0;
bool sUseOpenGL2 = false; bool sUseOpenGL2 = false;
bool drawGUI=true;
#ifndef USE_OPENGL3 #ifndef USE_OPENGL3
extern bool useShadowMap; extern bool useShadowMap;
#endif #endif
@@ -298,17 +297,20 @@ struct btTimings
int m_activeBuffer; int m_activeBuffer;
btAlignedObjectArray<btTiming> m_timings[1]; btAlignedObjectArray<btTiming> m_timings[1];
}; };
#ifndef BT_NO_PROFILE
btTimings gTimings[BT_MAX_THREAD_COUNT]; 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; btClock clk;
#define MAX_NESTING 1024
bool gProfileDisabled = true; 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) void MyDummyEnterProfileZoneFunc(const char* msg)
{ {
@@ -322,8 +324,11 @@ void MyEnterProfileZoneFunc(const char* msg)
{ {
if (gProfileDisabled) if (gProfileDisabled)
return; return;
int threadId = btGetCurrentThreadIndex(); #ifndef BT_NO_PROFILE
int threadId = btQuickprofGetCurrentThreadIndex2();
if (threadId<0)
return;
if (gStackDepths[threadId]>=MAX_NESTING) if (gStackDepths[threadId]>=MAX_NESTING)
{ {
btAssert(0); btAssert(0);
@@ -336,14 +341,18 @@ void MyEnterProfileZoneFunc(const char* msg)
gStartTimes[threadId][gStackDepths[threadId]]=1+gStartTimes[threadId][gStackDepths[threadId]-1]; gStartTimes[threadId][gStackDepths[threadId]]=1+gStartTimes[threadId][gStackDepths[threadId]-1];
} }
gStackDepths[threadId]++; gStackDepths[threadId]++;
#endif
} }
void MyLeaveProfileZoneFunc() void MyLeaveProfileZoneFunc()
{ {
if (gProfileDisabled) if (gProfileDisabled)
return; return;
#ifndef BT_NO_PROFILE
int threadId = btGetCurrentThreadIndex(); int threadId = btQuickprofGetCurrentThreadIndex2();
if (threadId<0)
return;
if (gStackDepths[threadId]<=0) if (gStackDepths[threadId]<=0)
{ {
return; return;
@@ -356,6 +365,7 @@ void MyLeaveProfileZoneFunc()
unsigned long long int endTime = clk.getTimeNanoseconds(); unsigned long long int endTime = clk.getTimeNanoseconds();
gTimings[threadId].addTiming(name,threadId,startTime,endTime); gTimings[threadId].addTiming(name,threadId,startTime,endTime);
#endif //BT_NO_PROFILE
} }
@@ -455,6 +465,7 @@ void MyKeyboardCallback(int key, int state)
if (key=='p') if (key=='p')
{ {
#ifndef BT_NO_PROFILE
if (state) if (state)
{ {
m_firstTiming = true; m_firstTiming = true;
@@ -479,7 +490,7 @@ void MyKeyboardCallback(int key, int state)
gTimingFile = fopen(fileName,"w"); gTimingFile = fopen(fileName,"w");
fprintf(gTimingFile,"{\"traceEvents\":[\n"); fprintf(gTimingFile,"{\"traceEvents\":[\n");
//dump the content to file //dump the content to file
for (int i=0;i<BT_MAX_THREAD_COUNT;i++) for (int i=0;i<BT_QUICKPROF_MAX_THREAD_COUNT;i++)
{ {
if (gTimings[i].m_numTimings) if (gTimings[i].m_numTimings)
{ {
@@ -492,6 +503,7 @@ void MyKeyboardCallback(int key, int state)
gTimingFile = 0; gTimingFile = 0;
} }
#endif //BT_NO_PROFILE
} }
#ifndef NO_OPENGL3 #ifndef NO_OPENGL3

View File

@@ -272,10 +272,10 @@ struct MotionThreadLocalStorage
int threadId; int threadId;
}; };
int skip = 0;
int skip1 = 0;
float clampedDeltaTime = 0.2; float clampedDeltaTime = 0.2;
void MotionThreadFunc(void* userPtr,void* lsMemory) void MotionThreadFunc(void* userPtr,void* lsMemory)
{ {
printf("MotionThreadFunc thread started\n"); printf("MotionThreadFunc thread started\n");
@@ -299,24 +299,19 @@ void MotionThreadFunc(void* userPtr,void* lsMemory)
do do
{ {
BT_PROFILE("loop"); BT_PROFILE("loop");
deltaTimeInSeconds+= double(clock.getTimeMicroseconds())/1000000.;
{
BT_PROFILE("Sleep(0)");
b3Clock::usleep(0);
}
double dt = double(clock.getTimeMicroseconds())/1000000.;
deltaTimeInSeconds+= dt;
clock.reset(); clock.reset();
if (deltaTimeInSeconds<(1./5000.))
{ {
skip++;
skip1++;
//if (skip1>105)
if (skip1>5)
{
BT_PROFILE("b3Clock::usleep(250)");
b3Clock::usleep(250);
skip1 = 0;
}
} else
{
skip1=0;
//process special controller commands, such as //process special controller commands, such as
//VR controller button press/release and controller motion //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 //do nothing
} }

View File

@@ -187,12 +187,16 @@ double b3Clock::getTimeInSeconds()
void b3Clock::usleep(int microSeconds) void b3Clock::usleep(int microSeconds)
{ {
#ifdef _WIN32 #ifdef _WIN32
int millis = microSeconds/1000; if (microSeconds==0)
if (millis < 1)
{ {
millis = 1; Sleep(0);
} else
{
int millis = microSeconds/1000;
if (millis<1)
millis=1;
Sleep(millis);
} }
Sleep(millis);
#else #else
::usleep(microSeconds); ::usleep(microSeconds);

View File

@@ -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), 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[ 0], &gRoots[ 1], &gRoots[ 2], &gRoots[ 3],
&gRoots[ 4], &gRoots[ 5], &gRoots[ 6], &gRoots[ 7], &gRoots[ 4], &gRoots[ 5], &gRoots[ 6], &gRoots[ 7],
@@ -517,13 +516,16 @@ unsigned long int CProfileManager::ResetTime = 0;
CProfileIterator * CProfileManager::Get_Iterator( void ) CProfileIterator * CProfileManager::Get_Iterator( void )
{ {
int threadIndex = btGetCurrentThreadIndex(); int threadIndex = btQuickprofGetCurrentThreadIndex2();
if (threadIndex<0)
return 0;
return new CProfileIterator( &gRoots[threadIndex]); return new CProfileIterator( &gRoots[threadIndex]);
} }
void CProfileManager::CleanupMemory(void) void CProfileManager::CleanupMemory(void)
{ {
for (int i=0;i<BT_MAX_THREAD_COUNT;i++) for (int i=0;i<BT_QUICKPROF_MAX_THREAD_COUNT;i++)
{ {
gRoots[i].CleanupMemory(); gRoots[i].CleanupMemory();
} }
@@ -545,7 +547,10 @@ void CProfileManager::CleanupMemory(void)
*=============================================================================================*/ *=============================================================================================*/
void CProfileManager::Start_Profile( const char * name ) void CProfileManager::Start_Profile( const char * name )
{ {
int threadIndex = btGetCurrentThreadIndex(); int threadIndex = btQuickprofGetCurrentThreadIndex2();
if (threadIndex<0)
return;
if (name != gCurrentNodes[threadIndex]->Get_Name()) { if (name != gCurrentNodes[threadIndex]->Get_Name()) {
gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Sub_Node( 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 ) 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 // Return will indicate whether we should back up to our parent (we may
// be profiling a recursive function) // be profiling a recursive function)
if (gCurrentNodes[threadIndex]->Return()) { 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 ) void CProfileManager::Reset( void )
{ {
gProfileClock.reset(); gProfileClock.reset();
gRoots[btGetCurrentThreadIndex()].Reset(); int threadIndex = btQuickprofGetCurrentThreadIndex2();
gRoots[btGetCurrentThreadIndex()].Call(); if (threadIndex<0)
return;
gRoots[threadIndex].Reset();
gRoots[threadIndex].Call();
FrameCounter = 0; FrameCounter = 0;
Profile_Get_Ticks(&ResetTime); 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 btEnterProfileZoneDefault(const char* name)
{ {
} }
void btLeaveProfileZoneDefault() void btLeaveProfileZoneDefault()
{ {
} }
#endif //BT_NO_PROFILE #endif //BT_NO_PROFILE
static btEnterProfileZoneFunc* bts_enterFunc = btEnterProfileZoneDefault; static btEnterProfileZoneFunc* bts_enterFunc = btEnterProfileZoneDefault;
static btLeaveProfileZoneFunc* bts_leaveFunc = btLeaveProfileZoneDefault; static btLeaveProfileZoneFunc* bts_leaveFunc = btLeaveProfileZoneDefault;

View File

@@ -60,6 +60,8 @@ typedef void (btLeaveProfileZoneFunc)();
btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc(); btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc();
btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc(); btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc();
void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc); void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc);
void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc); void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc);
@@ -67,6 +69,11 @@ void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc);
//To disable built-in profiling, please comment out next line //To disable built-in profiling, please comment out next line
//#define BT_NO_PROFILE 1 //#define BT_NO_PROFILE 1
#ifndef BT_NO_PROFILE #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 <stdio.h>//@todo remove this, backwards compatibility #include <stdio.h>//@todo remove this, backwards compatibility
#include "btAlignedAllocator.h" #include "btAlignedAllocator.h"

View File

@@ -226,23 +226,6 @@ bool btSpinMutex::tryLock()
return true; 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 #endif // #if BT_THREADSAFE

View File

@@ -69,8 +69,6 @@ const unsigned int BT_MAX_THREAD_COUNT = 64;
SIMD_FORCE_INLINE void btMutexLock( btSpinMutex* ) {} SIMD_FORCE_INLINE void btMutexLock( btSpinMutex* ) {}
SIMD_FORCE_INLINE void btMutexUnlock( btSpinMutex* ) {} SIMD_FORCE_INLINE void btMutexUnlock( btSpinMutex* ) {}
SIMD_FORCE_INLINE bool btMutexTryLock( btSpinMutex* ) {return true;} SIMD_FORCE_INLINE bool btMutexTryLock( btSpinMutex* ) {return true;}
unsigned int btGetCurrentThreadIndex();
const unsigned int BT_MAX_THREAD_COUNT = 64;
#endif #endif