Skip to content
Snippets Groups Projects
Commit e3cb3e9e authored by Richard Nelson's avatar Richard Nelson
Browse files

fixed a bug in LLFastTimer data gathering, and made them even faster (122 cycles on my 2.5Ghz Xeon)

can call LLFastTimer::nextFrame with timers still on the stack...first step towards more flexible data gathering
LLInstanceTracker works with statically allocated instances now
reviewed by Brad
parent 8799193f
Branches
Tags
No related merge requests found
...@@ -37,7 +37,75 @@ ...@@ -37,7 +37,75 @@
#define FAST_TIMER_ON 1 #define FAST_TIMER_ON 1
U64 get_cpu_clock_count(); #if LL_WINDOWS
// shift off lower 8 bits for lower resolution but longer term timing
// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
inline U32 get_cpu_clock_count_32()
{
U32 ret_val;
__asm
{
_emit 0x0f
_emit 0x31
shr eax,8
shl edx,24
or eax, edx
mov dword ptr [ret_val], eax
}
return ret_val;
}
// return full timer value, still shifted by 8 bits
inline U64 get_cpu_clock_count_64()
{
U64 ret_val;
__asm
{
_emit 0x0f
_emit 0x31
mov eax,eax
mov edx,edx
mov dword ptr [ret_val+4], edx
mov dword ptr [ret_val], eax
}
return ret_val >> 8;
}
#endif // LL_WINDOWS
#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
inline U32 get_cpu_clock_count_32()
{
U64 x;
__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
return (U32)x;
}
inline U32 get_cpu_clock_count_64()
{
U64 x;
__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
return x;
}
#endif
#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__))
//
// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock
//
// Just use gettimeofday implementation for now
inline U32 get_cpu_clock_count_32()
{
return (U32)get_clock_count();
}
inline U32 get_cpu_clock_count_64()
{
return get_clock_count();
}
#endif
class LLMutex; class LLMutex;
...@@ -52,13 +120,14 @@ class LLFastTimer ...@@ -52,13 +120,14 @@ class LLFastTimer
class NamedTimer class NamedTimer
: public LLInstanceTracker<NamedTimer> : public LLInstanceTracker<NamedTimer>
{ {
friend class DeclareTimer;
public: public:
~NamedTimer(); ~NamedTimer();
enum { HISTORY_NUM = 60 }; enum { HISTORY_NUM = 60 };
const std::string& getName() { return mName; } const std::string& getName() const { return mName; }
NamedTimer* getParent() { return mParent; } NamedTimer* getParent() const { return mParent; }
void setParent(NamedTimer* parent); void setParent(NamedTimer* parent);
S32 getDepth(); S32 getDepth();
std::string getToolTip(S32 history_index = -1); std::string getToolTip(S32 history_index = -1);
...@@ -71,11 +140,11 @@ class LLFastTimer ...@@ -71,11 +140,11 @@ class LLFastTimer
void setCollapsed(bool collapsed) { mCollapsed = collapsed; } void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
bool getCollapsed() const { return mCollapsed; } bool getCollapsed() const { return mCollapsed; }
U64 getCountAverage() const { return mCountAverage; } U32 getCountAverage() const { return mCountAverage; }
U64 getCallAverage() const { return mCallAverage; } U32 getCallAverage() const { return mCallAverage; }
U64 getHistoricalCount(S32 history_index = 0) const; U32 getHistoricalCount(S32 history_index = 0) const;
U64 getHistoricalCalls(S32 history_index = 0) const; U32 getHistoricalCalls(S32 history_index = 0) const;
static NamedTimer& getRootNamedTimer(); static NamedTimer& getRootNamedTimer();
...@@ -83,8 +152,7 @@ class LLFastTimer ...@@ -83,8 +152,7 @@ class LLFastTimer
{ {
FrameState(NamedTimer* timerp); FrameState(NamedTimer* timerp);
U64 mSelfTimeCounter; U32 mSelfTimeCounter;
U64 mLastStartTime; // most recent time when this timer was started
U32 mCalls; U32 mCalls;
FrameState* mParent; // info for caller timer FrameState* mParent; // info for caller timer
FrameState* mLastCaller; // used to bootstrap tree construction FrameState* mLastCaller; // used to bootstrap tree construction
...@@ -93,11 +161,6 @@ class LLFastTimer ...@@ -93,11 +161,6 @@ class LLFastTimer
bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
}; };
FrameState& getFrameStateFast() const
{
return (*sTimerInfos)[mFrameStateIndex];
}
S32 getFrameStateIndex() const { return mFrameStateIndex; } S32 getFrameStateIndex() const { return mFrameStateIndex; }
FrameState& getFrameState() const; FrameState& getFrameState() const;
...@@ -122,9 +185,6 @@ class LLFastTimer ...@@ -122,9 +185,6 @@ class LLFastTimer
static void resetFrame(); static void resetFrame();
static void reset(); static void reset();
typedef std::vector<FrameState> info_list_t;
static info_list_t& getFrameStateList();
static void createFrameStateList(); // must call before any call to getFrameStateList()
// //
// members // members
...@@ -133,13 +193,13 @@ class LLFastTimer ...@@ -133,13 +193,13 @@ class LLFastTimer
std::string mName; std::string mName;
U64 mTotalTimeCounter; U32 mTotalTimeCounter;
U64 mCountAverage; U32 mCountAverage;
U64 mCallAverage; U32 mCallAverage;
U64* mCountHistory; U32* mCountHistory;
U64* mCallHistory; U32* mCallHistory;
// tree structure // tree structure
NamedTimer* mParent; // NamedTimer of caller(parent) NamedTimer* mParent; // NamedTimer of caller(parent)
...@@ -147,41 +207,46 @@ class LLFastTimer ...@@ -147,41 +207,46 @@ class LLFastTimer
bool mCollapsed; // don't show children bool mCollapsed; // don't show children
bool mNeedsSorting; // sort children whenever child added bool mNeedsSorting; // sort children whenever child added
static info_list_t* sTimerInfos;
}; };
// used to statically declare a new named timer // used to statically declare a new named timer
class DeclareTimer class DeclareTimer
: public LLInstanceTracker<DeclareTimer>
{ {
public: public:
DeclareTimer(const std::string& name, bool open); DeclareTimer(const std::string& name, bool open);
DeclareTimer(const std::string& name); DeclareTimer(const std::string& name);
static void updateCachedPointers();
// convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer) // convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer)
operator NamedTimer::FrameState&() { return mNamedTimer.getFrameStateFast(); } operator NamedTimer::FrameState&() { return *mFrameState; }
private: private:
NamedTimer& mNamedTimer; NamedTimer& mTimer;
NamedTimer::FrameState* mFrameState;
}; };
public: public:
enum RootTimerMarker { ROOT };
static LLMutex* sLogLock; static LLMutex* sLogLock;
static std::queue<LLSD> sLogQueue; static std::queue<LLSD> sLogQueue;
static BOOL sLog; static BOOL sLog;
static BOOL sMetricLog; static BOOL sMetricLog;
typedef std::vector<NamedTimer::FrameState> info_list_t;
static info_list_t& getFrameStateList();
enum RootTimerMarker { ROOT };
LLFastTimer(RootTimerMarker); LLFastTimer(RootTimerMarker);
LLFastTimer(NamedTimer::FrameState& timer) LLFastTimer(NamedTimer::FrameState& timer)
: mFrameState(&timer) : mFrameState(&timer)
{ {
#if FAST_TIMER_ON #if FAST_TIMER_ON
NamedTimer::FrameState* frame_state = mFrameState; NamedTimer::FrameState* frame_state = &timer;
U64 cur_time = get_cpu_clock_count(); U32 cur_time = get_cpu_clock_count_32();
frame_state->mLastStartTime = cur_time;
mStartSelfTime = cur_time; mStartSelfTime = cur_time;
mStartTotalTime = cur_time;
frame_state->mActiveCount++; frame_state->mActiveCount++;
frame_state->mCalls++; frame_state->mCalls++;
...@@ -197,7 +262,7 @@ class LLFastTimer ...@@ -197,7 +262,7 @@ class LLFastTimer
{ {
#if FAST_TIMER_ON #if FAST_TIMER_ON
NamedTimer::FrameState* frame_state = mFrameState; NamedTimer::FrameState* frame_state = mFrameState;
U64 cur_time = get_cpu_clock_count(); U32 cur_time = get_cpu_clock_count_32();
frame_state->mSelfTimeCounter += cur_time - mStartSelfTime; frame_state->mSelfTimeCounter += cur_time - mStartSelfTime;
frame_state->mActiveCount--; frame_state->mActiveCount--;
...@@ -208,7 +273,7 @@ class LLFastTimer ...@@ -208,7 +273,7 @@ class LLFastTimer
frame_state->mLastCaller = last_timer->mFrameState; frame_state->mLastCaller = last_timer->mFrameState;
// we are only tracking self time, so subtract our total time delta from parents // we are only tracking self time, so subtract our total time delta from parents
U64 total_time = cur_time - frame_state->mLastStartTime; U32 total_time = cur_time - mStartTotalTime;
last_timer->mStartSelfTime += total_time; last_timer->mStartSelfTime += total_time;
#endif #endif
} }
...@@ -240,9 +305,11 @@ class LLFastTimer ...@@ -240,9 +305,11 @@ class LLFastTimer
static LLFastTimer* sCurTimer; static LLFastTimer* sCurTimer;
static S32 sCurFrameIndex; static S32 sCurFrameIndex;
static S32 sLastFrameIndex; static S32 sLastFrameIndex;
static U64 sLastFrameTime;
static info_list_t* sTimerInfos;
static F64 sCPUClockFrequency; U32 mStartSelfTime; // start time + time of all child timers
U64 mStartSelfTime; // start time + time of all child timers U32 mStartTotalTime; // start time + time of all child timers
NamedTimer::FrameState* mFrameState; NamedTimer::FrameState* mFrameState;
LLFastTimer* mLastTimer; LLFastTimer* mLastTimer;
}; };
......
...@@ -71,17 +71,13 @@ class LLInstanceTracker : boost::noncopyable ...@@ -71,17 +71,13 @@ class LLInstanceTracker : boost::noncopyable
static std::map<KEY, T*>& getMap() static std::map<KEY, T*>& getMap()
{ {
if (! sInstances) static std::map<KEY, T*>* sInstances = new std::map<KEY, T*>();
{
sInstances = new std::map<KEY, T*>;
}
return *sInstances; return *sInstances;
} }
private: private:
KEY mKey; KEY mKey;
static std::map<KEY, T*>* sInstances;
}; };
// explicit specialization for default case where KEY is T* // explicit specialization for default case where KEY is T*
...@@ -105,17 +101,10 @@ class LLInstanceTracker<T, T*> ...@@ -105,17 +101,10 @@ class LLInstanceTracker<T, T*>
static std::set<T*>& getSet() // called after getReady() but before go() static std::set<T*>& getSet() // called after getReady() but before go()
{ {
if (! sInstances) static std::set<T*>* sInstances = new std::set<T*>();
{
sInstances = new std::set<T*>;
}
return *sInstances; return *sInstances;
} }
static std::set<T*>* sInstances;
}; };
template <typename T, typename KEY> std::map<KEY, T*>* LLInstanceTracker<T, KEY>::sInstances = NULL;
template <typename T> std::set<T*>* LLInstanceTracker<T, T*>::sInstances = NULL;
#endif #endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment