summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/CMakeLists.txt1
-rw-r--r--indra/llcommon/llfasttimer.cpp12
-rw-r--r--indra/llcommon/llfasttimer.h9
-rw-r--r--indra/llcommon/lltrace.h169
4 files changed, 182 insertions, 9 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 87fffec0c3..05477c5fa6 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -238,6 +238,7 @@ set(llcommon_HEADER_FILES
llthread.h
llthreadsafequeue.h
lltimer.h
+ lltrace.h
lltreeiterators.h
lltypeinfolookup.h
lluri.h
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 6970c29092..939e332c3b 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -216,7 +216,7 @@ LLFastTimer::NamedTimer::NamedTimer(const std::string& name)
: mName(name),
mCollapsed(true),
mParent(NULL),
- mTotalTimeCounter(0),
+ mTreeTimeCounter(0),
mCountAverage(0),
mCallAverage(0),
mNeedsSorting(false),
@@ -389,6 +389,8 @@ void LLFastTimer::NamedTimer::accumulateTimings()
U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
cur_data->mChildTime = 0;
cur_timer->mFrameState->mSelfTimeCounter += self_time_delta;
+ cur_timer->mFrameState->mTotalTimeCounter += cumulative_time_delta;
+
cur_timer->mStartTime = cur_time;
cur_data = &cur_timer->mLastTimerData;
@@ -403,10 +405,10 @@ void LLFastTimer::NamedTimer::accumulateTimings()
++it)
{
NamedTimer* timerp = (*it);
- timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter;
+ timerp->mTreeTimeCounter = timerp->getFrameState().mSelfTimeCounter;
for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
{
- timerp->mTotalTimeCounter += (*child_it)->mTotalTimeCounter;
+ timerp->mTreeTimeCounter += (*child_it)->mTreeTimeCounter;
}
S32 cur_frame = sCurFrameIndex;
@@ -415,8 +417,8 @@ void LLFastTimer::NamedTimer::accumulateTimings()
// update timer history
int hidx = cur_frame % HISTORY_NUM;
- timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter;
- timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTotalTimeCounter) / (cur_frame+1);
+ timerp->mCountHistory[hidx] = timerp->mTreeTimeCounter;
+ timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTreeTimeCounter) / (cur_frame+1);
timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls;
timerp->mCallAverage = ((U64)timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1);
}
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index e42e549df5..061a37ae31 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -45,18 +45,17 @@ LL_COMMON_API void assert_main_thread();
class LL_COMMON_API LLFastTimer
{
public:
- class NamedTimer;
-
struct LL_COMMON_API FrameState
{
FrameState();
void setNamedTimer(NamedTimer* timerp) { mTimer = timerp; }
U32 mSelfTimeCounter;
+ U32 mTotalTimeCounter;
U32 mCalls;
FrameState* mParent; // info for caller timer
FrameState* mLastCaller; // used to bootstrap tree construction
- NamedTimer* mTimer;
+ class NamedTimer* mTimer;
U16 mActiveCount; // number of timers with this ID active on stack
bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
};
@@ -120,7 +119,8 @@ public:
std::string mName;
- U32 mTotalTimeCounter;
+ // sum of recorded self time and tree time of all children timers (might not match actual recorded time of children if topology is incomplete
+ U32 mTreeTimeCounter;
U32 mCountAverage;
U32 mCallAverage;
@@ -186,6 +186,7 @@ public:
U32 total_time = getCPUClockCount32() - mStartTime;
frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime;
+ frame_state->mTotalTimeCounter += total_time;
frame_state->mActiveCount--;
// store last caller to bootstrap tree creation
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
new file mode 100644
index 0000000000..3d3ee18100
--- /dev/null
+++ b/indra/llcommon/lltrace.h
@@ -0,0 +1,169 @@
+/**
+ * @file lltrace.h
+ * @brief Runtime statistics accumulation.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACE_H
+#define LL_LLTRACE_H
+
+namespace LLTrace
+{
+ class Stat
+ {
+ public:
+ Stat(const char* name)
+ : mName(name)
+ {}
+ void record() {}
+ void record(int value) {}
+ void record(float value) {}
+ private:
+ const std::string mName;
+ };
+
+ class BlockTimer
+ {
+ public:
+ BlockTimer(const char* name)
+ : mName(name)
+ {}
+
+ struct Accumulator
+ {
+ U32 mSelfTimeCounter;
+ U32 mTotalTimeCounter;
+ U32 mCalls;
+ Accumulator* mParent; // info for caller timer
+ Accumulator* mLastCaller; // used to bootstrap tree construction
+ const BlockTimer* mTimer; // points to block timer associated with this storage
+ U16 mActiveCount; // number of timers with this ID active on stack
+ bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
+ std::vector<Accumulator*> mChildren; // currently assumed child timers
+ };
+
+ struct RecorderHead
+ {
+ struct Recorder* mRecorder;
+ Accumulator* mAccumulator;
+ U32 mChildTime;
+ };
+
+ struct Recorder
+ {
+ LL_FORCE_INLINE Recorder(BlockTimer& block_timer)
+ : mLastHead(sRecorderHead)
+ {
+ mStartTime = getCPUClockCount32();
+ Accumulator* accumulator = ???; // get per-thread accumulator
+ accumulator->mActiveCount++;
+ accumulator->mCalls++;
+ accumulator->mMoveUpTree |= (accumulator->mParent->mActiveCount == 0);
+
+ // push new timer on stack
+ sRecorderHead->mRecorder = this;
+ sRecorderHead->mAccumulator = accumulator;
+ sRecorderHead->mChildTime = 0;
+ }
+
+ LL_FORCE_INLINE ~Recorder()
+ {
+ U32 total_time = getCPUClockCount32() - mStartTime;
+
+ Accumulator* accumulator = sRecorderHead->mAccumulator;
+ accumulator->mSelfTimeCounter += total_time- sRecorderHead.mChildTime;
+ accumulator->mTotalTimeCounter += total_time;
+ accumulator->mActiveCount--;
+
+ accumulator->mLastCaller = mLastHead->mAccumulator;
+ mLastHead->mChildTime += total_time;
+
+ // pop stack
+ sRecorderHead = mLastHead;
+ }
+
+ AccumulatorHead mLastHead;
+ U32 mStartTime;
+ };
+
+ private:
+ U32 getCPUClockCount32()
+ {
+ 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, *not* shifted by 8 bits
+ static U64 getCPUClockCount64()
+ {
+ 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;
+ }
+
+ const std::string mName;
+ static RecorderHead* sRecorderHead;
+ };
+
+ BlockTimer::RecorderHead BlockTimer::sRecorderHead;
+
+ class TimeInterval
+ {
+ public:
+ void start() {}
+ void stop() {}
+ void resume() {}
+ };
+
+ class SamplingTimeInterval
+ {
+ public:
+ void start() {}
+ void stop() {}
+ void resume() {}
+ };
+
+}
+
+#define TOKEN_PASTE_ACTUAL(x, y) x##y
+#define TOKEN_PASTE(x, y) TOKEN_PASTE_ACTUAL(x, y)
+#define RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
+
+#endif // LL_LLTRACE_H