Merge pull request #74 from avoroshilov/manual-lifetime

Manual lifetime management for Multi-DLL
This commit is contained in:
Bartosz Taudul 2020-07-19 12:06:11 +02:00 committed by GitHub
commit 2bef3629b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 61 additions and 0 deletions

View File

@ -40,3 +40,5 @@ jobs:
make -j -C test make -j -C test
make -j -C test clean make -j -C test clean
make -j -C test TRACYFLAGS=-DTRACY_ON_DEMAND make -j -C test TRACYFLAGS=-DTRACY_ON_DEMAND
make -j -C test clean
make -j -C test TRACYFLAGS="-DTRACY_DELAYED_INIT -DTRACY_MANUAL_LIFETIME"

View File

@ -11,3 +11,4 @@ Thales Sabino <thales@codeplay.com> (OpenCL support)
Andrew Depke <andrewdepke@gmail.com> (Direct3D 12 support) Andrew Depke <andrewdepke@gmail.com> (Direct3D 12 support)
Simonas Kazlauskas <git@kazlauskas.me> (OSX CI, external bindings) Simonas Kazlauskas <git@kazlauskas.me> (OSX CI, external bindings)
Jakub Žádník <kubouch@gmail.com> (csvexport utility) Jakub Žádník <kubouch@gmail.com> (csvexport utility)
Andrey Voroshilov <andrew.voroshilov@gmail.com> (multi-DLL fixes)

View File

