mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-07-16 06:19:58 +00:00
321 lines
7.0 KiB
C++
321 lines
7.0 KiB
C++
//========= Copyright (c) Valve Corporation, All rights reserved. ============
|
|
//
|
|
// this is even smaller profiler than miniprofiler: there is no linking or bookkeeping
|
|
// of any kind, it's just to throw in quick profilers that don't mess with code speed
|
|
// even in CERT builds
|
|
//
|
|
#ifndef TIER0MICROPROFILERHDR
|
|
#define TIER0MICROPROFILERHDR
|
|
|
|
#include "platform.h"
|
|
|
|
|
|
// define this to 1 to enable microprofiler; 2 to enable miniprofiler
|
|
#ifndef ENABLE_MICRO_PROFILER
|
|
#define ENABLE_MICRO_PROFILER 1
|
|
#endif
|
|
|
|
|
|
class CMicroProfiler;
|
|
|
|
PLATFORM_INTERFACE void MicroProfilerAddTS( CMicroProfiler *pProfiler, uint64 numTimeBaseTicks );
|
|
PLATFORM_INTERFACE int64 GetHardwareClockReliably();
|
|
|
|
|
|
#ifdef IS_WINDOWS_PC
|
|
#include <intrin.h> // get __rdtsc
|
|
#endif
|
|
|
|
#ifdef __e2k__
|
|
#include <x86intrin.h>
|
|
#endif
|
|
|
|
inline unsigned long long GetTimebaseRegister( void )
|
|
{
|
|
return Plat_Rdtsc();
|
|
}
|
|
|
|
|
|
#if ENABLE_MICRO_PROFILER > 0
|
|
|
|
class CMicroProfilerSample
|
|
{
|
|
int64 m_nTimeBaseBegin; // time base is kept here instead of using -= and += for better reliability and to avoid a cache miss at the beginning of the profiled section
|
|
|
|
public:
|
|
CMicroProfilerSample()
|
|
{
|
|
m_nTimeBaseBegin = GetTimebaseRegister();
|
|
}
|
|
|
|
int64 GetElapsed()const
|
|
{
|
|
return GetTimebaseRegister() - m_nTimeBaseBegin;
|
|
}
|
|
};
|
|
|
|
|
|
#ifdef IS_WINDOWS_PC
|
|
class CMicroProfilerQpcSample
|
|
{
|
|
int64 m_nTimeBaseBegin; // time base is kept here instead of using -= and += for better reliability and to avoid a cache miss at the beginning of the profiled section
|
|
|
|
public:
|
|
CMicroProfilerQpcSample()
|
|
{
|
|
m_nTimeBaseBegin = GetHardwareClockReliably();
|
|
}
|
|
|
|
int64 GetElapsed()const
|
|
{
|
|
return GetHardwareClockReliably() - m_nTimeBaseBegin;
|
|
}
|
|
};
|
|
#else
|
|
typedef CMicroProfilerSample CMicroProfilerQpcSample;
|
|
#endif
|
|
|
|
|
|
class CMicroProfiler
|
|
{
|
|
public:
|
|
uint64 m_numTimeBaseTicks; // this will be totally screwed between Begin() and End()
|
|
uint64 m_numCalls;
|
|
public:
|
|
CMicroProfiler()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
CMicroProfiler( const CMicroProfiler &other )
|
|
{
|
|
m_numTimeBaseTicks = other.m_numTimeBaseTicks;
|
|
m_numCalls = other.m_numCalls;
|
|
}
|
|
|
|
CMicroProfiler &operator=( const CMicroProfiler &other )
|
|
{
|
|
m_numTimeBaseTicks = other.m_numTimeBaseTicks;
|
|
m_numCalls = other.m_numCalls;
|
|
return *this;
|
|
}
|
|
|
|
void Begin()
|
|
{
|
|
m_numTimeBaseTicks -= GetTimebaseRegister();
|
|
}
|
|
|
|
void End()
|
|
{
|
|
m_numTimeBaseTicks += GetTimebaseRegister();
|
|
m_numCalls ++;
|
|
}
|
|
void End( uint64 nCalls )
|
|
{
|
|
m_numTimeBaseTicks += GetTimebaseRegister();
|
|
m_numCalls += nCalls;
|
|
}
|
|
|
|
|
|
void Add( uint64 numTimeBaseTicks, uint64 numCalls = 1)
|
|
{
|
|
m_numTimeBaseTicks += numTimeBaseTicks;
|
|
m_numCalls += numCalls;
|
|
}
|
|
|
|
void AddTS( uint64 numTimeBaseTicks )
|
|
{
|
|
MicroProfilerAddTS( this, numTimeBaseTicks );
|
|
}
|
|
|
|
void Add(const CMicroProfilerSample &sample)
|
|
{
|
|
Add( sample.GetElapsed() );
|
|
}
|
|
|
|
void Add( const CMicroProfiler& profiler)
|
|
{
|
|
Add( profiler.m_numTimeBaseTicks, profiler.m_numCalls );
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
m_numTimeBaseTicks = 0;
|
|
m_numCalls = 0;
|
|
}
|
|
|
|
void Damp( int shift = 1 )
|
|
{
|
|
m_numTimeBaseTicks >>= shift;
|
|
m_numCalls >>= shift;
|
|
}
|
|
|
|
uint64 GetNumCalls() const
|
|
{
|
|
return m_numCalls;
|
|
}
|
|
|
|
uint64 GetNumTimeBaseTicks() const
|
|
{
|
|
return m_numTimeBaseTicks;
|
|
}
|
|
|
|
float GetAverageMilliseconds() const
|
|
{
|
|
return m_numCalls ? GetTotalMilliseconds() / m_numCalls : 0;
|
|
}
|
|
|
|
float GetTotalMilliseconds() const
|
|
{
|
|
return TimeBaseTicksToMilliseconds( m_numTimeBaseTicks );
|
|
}
|
|
|
|
static float TimeBaseTicksToMilliseconds( uint64 numTimeBaseTicks )
|
|
{
|
|
#if defined( _X360 ) || defined( _PS3 )
|
|
return numTimeBaseTicks / 79800.0 ;
|
|
#else
|
|
return numTimeBaseTicks / ( GetCPUInformation()->m_Speed * 0.001f );
|
|
#endif
|
|
}
|
|
float GetAverageTicks() const
|
|
{
|
|
#if defined( _X360 ) || defined( _PS3 )
|
|
return m_numTimeBaseTicks * 40.1f / m_numCalls; // timebase register is 79.8 MHz on these platforms
|
|
#else
|
|
return float( m_numTimeBaseTicks / m_numCalls );
|
|
#endif
|
|
}
|
|
friend const CMicroProfiler operator + ( const CMicroProfiler &left, const CMicroProfiler &right );
|
|
|
|
void Accumulate( const CMicroProfiler &other )
|
|
{
|
|
m_numCalls += other.m_numCalls;
|
|
m_numTimeBaseTicks += other.m_numTimeBaseTicks;
|
|
}
|
|
};
|
|
|
|
|
|
inline const CMicroProfiler operator + ( const CMicroProfiler &left, const CMicroProfiler &right )
|
|
{
|
|
CMicroProfiler result;
|
|
result.m_numCalls = left.m_numCalls + right.m_numCalls;
|
|
result.m_numTimeBaseTicks = left.m_numTimeBaseTicks + right.m_numTimeBaseTicks;
|
|
return result;
|
|
}
|
|
|
|
|
|
class CMicroProfilerGuard: public CMicroProfilerSample
|
|
{
|
|
CMicroProfiler *m_pProfiler;
|
|
public:
|
|
CMicroProfilerGuard( CMicroProfiler *pProfiler )
|
|
{
|
|
m_pProfiler = pProfiler;
|
|
}
|
|
~CMicroProfilerGuard()
|
|
{
|
|
m_pProfiler->Add( GetElapsed() );
|
|
}
|
|
};
|
|
|
|
|
|
class CMicroProfilerGuardWithCount: public CMicroProfilerSample
|
|
{
|
|
CMicroProfiler *m_pProfiler;
|
|
uint m_nCount;
|
|
public:
|
|
CMicroProfilerGuardWithCount( CMicroProfiler *pProfiler, uint nCount )
|
|
{
|
|
m_nCount = nCount;
|
|
m_pProfiler = pProfiler;
|
|
}
|
|
void OverrideCount( uint nCount ) { m_nCount = nCount; }
|
|
~CMicroProfilerGuardWithCount( )
|
|
{
|
|
m_pProfiler->Add( GetElapsed( ), m_nCount );
|
|
}
|
|
};
|
|
|
|
|
|
// thread-safe variant of the same profiler
|
|
class CMicroProfilerGuardTS: public CMicroProfilerSample
|
|
{
|
|
CMicroProfiler *m_pProfiler;
|
|
public:
|
|
CMicroProfilerGuardTS( CMicroProfiler *pProfiler )
|
|
{
|
|
m_pProfiler = pProfiler;
|
|
}
|
|
~CMicroProfilerGuardTS()
|
|
{
|
|
m_pProfiler->AddTS( GetElapsed() );
|
|
}
|
|
};
|
|
|
|
|
|
#define MICRO_PROFILER_NAME_0(LINE) localAutoMpg##LINE
|
|
#define MICRO_PROFILER_NAME(LINE) MICRO_PROFILER_NAME_0(LINE)
|
|
#define MICRO_PROFILE( MP ) CMicroProfilerGuard MICRO_PROFILER_NAME(__LINE__)( &( MP ) )
|
|
#define MICRO_PROFILE_TS( MP ) CMicroProfilerGuardTS MICRO_PROFILER_NAME(__LINE__)( &( MP ) )
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
class CMicroProfilerSample
|
|
{public:
|
|
CMicroProfilerSample(){}
|
|
int GetElapsed()const{ return 0;}
|
|
};
|
|
|
|
typedef CMicroProfilerSample CMicroProfilerQpcSample;
|
|
|
|
|
|
|
|
class CMicroProfiler
|
|
{ public:
|
|
CMicroProfiler(){}
|
|
CMicroProfiler &operator=( const CMicroProfiler &other ) { return *this; }
|
|
void Begin(){}
|
|
void End(){}
|
|
void End( uint32 ){}
|
|
void Add( uint64 numTimeBaseTicks, int numCalls = 1){}
|
|
void AddTS( uint64 numTimeBaseTicks ) {}
|
|
void Add( const CMicroProfilerSample &sample){}
|
|
void Add( const CMicroProfiler& profiler) {}
|
|
void Reset(){}
|
|
void Damp(int shift = 1){}
|
|
uint64 GetNumCalls() const { return 0; }
|
|
uint64 GetNumTimeBaseTicks() const { return 0; }
|
|
int64 GetNumTimeBaseTicksExclusive() const { return 0; }
|
|
float GetAverageMilliseconds()const { return 0; }
|
|
float GetTotalMilliseconds()const { return 0; }
|
|
static float TimeBaseTicksToMilliseconds( uint64 numTimeBaseTicks ) { return 0; }
|
|
float GetAverageTicks() const { return 0; }
|
|
friend const CMicroProfiler operator + ( const CMicroProfiler &left, const CMicroProfiler &right );
|
|
};
|
|
|
|
inline const CMicroProfiler operator + ( const CMicroProfiler &left, const CMicroProfiler &right ) { return left; }
|
|
|
|
class CMicroProfilerGuard: public CMicroProfilerSample
|
|
{
|
|
public:
|
|
CMicroProfilerGuard( CMicroProfiler *pProfiler ){}
|
|
~CMicroProfilerGuard(){}
|
|
};
|
|
|
|
class CMicroProfilerGuardTS: public CMicroProfilerSample
|
|
{
|
|
public:
|
|
CMicroProfilerGuardTS( CMicroProfiler *pProfiler ){}
|
|
~CMicroProfilerGuardTS(){}
|
|
};
|
|
|
|
#define MICRO_PROFILE( MP )
|
|
#endif
|
|
|
|
|
|
#endif
|