@ -924,6 +924,25 @@ struct ProfilerThreadData
# endif # endif
}; };
# ifdef TRACY_MANUAL_LIFETIME
ProfilerData* s_profilerData = nullptr;
TRACY_API void StartupProfiler()
{
s_profilerData = new ProfilerData;
s_profilerData->profiler.SpawnWorkerThreads();
}
static ProfilerData& GetProfilerData()
{
assert(s_profilerData);
return *s_profilerData;
}
TRACY_API void ShutdownProfiler()
{
delete s_profilerData;
s_profilerData = nullptr;
rpmalloc_finalize();
}
# else
static std::atomic<int> profilerDataLock { 0 }; static std::atomic<int> profilerDataLock { 0 };
static std::atomic<ProfilerData*> profilerData { nullptr }; static std::atomic<ProfilerData*> profilerData { nullptr };
@ -945,6 +964,7 @@ static ProfilerData& GetProfilerData()
} }
return *ptr; return *ptr;
} }
# endif
static ProfilerThreadData& GetProfilerThreadData() static ProfilerThreadData& GetProfilerThreadData()
{ {
@ -966,10 +986,12 @@ std::atomic<ThreadNameData*>& GetThreadNameData() { return GetProfilerData().thr
TRACY_API LuaZoneState& GetLuaZoneState() { return GetProfilerThreadData().luaZoneState; } TRACY_API LuaZoneState& GetLuaZoneState() { return GetProfilerThreadData().luaZoneState; }
# endif # endif
# ifndef TRACY_MANUAL_LIFETIME
namespace namespace
{ {
const auto& __profiler_init = GetProfiler(); const auto& __profiler_init = GetProfiler();
} }
# endif
#else #else
TRACY_API void InitRPMallocThread() TRACY_API void InitRPMallocThread()
@ -1094,6 +1116,13 @@ Profiler::Profiler()
m_userPort = atoi( userPort ); m_userPort = atoi( userPort );
} }
#if !defined(TRACY_DELAYED_INIT) || !defined(TRACY_MANUAL_LIFETIME)
SpawnWorkerThreads();
#endif
}
void Profiler::SpawnWorkerThreads()
{
s_thread = (Thread*)tracy_malloc( sizeof( Thread ) ); s_thread = (Thread*)tracy_malloc( sizeof( Thread ) );
new(s_thread) Thread( LaunchWorker, this ); new(s_thread) Thread( LaunchWorker, this );
@ -1185,6 +1214,8 @@ void Profiler::Worker()
s_profilerTid = syscall( SYS_gettid ); s_profilerTid = syscall( SYS_gettid );
#endif #endif
ThreadExitHandler threadExitHandler;
SetThreadName( "Tracy Profiler" ); SetThreadName( "Tracy Profiler" );
#ifdef TRACY_DATA_PORT #ifdef TRACY_DATA_PORT
@ -1605,6 +1636,8 @@ void Profiler::Worker()
void Profiler::CompressWorker() void Profiler::CompressWorker()
{ {
ThreadExitHandler threadExitHandler;
SetThreadName( "Tracy DXT1" ); SetThreadName( "Tracy DXT1" );
while( m_timeBegin.load( std::memory_order_relaxed ) == 0 ) std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) ); while( m_timeBegin.load( std::memory_order_relaxed ) == 0 ) std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
rpmalloc_thread_initialize(); rpmalloc_thread_initialize();

View File

@ -41,6 +41,10 @@
namespace tracy namespace tracy
{ {
#if defined(TRACY_DELAYED_INIT) && defined(TRACY_MANUAL_LIFETIME)
void StartupProfiler();
void ShutdownProfiler();
#endif
class GpuCtx; class GpuCtx;
class Profiler; class Profiler;
@ -119,6 +123,8 @@ public:
Profiler(); Profiler();
~Profiler(); ~Profiler();
void SpawnWorkerThreads();
static tracy_force_inline int64_t GetTime() static tracy_force_inline int64_t GetTime()
{ {
#ifdef TRACY_HW_TIMER #ifdef TRACY_HW_TIMER

View File

@ -321,6 +321,7 @@ static void SetupVsync()
s_threadVsync = (Thread*)tracy_malloc( sizeof( Thread ) ); s_threadVsync = (Thread*)tracy_malloc( sizeof( Thread ) );
new(s_threadVsync) Thread( [] (void*) { new(s_threadVsync) Thread( [] (void*) {
ThreadExitHandler threadExitHandler;
SetThreadName( "Tracy Vsync" ); SetThreadName( "Tracy Vsync" );
ProcessTrace( &s_traceHandleVsync2, 1, nullptr, nullptr ); ProcessTrace( &s_traceHandleVsync2, 1, nullptr, nullptr );
}, nullptr ); }, nullptr );
@ -455,6 +456,7 @@ void SysTraceStop()
void SysTraceWorker( void* ptr ) void SysTraceWorker( void* ptr )
{ {
ThreadExitHandler threadExitHandler;
SetThreadName( "Tracy SysTrace" ); SetThreadName( "Tracy SysTrace" );
ProcessTrace( &s_traceHandle2, 1, 0, 0 ); ProcessTrace( &s_traceHandle2, 1, 0, 0 );
ControlTrace( 0, KERNEL_LOGGER_NAME, s_prop, EVENT_TRACE_CONTROL_STOP ); ControlTrace( 0, KERNEL_LOGGER_NAME, s_prop, EVENT_TRACE_CONTROL_STOP );
@ -955,6 +957,7 @@ static void ProcessTraceLines( int fd )
void SysTraceWorker( void* ptr ) void SysTraceWorker( void* ptr )
{ {
ThreadExitHandler threadExitHandler;
SetThreadName( "Tracy SysTrace" ); SetThreadName( "Tracy SysTrace" );
int pipefd[2]; int pipefd[2];
if( pipe( pipefd ) == 0 ) if( pipe( pipefd ) == 0 )
@ -1028,6 +1031,7 @@ static void ProcessTraceLines( int fd )
void SysTraceWorker( void* ptr ) void SysTraceWorker( void* ptr )
{ {
ThreadExitHandler threadExitHandler;
SetThreadName( "Tracy SysTrace" ); SetThreadName( "Tracy SysTrace" );
char tmp[256]; char tmp[256];
memcpy( tmp, BasePath, sizeof( BasePath ) - 1 ); memcpy( tmp, BasePath, sizeof( BasePath ) - 1 );

View File

@ -10,6 +10,17 @@
namespace tracy namespace tracy
{ {
class ThreadExitHandler
{
public:
~ThreadExitHandler()
{
#ifdef TRACY_MANUAL_LIFETIME
rpmalloc_thread_finalize();
#endif
}
};
#if defined _WIN32 || defined __CYGWIN__ #if defined _WIN32 || defined __CYGWIN__
class Thread class Thread

View File

@ -427,6 +427,10 @@ For that you need a \emph{profiler DLL} to which your executable and the other D
If you are targeting Windows with Microsoft Visual Studio or MinGW, add the \texttt{TRACY\_IMPORTS} define to your application. If you are targeting Windows with Microsoft Visual Studio or MinGW, add the \texttt{TRACY\_IMPORTS} define to your application.
If you are experiencing crashes or freezes when manually loading/unloading a separate DLL with Tracy integration, you might want to try defining both \texttt{TRACY\_DELAYED\_INIT} and \texttt{TRACY\_MANUAL\_LIFETIME} macros.
\texttt{TRACY\_DELAYED\_INIT} enables a path where profiler data is gathered into one structure and initialized on the first request rather than statically at the DLL load at the expense of atomic load on each request to the profiler data. \texttt{TRACY\_MANUAL\_LIFETIME} flag augments this behavior to provide manual \texttt{StartupProfiler} and \texttt{ShutdownProfiler} functions that allow you to manually create and destroy the profiler data, removing the need to do an atomic load on each call, as well as letting you define an appropriate place to free the resources.
\subsubsection{Problematic platforms} \subsubsection{Problematic platforms}
Some OS vendors think that \emph{they} own and control the devices \emph{you} have paid for. This results in restricting usage of APIs that might 'confuse' you, or denying you access to information about what your computer is doing. Some OS vendors think that \emph{they} own and control the devices \emph{you} have paid for. This results in restricting usage of APIs that might 'confuse' you, or denying you access to information about what your computer is doing.