summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rwxr-xr-xindra/llcharacter/llkeyframewalkmotion.cpp2
-rwxr-xr-xindra/llcommon/CMakeLists.txt2
-rwxr-xr-xindra/llcommon/llcommon.cpp14
-rwxr-xr-xindra/llcommon/llfasttimer.cpp15
-rwxr-xr-xindra/llcommon/llfasttimer.h30
-rwxr-xr-xindra/llcommon/llpointer.h18
-rwxr-xr-xindra/llcommon/llqueuedthread.cpp4
-rwxr-xr-xindra/llcommon/llthread.cpp4
-rw-r--r--indra/llcommon/llthreadlocalstorage.cpp2
-rw-r--r--indra/llcommon/llthreadlocalstorage.h172
-rw-r--r--indra/llcommon/lltrace.cpp50
-rw-r--r--indra/llcommon/lltrace.h626
-rw-r--r--indra/llcommon/lltraceaccumulators.cpp123
-rw-r--r--indra/llcommon/lltraceaccumulators.h656
-rw-r--r--indra/llcommon/lltracerecording.cpp118
-rw-r--r--indra/llcommon/lltracerecording.h45
-rw-r--r--indra/llcommon/lltracethreadrecorder.cpp196
-rw-r--r--indra/llcommon/lltracethreadrecorder.h94
-rw-r--r--indra/llcommon/llunit.h68
-rwxr-xr-xindra/llimage/llimage.cpp12
-rwxr-xr-xindra/llimage/tests/llimageworker_test.cpp5
-rwxr-xr-xindra/llui/llstatbar.cpp12
-rwxr-xr-xindra/newview/llappviewer.cpp4
-rwxr-xr-xindra/newview/llclassifiedstatsresponder.cpp17
-rwxr-xr-xindra/newview/llfasttimerview.cpp20
-rw-r--r--indra/newview/llscenemonitor.cpp28
-rwxr-xr-xindra/newview/llstartup.cpp54
-rwxr-xr-xindra/newview/lltexturefetch.cpp132
-rwxr-xr-xindra/newview/lltextureinfo.cpp80
-rwxr-xr-xindra/newview/lltextureinfo.h32
-rwxr-xr-xindra/newview/lltextureinfodetails.cpp4
-rwxr-xr-xindra/newview/lltextureinfodetails.h14
-rwxr-xr-xindra/newview/lltexturestats.cpp3
-rwxr-xr-xindra/newview/lltexturestatsuploader.cpp8
-rwxr-xr-xindra/newview/lltexturestatsuploader.h4
-rwxr-xr-xindra/newview/llviewerassetstats.cpp15
-rwxr-xr-xindra/newview/llviewercamera.cpp2
-rwxr-xr-xindra/newview/llviewerdisplay.cpp15
-rwxr-xr-xindra/newview/llviewerstats.cpp10
-rwxr-xr-xindra/newview/llvocache.h1
-rwxr-xr-xindra/newview/tests/llviewerassetstats_test.cpp6
-rwxr-xr-xindra/test/test.cpp9
42 files changed, 1313 insertions, 1413 deletions
diff --git a/indra/llcharacter/llkeyframewalkmotion.cpp b/indra/llcharacter/llkeyframewalkmotion.cpp
index c6ca0b542e..b627110da6 100755
--- a/indra/llcharacter/llkeyframewalkmotion.cpp
+++ b/indra/llcharacter/llkeyframewalkmotion.cpp
@@ -383,7 +383,7 @@ BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask)
F32 target_roll = llclamp(ang_vel.mV[VZ], -4.f, 4.f) * roll_factor;
// roll is critically damped interpolation between current roll and angular velocity-derived target roll
- mRoll = LLSmoothInterpolation::lerp(mRoll, target_roll, LLUnit<F32, LLUnits::Milliseconds>(100));
+ mRoll = LLSmoothInterpolation::lerp(mRoll, target_roll, LLUnits::Milliseconds::fromValue(100));
LLQuaternion roll(mRoll, LLVector3(0.f, 0.f, 1.f));
mPelvisState->setRotation(roll);
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index bf99a4c3a0..0c76fd46c0 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -103,6 +103,7 @@ set(llcommon_SOURCE_FILES
llthreadsafequeue.cpp
lltimer.cpp
lltrace.cpp
+ lltraceaccumulators.cpp
lltracerecording.cpp
lltracethreadrecorder.cpp
lluri.cpp
@@ -231,6 +232,7 @@ set(llcommon_HEADER_FILES
llthreadsafequeue.h
lltimer.h
lltrace.h
+ lltraceaccumulators.h
lltracerecording.h
lltracethreadrecorder.h
lltreeiterators.h
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index c720df7555..96ec0cdefe 100755
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -30,10 +30,13 @@
#include "llmemory.h"
#include "llthread.h"
#include "lltrace.h"
+#include "lltracethreadrecorder.h"
//static
BOOL LLCommon::sAprInitialized = FALSE;
+static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
+
//static
void LLCommon::initClass()
{
@@ -45,13 +48,20 @@ void LLCommon::initClass()
}
LLTimer::initClass();
LLThreadSafeRefCount::initThreadSafeRefCount();
- LLTrace::init();
+
+ if (!sMasterThreadRecorder)
+ {
+ sMasterThreadRecorder = new LLTrace::ThreadRecorder();
+ LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
+ }
}
//static
void LLCommon::cleanupClass()
{
- LLTrace::cleanup();
+ delete sMasterThreadRecorder;
+ sMasterThreadRecorder = NULL;
+ LLTrace::set_master_thread_recorder(NULL);
LLThreadSafeRefCount::cleanupThreadSafeRefCount();
LLTimer::cleanupClass();
if (sAprInitialized)
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 60c451b137..a72f16d385 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -247,17 +247,18 @@ void TimeBlock::incrementalUpdateTimerTree()
void TimeBlock::updateTimes()
- {
- U64 cur_time = getCPUClockCount64();
-
+{
// walk up stack of active timers and accumulate current time while leaving timing structures active
- BlockTimerStackRecord* stack_record = ThreadTimerStack::getInstance();
+ BlockTimerStackRecord* stack_record = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ if (!stack_record) return;
+
+ U64 cur_time = getCPUClockCount64();
BlockTimer* cur_timer = stack_record->mActiveTimer;
TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
while(cur_timer
&& cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
- {
+ {
U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
accumulator->mTotalTimeCounter += cumulative_time_delta
- (accumulator->mTotalTimeCounter
@@ -386,7 +387,7 @@ void TimeBlock::dumpCurTimes()
U32 num_calls = last_frame_recording.getSum(timerp->callCount());
// Don't bother with really brief times, keep output concise
- if (total_time < LLUnit<F32, LLUnits::Milliseconds>(0.1)) continue;
+ if (total_time < LLUnits::Milliseconds::fromValue(0.1f)) continue;
std::ostringstream out_str;
TimeBlock* parent_timerp = timerp;
@@ -397,7 +398,7 @@ void TimeBlock::dumpCurTimes()
}
out_str << timerp->getName() << " "
- << std::setprecision(3) << total_time.getAs<LLUnits::Milliseconds>() << " ms, "
+ << std::setprecision(3) << total_time.valueAs<LLUnits::Milliseconds>() << " ms, "
<< num_calls << " calls";
llinfos << out_str.str() << llendl;
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 642c99ccce..73c40749ed 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -38,29 +38,6 @@ class LLMutex;
namespace LLTrace
{
-struct BlockTimerStackRecord
-{
- class BlockTimer* mActiveTimer;
- class TimeBlock* mTimeBlock;
- U64 mChildTime;
-};
-
-class ThreadTimerStack
-: public BlockTimerStackRecord,
- public LLThreadLocalSingleton<ThreadTimerStack>
-{
- friend class LLThreadLocalSingleton<ThreadTimerStack>;
- ThreadTimerStack()
- {}
-
-public:
- ThreadTimerStack& operator=(const BlockTimerStackRecord& other)
- {
- BlockTimerStackRecord::operator=(other);
- return *this;
- }
-};
-
class BlockTimer
{
public:
@@ -278,7 +255,8 @@ public:
LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
{
#if FAST_TIMER_ON
- BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
+ BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ if (!cur_timer_data) return;
TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
accumulator->mActiveCount++;
mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
@@ -300,7 +278,9 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
{
#if FAST_TIMER_ON
U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
- BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
+ BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ if (!cur_timer_data) return;
+
TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
accumulator->mCalls++;
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 6a0a8fcb0d..c827996db1 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -173,15 +173,23 @@ public:
typedef LLPointer<Type> pointer_t;
LLCopyOnWritePointer()
+ : mStayUnique(false)
{}
LLCopyOnWritePointer(Type* ptr)
- : LLPointer<Type>(ptr)
+ : LLPointer<Type>(ptr),
+ mStayUnique(false)
{}
LLCopyOnWritePointer(LLPointer<Type>& ptr)
- : LLPointer<Type>(ptr)
- {}
+ : LLPointer<Type>(ptr),
+ mStayUnique(false)
+ {
+ if (ptr.mForceUnique)
+ {
+ makeUnique();
+ }
+ }
Type* write()
{
@@ -199,6 +207,10 @@ public:
const Type* operator->() const { return pointer_t::mPointer; }
const Type& operator*() const { return *pointer_t::mPointer; }
+
+ void setStayUnique(bool stay) { makeUnique(); mStayUnique = stay; }
+private:
+ bool mStayUnique;
};
#endif
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 4339f203db..3689c4728e 100755
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -470,7 +470,7 @@ S32 LLQueuedThread::processNextRequest()
}
}
- LLTrace::get_thread_recorder()->pushToMaster();
+ LLTrace::get_thread_recorder()->pushToParent();
}
S32 pending = getPending();
@@ -502,7 +502,7 @@ void LLQueuedThread::run()
if (isQuitting())
{
- LLTrace::get_thread_recorder()->pushToMaster();
+ LLTrace::get_thread_recorder()->pushToParent();
endThread();
break;
}
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 118568d5ef..166a4eb26d 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -93,7 +93,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
{
LLThread *threadp = (LLThread *)datap;
- LLTrace::ThreadRecorder* thread_recorder = new LLTrace::SlaveThreadRecorder(LLTrace::getUIThreadRecorder());
+ LLTrace::ThreadRecorder thread_recorder(*LLTrace::get_master_thread_recorder());
#if !LL_DARWIN
sThreadID = threadp->mID;
@@ -107,8 +107,6 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
// We're done with the run function, this thread is done executing now.
threadp->mStatus = STOPPED;
- delete thread_recorder;
-
return NULL;
}
diff --git a/indra/llcommon/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp
index 32d94331a6..03c306cc7f 100644
--- a/indra/llcommon/llthreadlocalstorage.cpp
+++ b/indra/llcommon/llthreadlocalstorage.cpp
@@ -88,6 +88,7 @@ void LLThreadLocalPointerBase::destroyStorage()
}
}
+//static
void LLThreadLocalPointerBase::initAllThreadLocalStorage()
{
if (!sInitialized)
@@ -102,6 +103,7 @@ void LLThreadLocalPointerBase::initAllThreadLocalStorage()
}
}
+//static
void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
{
if (sInitialized)
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index a15f9185b1..3b2f5f4193 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -125,178 +125,6 @@ public:
};
template<typename DERIVED_TYPE>
-class LLThreadLocalSingleton
-{
- typedef enum e_init_state
- {
- UNINITIALIZED = 0,
- CONSTRUCTING,
- INITIALIZING,
- INITIALIZED,
- DELETED
- } EInitState;
-
-public:
- LLThreadLocalSingleton()
- {}
-
- virtual ~LLThreadLocalSingleton()
- {
-#if LL_DARWIN
- pthread_setspecific(sInstanceKey, NULL);
-#else
- sInstance = NULL;
-#endif
- setInitState(DELETED);
- }
-
- static void deleteSingleton()
- {
- delete getIfExists();
- }
-
- static DERIVED_TYPE* getInstance()
- {
- EInitState init_state = getInitState();
- if (init_state == CONSTRUCTING)
- {
- llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
- }
-
- if (init_state == DELETED)
- {
- llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
- }
-
-#if LL_DARWIN
- createTLSInstance();
-#endif
- if (!getIfExists())
- {
- setInitState(CONSTRUCTING);
- DERIVED_TYPE* instancep = new DERIVED_TYPE();
-#if LL_DARWIN
- S32 result = pthread_setspecific(sInstanceKey, (void*)instancep);
- if (result != 0)
- {
- llerrs << "Could not set thread local storage" << llendl;
- }
-#else
- sInstance = instancep;
-#endif
- setInitState(INITIALIZING);
- instancep->initSingleton();
- setInitState(INITIALIZED);
- }
-
- return getIfExists();
- }
-
- static DERIVED_TYPE* getIfExists()
- {
-#if LL_DARWIN
- return (DERIVED_TYPE*)pthread_getspecific(sInstanceKey);
-#else
- return sInstance;
-#endif
- }
-
- // Reference version of getInstance()
- // Preferred over getInstance() as it disallows checking for NULL
- static DERIVED_TYPE& instance()
- {
- return *getInstance();
- }
-
- // Has this singleton been created uet?
- // Use this to avoid accessing singletons before the can safely be constructed
- static bool instanceExists()
- {
- return getInitState() == INITIALIZED;
- }
-
- // Has this singleton already been deleted?
- // Use this to avoid accessing singletons from a static object's destructor
- static bool destroyed()
- {
- return getInitState() == DELETED;
- }
-private:
-#if LL_DARWIN
- static void createTLSInitState()
- {
- static S32 key_created = pthread_key_create(&sInitStateKey, NULL);
- if (key_created != 0)
- {
- llerrs << "Could not create thread local storage" << llendl;
- }
- }
-
- static void createTLSInstance()
- {
- static S32 key_created = pthread_key_create(&sInstanceKey, NULL);
- if (key_created != 0)
- {
- llerrs << "Could not create thread local storage" << llendl;
- }
- }
-#endif
- static EInitState getInitState()
- {
-#if LL_DARWIN
- createTLSInitState();
- return (EInitState)(int)pthread_getspecific(sInitStateKey);
-#else
- return sInitState;
-#endif
- }
-
- static void setInitState(EInitState state)
- {
-#if LL_DARWIN
- createTLSInitState();
- pthread_setspecific(sInitStateKey, (void*)state);
-#else
- sInitState = state;
-#endif
- }
- LLThreadLocalSingleton(const LLThreadLocalSingleton& other);
- virtual void initSingleton() {}
-
-#ifdef LL_WINDOWS
- static __declspec(thread) DERIVED_TYPE* sInstance;
- static __declspec(thread) EInitState sInitState;
-#elif LL_LINUX
- static __thread DERIVED_TYPE* sInstance;
- static __thread EInitState sInitState;
-#elif LL_DARWIN
- static pthread_key_t sInstanceKey;
- static pthread_key_t sInitStateKey;
-#endif
-};
-
-#if LL_WINDOWS
-template<typename DERIVED_TYPE>
-__declspec(thread) DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
-
-template<typename DERIVED_TYPE>
-__declspec(thread) typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED;
-#elif LL_LINUX
-template<typename DERIVED_TYPE>
-__thread DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
-
-template<typename DERIVED_TYPE>
-__thread typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED;
-#elif LL_DARWIN
-template<typename DERIVED_TYPE>
-pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInstanceKey;
-
-template<typename DERIVED_TYPE>
-pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInitStateKey;
-
-#endif
-
-template<typename DERIVED_TYPE>
class LLThreadLocalSingletonPointer
{
public:
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 59a4b42c97..3dffbe6d4a 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -30,58 +30,26 @@
#include "lltracethreadrecorder.h"
#include "llfasttimer.h"
-static S32 sInitializationCount = 0;
-
namespace LLTrace
{
-static MasterThreadRecorder* gUIThreadRecorder = NULL;
-
-void init()
-{
- if (sInitializationCount++ == 0)
- {
- gUIThreadRecorder = new MasterThreadRecorder();
- }
-}
-
-bool isInitialized()
-{
- return sInitializationCount > 0;
-}
-
-void cleanup()
+TraceBase::TraceBase( const char* name, const char* description )
+: mName(name),
+ mDescription(description ? description : "")
{
- if (--sInitializationCount == 0)
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ if (LLTrace::get_master_thread_recorder() != NULL)
{
- delete gUIThreadRecorder;
- gUIThreadRecorder = NULL;
+ llerrs << "Attempting to declare trace object after program initialization. Trace objects should be statically initialized." << llendl;
}
+#endif
}
-MasterThreadRecorder& getUIThreadRecorder()
+const char* TraceBase::getUnitLabel()
{
- llassert(gUIThreadRecorder != NULL);
- return *gUIThreadRecorder;
+ return "";
}
-LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
-{
- static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
- return s_thread_recorder;
-}
-
-const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
-{
- return get_thread_recorder_ptr();
-}
-
-void set_thread_recorder(ThreadRecorder* recorder)
-{
- get_thread_recorder_ptr() = recorder;
-}
-
-
TimeBlockTreeNode::TimeBlockTreeNode()
: mBlock(NULL),
mParent(NULL),
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 884a316a3b..2c45923aac 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -32,7 +32,7 @@
#include "llmemory.h"
#include "llrefcount.h"
-#include "llunit.h"
+#include "lltraceaccumulators.h"
#include "llthreadlocalstorage.h"
#include "lltimer.h"
@@ -53,198 +53,29 @@ STORAGE_TYPE storage_value(LLUnit<STORAGE_TYPE, UNIT_TYPE> val) { return val.val
template<typename UNIT_TYPE, typename STORAGE_TYPE>
STORAGE_TYPE storage_value(LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
-void init();
-void cleanup();
-bool isInitialized();
-
-const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
-void set_thread_recorder(class ThreadRecorder*);
-
-class MasterThreadRecorder& getUIThreadRecorder();
-
-template<typename ACCUMULATOR>
-class AccumulatorBuffer : public LLRefCount
+class TraceBase
{
- typedef AccumulatorBuffer<ACCUMULATOR> self_t;
- static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
-private:
- struct StaticAllocationMarker { };
-
- AccumulatorBuffer(StaticAllocationMarker m)
- : mStorageSize(0),
- mStorage(NULL)
- {}
-
public:
+ TraceBase(const char* name, const char* description);
+ virtual ~TraceBase() {};
+ virtual const char* getUnitLabel();
- AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer())
- : mStorageSize(0),
- mStorage(NULL)
- {
- resize(other.mStorageSize);
- for (S32 i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i] = other.mStorage[i];
- }
- }
-
- ~AccumulatorBuffer()
- {
- if (isPrimary())
- {
- LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
- }
- delete[] mStorage;
- }
-
- LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index)
- {
- return mStorage[index];
- }
-
- LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
- {
- return mStorage[index];
- }
-
- void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, bool append = true)
- {
- llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
- for (size_t i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i].addSamples(other.mStorage[i], append);
- }
- }
-
- void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
- {
- llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
- for (size_t i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i] = other.mStorage[i];
- }
- }
-
- void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
- {
- llassert(mStorageSize >= sNextStorageSlot);
- for (size_t i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i].reset(other ? &other->mStorage[i] : NULL);
- }
- }
-
- void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
- {
- llassert(mStorageSize >= sNextStorageSlot);
- for (size_t i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i].flush(time_stamp);
- }
- }
-
- void makePrimary()
- {
- LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
- }
-
- bool isPrimary() const
- {
- return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
- }
-
- LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage()
- {
- ACCUMULATOR* accumulator = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
- return accumulator ? accumulator : getDefaultBuffer()->mStorage;
- }
-
- // NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned
- size_t reserveSlot()
- {
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- if (LLTrace::isInitialized())
- {
- llerrs << "Attempting to declare trace object after program initialization. Trace objects should be statically initialized." << llendl;
- }
-#endif
- size_t next_slot = sNextStorageSlot++;
- if (next_slot >= mStorageSize)
- {
- resize(mStorageSize + (mStorageSize >> 2));
- }
- llassert(mStorage && next_slot < mStorageSize);
- return next_slot;
- }
-
- void resize(size_t new_size)
- {
- if (new_size <= mStorageSize) return;
-
- ACCUMULATOR* old_storage = mStorage;
- mStorage = new ACCUMULATOR[new_size];
- if (old_storage)
- {
- for (S32 i = 0; i < mStorageSize; i++)
- {
- mStorage[i] = old_storage[i];
- }
- }
- mStorageSize = new_size;
- delete[] old_storage;
-
- self_t* default_buffer = getDefaultBuffer();
- if (this != default_buffer
- && new_size > default_buffer->size())
- {
- //NB: this is not thread safe, but we assume that all resizing occurs during static initialization
- default_buffer->resize(new_size);
- }
- }
-
- size_t size() const
- {
- return getNumIndices();
- }
-
- static size_t getNumIndices()
- {
- return sNextStorageSlot;
- }
-
- static self_t* getDefaultBuffer()
- {
- static bool sInitialized = false;
- if (!sInitialized)
- {
- // this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
- // so as not to trigger an access violation
- sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker());
- sInitialized = true;
- sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
- }
- return sDefaultBuffer;
- }
+ const std::string& getName() const { return mName; }
-private:
- ACCUMULATOR* mStorage;
- size_t mStorageSize;
- static size_t sNextStorageSlot;
- static self_t* sDefaultBuffer;
+protected:
+ const std::string mName;
+ const std::string mDescription;
};
-template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
-template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL;
-
template<typename ACCUMULATOR>
class TraceType
-: public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
+: public TraceBase,
+ public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
{
public:
TraceType(const char* name, const char* description = NULL)
: LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name),
- mName(name),
- mDescription(description ? description : ""),
+ TraceBase(name, description),
mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
{}
@@ -257,354 +88,10 @@ public:
size_t getIndex() const { return mAccumulatorIndex; }
static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); }
- virtual const char* getUnitLabel() { return ""; }
-
- const std::string& getName() const { return mName; }
-
-protected:
- const std::string mName;
- const std::string mDescription;
- const size_t mAccumulatorIndex;
-};
-
-class EventAccumulator
-{
-public:
- typedef F64 value_t;
- typedef F64 mean_t;
-
- EventAccumulator()
- : mSum(0),
- mMin((std::numeric_limits<F64>::max)()),
- mMax((std::numeric_limits<F64>::min)()),
- mMean(0),
- mVarianceSum(0),
- mNumSamples(0),
- mLastValue(0)
- {}
-
- void record(F64 value)
- {
- mNumSamples++;
- mSum += value;
- // NOTE: both conditions will hold on first pass through
- if (value < mMin)
- {
- mMin = value;
- }
- if (value > mMax)
- {
- mMax = value;
- }
- F64 old_mean = mMean;
- mMean += (value - old_mean) / (F64)mNumSamples;
- mVarianceSum += (value - old_mean) * (value - mMean);
- mLastValue = value;
- }
-
- void addSamples(const EventAccumulator& other, bool append)
- {
- if (other.mNumSamples)
- {
- mSum += other.mSum;
-
- // NOTE: both conditions will hold first time through
- if (other.mMin < mMin) { mMin = other.mMin; }
- if (other.mMax > mMax) { mMax = other.mMax; }
-
- // combine variance (and hence standard deviation) of 2 different sized sample groups using
- // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
- F64 n_1 = (F64)mNumSamples,
- n_2 = (F64)other.mNumSamples;
- F64 m_1 = mMean,
- m_2 = other.mMean;
- F64 v_1 = mVarianceSum / mNumSamples,
- v_2 = other.mVarianceSum / other.mNumSamples;
- if (n_1 == 0)
- {
- mVarianceSum = other.mVarianceSum;
- }
- else if (n_2 == 0)
- {
- // don't touch variance
- // mVarianceSum = mVarianceSum;
- }
- else
- {
- mVarianceSum = (F64)mNumSamples
- * ((((n_1 - 1.f) * v_1)
- + ((n_2 - 1.f) * v_2)
- + (((n_1 * n_2) / (n_1 + n_2))
- * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
- / (n_1 + n_2 - 1.f));
- }
-
- F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
- mNumSamples += other.mNumSamples;
- mMean = mMean * weight + other.mMean * (1.f - weight);
- if (append) mLastValue = other.mLastValue;
- }
- }
-
- void reset(const EventAccumulator* other)
- {
- mNumSamples = 0;
- mSum = 0;
- mMin = std::numeric_limits<F64>::max();
- mMax = std::numeric_limits<F64>::min();
- mMean = 0;
- mVarianceSum = 0;
- mLastValue = other ? other->mLastValue : 0;
- }
-
- void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
-
- F64 getSum() const { return mSum; }
- F64 getMin() const { return mMin; }
- F64 getMax() const { return mMax; }
- F64 getLastValue() const { return mLastValue; }
- F64 getMean() const { return mMean; }
- F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
- U32 getSampleCount() const { return mNumSamples; }
-
-private:
- F64 mSum,
- mMin,
- mMax,
- mLastValue;
-
- F64 mMean,
- mVarianceSum;
-
- U32 mNumSamples;
-};
-
-
-class SampleAccumulator
-{
-public:
- typedef F64 value_t;
- typedef F64 mean_t;
-
- SampleAccumulator()
- : mSum(0),
- mMin((std::numeric_limits<F64>::max)()),
- mMax((std::numeric_limits<F64>::min)()),
- mMean(0),
- mVarianceSum(0),
- mLastSampleTimeStamp(LLTimer::getTotalSeconds()),
- mTotalSamplingTime(0),
- mNumSamples(0),
- mLastValue(0),
- mHasValue(false)
- {}
-
- void sample(F64 value)
- {
- LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
- LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
- mLastSampleTimeStamp = time_stamp;
-
- if (mHasValue)
- {
- mTotalSamplingTime += delta_time;
- mSum += mLastValue * delta_time;
-
- // NOTE: both conditions will hold first time through
- if (value < mMin) { mMin = value; }
- if (value > mMax) { mMax = value; }
-
- F64 old_mean = mMean;
- mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
- mVarianceSum += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
- }
-
- mLastValue = value;
- mNumSamples++;
- mHasValue = true;
- }
-
- void addSamples(const SampleAccumulator& other, bool append)
- {
- if (other.mTotalSamplingTime)
- {
- mSum += other.mSum;
-
- // NOTE: both conditions will hold first time through
- if (other.mMin < mMin) { mMin = other.mMin; }
- if (other.mMax > mMax) { mMax = other.mMax; }
-
- // combine variance (and hence standard deviation) of 2 different sized sample groups using
- // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
- F64 n_1 = mTotalSamplingTime,
- n_2 = other.mTotalSamplingTime;
- F64 m_1 = mMean,
- m_2 = other.mMean;
- F64 v_1 = mVarianceSum / mTotalSamplingTime,
- v_2 = other.mVarianceSum / other.mTotalSamplingTime;
- if (n_1 == 0)
- {
- mVarianceSum = other.mVarianceSum;
- }
- else if (n_2 == 0)
- {
- // variance is unchanged
- // mVarianceSum = mVarianceSum;
- }
- else
- {
- mVarianceSum = mTotalSamplingTime
- * ((((n_1 - 1.f) * v_1)
- + ((n_2 - 1.f) * v_2)
- + (((n_1 * n_2) / (n_1 + n_2))
- * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
- / (n_1 + n_2 - 1.f));
- }
-
- llassert(other.mTotalSamplingTime > 0);
- F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
- mNumSamples += other.mNumSamples;
- mTotalSamplingTime += other.mTotalSamplingTime;
- mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
- if (append)
- {
- mLastValue = other.mLastValue;
- mLastSampleTimeStamp = other.mLastSampleTimeStamp;
- mHasValue |= other.mHasValue;
- }
- }
- }
-
- void reset(const SampleAccumulator* other)
- {
- mNumSamples = 0;
- mSum = 0;
- mMin = std::numeric_limits<F64>::max();
- mMax = std::numeric_limits<F64>::min();
- mMean = other ? other->mLastValue : 0;
- mVarianceSum = 0;
- mLastSampleTimeStamp = LLTimer::getTotalSeconds();
- mTotalSamplingTime = 0;
- mLastValue = other ? other->mLastValue : 0;
- mHasValue = other ? other->mHasValue : false;
- }
-
- void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
- {
- LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
-
- if (mHasValue)
- {
- mSum += mLastValue * delta_time;
- mTotalSamplingTime += delta_time;
- }
- mLastSampleTimeStamp = time_stamp;
- }
-
- F64 getSum() const { return mSum; }
- F64 getMin() const { return mMin; }
- F64 getMax() const { return mMax; }
- F64 getLastValue() const { return mLastValue; }
- F64 getMean() const { return mMean; }
- F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mTotalSamplingTime); }
- U32 getSampleCount() const { return mNumSamples; }
-
-private:
- F64 mSum,
- mMin,
- mMax,
- mLastValue;
-
- bool mHasValue;
-
- F64 mMean,
- mVarianceSum;
-
- LLUnitImplicit<F64, LLUnits::Seconds> mLastSampleTimeStamp,
- mTotalSamplingTime;
-
- U32 mNumSamples;
-};
-
-class CountAccumulator
-{
-public:
- typedef F64 value_t;
- typedef F64 mean_t;
-
- CountAccumulator()
- : mSum(0),
- mNumSamples(0)
- {}
-
- void add(F64 value)
- {
- mNumSamples++;
- mSum += value;
- }
-
- void addSamples(const CountAccumulator& other, bool /*append*/)
- {
- mSum += other.mSum;
- mNumSamples += other.mNumSamples;
- }
-
- void reset(const CountAccumulator* other)
- {
- mNumSamples = 0;
- mSum = 0;
- }
-
- void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
-
- F64 getSum() const { return mSum; }
-
- U32 getSampleCount() const { return mNumSamples; }
-
private:
- F64 mSum;
-
- U32 mNumSamples;
+ const size_t mAccumulatorIndex;
};
-class TimeBlockAccumulator
-{
-public:
- typedef LLUnit<F64, LLUnits::Seconds> value_t;
- typedef LLUnit<F64, LLUnits::Seconds> mean_t;
- typedef TimeBlockAccumulator self_t;
-
- // fake classes that allows us to view different facets of underlying statistic
- struct CallCountFacet
- {
- typedef U32 value_t;
- typedef F32 mean_t;
- };
-
- struct SelfTimeFacet
- {
- typedef LLUnit<F64, LLUnits::Seconds> value_t;
- typedef LLUnit<F64, LLUnits::Seconds> mean_t;
- };
-
- TimeBlockAccumulator();
- void addSamples(const self_t& other, bool /*append*/);
- void reset(const self_t* other);
- void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
-
- //
- // members
- //
- U64 mStartTotalTimeCounter,
- mTotalTimeCounter,
- mSelfTimeCounter;
- U32 mCalls;
- class TimeBlock* mParent; // last acknowledged parent of this time block
- class TimeBlock* mLastCaller; // used to bootstrap tree construction
- 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
-
-};
template<>
class TraceType<TimeBlockAccumulator::CallCountFacet>
@@ -628,23 +115,6 @@ public:
{}
};
-class TimeBlock;
-class TimeBlockTreeNode
-{
-public:
- TimeBlockTreeNode();
-
- void setParent(TimeBlock* parent);
- TimeBlock* getParent() { return mParent; }
-
- TimeBlock* mBlock;
- TimeBlock* mParent;
- std::vector<TimeBlock*> mChildren;
- bool mCollapsed;
- bool mNeedsSorting;
-};
-
-
template <typename T = F64>
class EventStatHandle
: public TraceType<EventAccumulator>
@@ -712,64 +182,6 @@ void add(CountStatHandle<T>& count, VALUE_T value)
count.getPrimaryAccumulator()->add(storage_value(converted_value));
}
-
-struct MemStatAccumulator
-{
- typedef MemStatAccumulator self_t;
-
- // fake classes that allows us to view different facets of underlying statistic
- struct AllocationCountFacet
- {
- typedef U32 value_t;
- typedef F32 mean_t;
- };
-
- struct DeallocationCountFacet
- {
- typedef U32 value_t;
- typedef F32 mean_t;
- };
-
- struct ChildMemFacet
- {
- typedef LLUnit<F64, LLUnits::Bytes> value_t;
- typedef LLUnit<F64, LLUnits::Bytes> mean_t;
- };
-
- MemStatAccumulator()
- : mAllocatedCount(0),
- mDeallocatedCount(0)
- {}
-
- void addSamples(const MemStatAccumulator& other, bool append)
- {
- mSize.addSamples(other.mSize, append);
- mChildSize.addSamples(other.mChildSize, append);
- mAllocatedCount += other.mAllocatedCount;
- mDeallocatedCount += other.mDeallocatedCount;
- }
-
- void reset(const MemStatAccumulator* other)
- {
- mSize.reset(other ? &other->mSize : NULL);
- mChildSize.reset(other ? &other->mChildSize : NULL);
- mAllocatedCount = 0;
- mDeallocatedCount = 0;
- }
-
- void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
- {
- mSize.flush(time_stamp);
- mChildSize.flush(time_stamp);
- }
-
- SampleAccumulator mSize,
- mChildSize;
- int mAllocatedCount,
- mDeallocatedCount;
-};
-
-
template<>
class TraceType<MemStatAccumulator::AllocationCountFacet>
: public TraceType<MemStatAccumulator>
@@ -912,7 +324,7 @@ class MemTrackable
template<typename TRACKED, typename TRACKED_IS_TRACKER>
struct TrackMemImpl;
- typedef MemTrackable<DERIVED> mem_trackable_t;
+ typedef MemTrackable<DERIVED, ALIGNMENT> mem_trackable_t;
public:
typedef void mem_trackable_tag_t;
@@ -986,14 +398,16 @@ public:
}
- void memClaimAmount(size_t size)
+ template<typename AMOUNT_T>
+ AMOUNT_T& memClaimAmount(AMOUNT_T& size)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
- mMemFootprint += size;
+ mMemFootprint += (size_t)size;
if (accumulator)
{
accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
}
+ return size;
}
// remove memory we had claimed from our calculated footprint
@@ -1011,13 +425,15 @@ public:
return value;
}
- void memDisclaimAmount(size_t size)
+ template<typename AMOUNT_T>
+ AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
if (accumulator)
{
accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
}
+ return size;
}
private:
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
new file mode 100644
index 0000000000..950c1d97d1
--- /dev/null
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -0,0 +1,123 @@
+/**
+ * @file lltracesampler.cpp
+ *
+ * $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$
+ */
+
+#include "linden_common.h"
+
+#include "lltraceaccumulators.h"
+#include "lltracethreadrecorder.h"
+
+namespace LLTrace
+{
+
+
+///////////////////////////////////////////////////////////////////////
+// AccumulatorBufferGroup
+///////////////////////////////////////////////////////////////////////
+
+AccumulatorBufferGroup::AccumulatorBufferGroup()
+{}
+
+void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other)
+{
+ other.mCounts.reset(&mCounts);
+ other.mSamples.reset(&mSamples);
+ other.mEvents.reset(&mEvents);
+ other.mStackTimers.reset(&mStackTimers);
+ other.mMemStats.reset(&mMemStats);
+}
+
+void AccumulatorBufferGroup::makePrimary()
+{
+ mCounts.makePrimary();
+ mSamples.makePrimary();
+ mEvents.makePrimary();
+ mStackTimers.makePrimary();
+ mMemStats.makePrimary();
+
+ ThreadRecorder* thread_recorder = get_thread_recorder().get();
+ AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
+ // update stacktimer parent pointers
+ for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++)
+ {
+ TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(i);
+ if (tree_node)
+ {
+ timer_accumulator_buffer[i].mParent = tree_node->mParent;
+ }
+ }
+}
+
+//static
+void AccumulatorBufferGroup::clearPrimary()
+{
+ AccumulatorBuffer<CountAccumulator>::clearPrimary();
+ AccumulatorBuffer<SampleAccumulator>::clearPrimary();
+ AccumulatorBuffer<EventAccumulator>::clearPrimary();
+ AccumulatorBuffer<TimeBlockAccumulator>::clearPrimary();
+ AccumulatorBuffer<MemStatAccumulator>::clearPrimary();
+}
+
+bool AccumulatorBufferGroup::isPrimary() const
+{
+ return mCounts.isPrimary();
+}
+
+void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other )
+{
+ mCounts.addSamples(other.mCounts);
+ mSamples.addSamples(other.mSamples);
+ mEvents.addSamples(other.mEvents);
+ mMemStats.addSamples(other.mMemStats);
+ mStackTimers.addSamples(other.mStackTimers);
+}
+
+void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other)
+{
+ mCounts.addSamples(other.mCounts, false);
+ mSamples.addSamples(other.mSamples, false);
+ mEvents.addSamples(other.mEvents, false);
+ mMemStats.addSamples(other.mMemStats, false);
+ // for now, hold out timers from merge, need to be displayed per thread
+ //mStackTimers.addSamples(other.mStackTimers, false);
+}
+
+void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
+{
+ mCounts.reset(other ? &other->mCounts : NULL);
+ mSamples.reset(other ? &other->mSamples : NULL);
+ mEvents.reset(other ? &other->mEvents : NULL);
+ mStackTimers.reset(other ? &other->mStackTimers : NULL);
+ mMemStats.reset(other ? &other->mMemStats : NULL);
+}
+
+void AccumulatorBufferGroup::sync()
+{
+ LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
+
+ mSamples.sync(time_stamp);
+ mMemStats.sync(time_stamp);
+}
+
+}
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
new file mode 100644
index 0000000000..fac6347ff9
--- /dev/null
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -0,0 +1,656 @@
+/**
+ * @file lltraceaccumulators.h
+ * @brief Storage for accumulating statistics
+ *
+ * $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_LLTRACEACCUMULATORS_H
+#define LL_LLTRACEACCUMULATORS_H
+
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+#include "llunit.h"
+#include "lltimer.h"
+#include "llrefcount.h"
+#include "llthreadlocalstorage.h"
+
+namespace LLTrace
+{
+
+ template<typename ACCUMULATOR>
+ class AccumulatorBuffer : public LLRefCount
+ {
+ typedef AccumulatorBuffer<ACCUMULATOR> self_t;
+ static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
+ private:
+ struct StaticAllocationMarker { };
+
+ AccumulatorBuffer(StaticAllocationMarker m)
+ : mStorageSize(0),
+ mStorage(NULL)
+ {}
+
+ public:
+
+ AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer())
+ : mStorageSize(0),
+ mStorage(NULL)
+ {
+ resize(other.mStorageSize);
+ for (S32 i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i] = other.mStorage[i];
+ }
+ }
+
+ ~AccumulatorBuffer()
+ {
+ if (isPrimary())
+ {
+ LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
+ }
+ delete[] mStorage;
+ }
+
+ LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index)
+ {
+ return mStorage[index];
+ }
+
+ LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
+ {
+ return mStorage[index];
+ }
+
+ void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, bool append = true)
+ {
+ llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i].addSamples(other.mStorage[i], append);
+ }
+ }
+
+ void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
+ {
+ llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i] = other.mStorage[i];
+ }
+ }
+
+ void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
+ {
+ llassert(mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i].reset(other ? &other->mStorage[i] : NULL);
+ }
+ }
+
+ void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
+ {
+ llassert(mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i].sync(time_stamp);
+ }
+ }
+
+ void makePrimary()
+ {
+ LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
+ }
+
+ bool isPrimary() const
+ {
+ return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
+ }
+
+ static void clearPrimary()
+ {
+ LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
+ }
+
+ LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage()
+ {
+ ACCUMULATOR* accumulator = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
+ return accumulator ? accumulator : getDefaultBuffer()->mStorage;
+ }
+
+ // NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned
+ size_t reserveSlot()
+ {
+ size_t next_slot = sNextStorageSlot++;
+ if (next_slot >= mStorageSize)
+ {
+ resize(mStorageSize + (mStorageSize >> 2));
+ }
+ llassert(mStorage && next_slot < mStorageSize);
+ return next_slot;
+ }
+
+ void resize(size_t new_size)
+ {
+ if (new_size <= mStorageSize) return;
+
+ ACCUMULATOR* old_storage = mStorage;
+ mStorage = new ACCUMULATOR[new_size];
+ if (old_storage)
+ {
+ for (S32 i = 0; i < mStorageSize; i++)
+ {
+ mStorage[i] = old_storage[i];
+ }
+ }
+ mStorageSize = new_size;
+ delete[] old_storage;
+
+ self_t* default_buffer = getDefaultBuffer();
+ if (this != default_buffer
+ && new_size > default_buffer->size())
+ {
+ //NB: this is not thread safe, but we assume that all resizing occurs during static initialization
+ default_buffer->resize(new_size);
+ }
+ }
+
+ size_t size() const
+ {
+ return getNumIndices();
+ }
+
+ static size_t getNumIndices()
+ {
+ return sNextStorageSlot;
+ }
+
+ static self_t* getDefaultBuffer()
+ {
+ static bool sInitialized = false;
+ if (!sInitialized)
+ {
+ // this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
+ // so as not to trigger an access violation
+ sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker());
+ sInitialized = true;
+ sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
+ }
+ return sDefaultBuffer;
+ }
+
+ private:
+ ACCUMULATOR* mStorage;
+ size_t mStorageSize;
+ static size_t sNextStorageSlot;
+ static self_t* sDefaultBuffer;
+ };
+
+ template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
+ template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL;
+
+
+ class EventAccumulator
+ {
+ public:
+ typedef F64 value_t;
+ typedef F64 mean_t;
+
+ EventAccumulator()
+ : mSum(0),
+ mMin((std::numeric_limits<F64>::max)()),
+ mMax((std::numeric_limits<F64>::min)()),
+ mMean(0),
+ mVarianceSum(0),
+ mNumSamples(0),
+ mLastValue(0)
+ {}
+
+ void record(F64 value)
+ {
+ mNumSamples++;
+ mSum += value;
+ // NOTE: both conditions will hold on first pass through
+ if (value < mMin)
+ {
+ mMin = value;
+ }
+ if (value > mMax)
+ {
+ mMax = value;
+ }
+ F64 old_mean = mMean;
+ mMean += (value - old_mean) / (F64)mNumSamples;
+ mVarianceSum += (value - old_mean) * (value - mMean);
+ mLastValue = value;
+ }
+
+ void addSamples(const EventAccumulator& other, bool append)
+ {
+ if (other.mNumSamples)
+ {
+ mSum += other.mSum;
+
+ // NOTE: both conditions will hold first time through
+ if (other.mMin < mMin) { mMin = other.mMin; }
+ if (other.mMax > mMax) { mMax = other.mMax; }
+
+ // combine variance (and hence standard deviation) of 2 different sized sample groups using
+ // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+ F64 n_1 = (F64)mNumSamples,
+ n_2 = (F64)other.mNumSamples;
+ F64 m_1 = mMean,
+ m_2 = other.mMean;
+ F64 v_1 = mVarianceSum / mNumSamples,
+ v_2 = other.mVarianceSum / other.mNumSamples;
+ if (n_1 == 0)
+ {
+ mVarianceSum = other.mVarianceSum;
+ }
+ else if (n_2 == 0)
+ {
+ // don't touch variance
+ // mVarianceSum = mVarianceSum;
+ }
+ else
+ {
+ mVarianceSum = (F64)mNumSamples
+ * ((((n_1 - 1.f) * v_1)
+ + ((n_2 - 1.f) * v_2)
+ + (((n_1 * n_2) / (n_1 + n_2))
+ * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+ / (n_1 + n_2 - 1.f));
+ }
+
+ F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
+ mNumSamples += other.mNumSamples;
+ mMean = mMean * weight + other.mMean * (1.f - weight);
+ if (append) mLastValue = other.mLastValue;
+ }
+ }
+
+ void reset(const EventAccumulator* other)
+ {
+ mNumSamples = 0;
+ mSum = 0;
+ mMin = std::numeric_limits<F64>::max();
+ mMax = std::numeric_limits<F64>::min();
+ mMean = 0;
+ mVarianceSum = 0;
+ mLastValue = other ? other->mLastValue : 0;
+ }
+
+ void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+
+ F64 getSum() const { return mSum; }
+ F64 getMin() const { return mMin; }
+ F64 getMax() const { return mMax; }
+ F64 getLastValue() const { return mLastValue; }
+ F64 getMean() const { return mMean; }
+ F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
+ U32 getSampleCount() const { return mNumSamples; }
+
+ private:
+ F64 mSum,
+ mMin,
+ mMax,
+ mLastValue;
+
+ F64 mMean,
+ mVarianceSum;
+
+ U32 mNumSamples;
+ };
+
+
+ class SampleAccumulator
+ {
+ public:
+ typedef F64 value_t;
+ typedef F64 mean_t;
+
+ SampleAccumulator()
+ : mSum(0),
+ mMin((std::numeric_limits<F64>::max)()),
+ mMax((std::numeric_limits<F64>::min)()),
+ mMean(0),
+ mVarianceSum(0),
+ mLastSampleTimeStamp(LLTimer::getTotalSeconds()),
+ mTotalSamplingTime(0),
+ mNumSamples(0),
+ mLastValue(0),
+ mHasValue(false)
+ {}
+
+ void sample(F64 value)
+ {
+ LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
+ LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
+ mLastSampleTimeStamp = time_stamp;
+
+ if (mHasValue)
+ {
+ mTotalSamplingTime += delta_time;
+ mSum += mLastValue * delta_time;
+
+ // NOTE: both conditions will hold first time through
+ if (value < mMin) { mMin = value; }
+ if (value > mMax) { mMax = value; }
+
+ F64 old_mean = mMean;
+ mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
+ mVarianceSum += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
+ }
+
+ mLastValue = value;
+ mNumSamples++;
+ mHasValue = true;
+ }
+
+ void addSamples(const SampleAccumulator& other, bool append)
+ {
+ if (other.mTotalSamplingTime)
+ {
+ mSum += other.mSum;
+
+ // NOTE: both conditions will hold first time through
+ if (other.mMin < mMin) { mMin = other.mMin; }
+ if (other.mMax > mMax) { mMax = other.mMax; }
+
+ // combine variance (and hence standard deviation) of 2 different sized sample groups using
+ // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+ F64 n_1 = mTotalSamplingTime,
+ n_2 = other.mTotalSamplingTime;
+ F64 m_1 = mMean,
+ m_2 = other.mMean;
+ F64 v_1 = mVarianceSum / mTotalSamplingTime,
+ v_2 = other.mVarianceSum / other.mTotalSamplingTime;
+ if (n_1 == 0)
+ {
+ mVarianceSum = other.mVarianceSum;
+ }
+ else if (n_2 == 0)
+ {
+ // variance is unchanged
+ // mVarianceSum = mVarianceSum;
+ }
+ else
+ {
+ mVarianceSum = mTotalSamplingTime
+ * ((((n_1 - 1.f) * v_1)
+ + ((n_2 - 1.f) * v_2)
+ + (((n_1 * n_2) / (n_1 + n_2))
+ * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+ / (n_1 + n_2 - 1.f));
+ }
+
+ llassert(other.mTotalSamplingTime > 0);
+ F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
+ mNumSamples += other.mNumSamples;
+ mTotalSamplingTime += other.mTotalSamplingTime;
+ mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
+ if (append)
+ {
+ mLastValue = other.mLastValue;
+ mLastSampleTimeStamp = other.mLastSampleTimeStamp;
+ mHasValue |= other.mHasValue;
+ }
+ }
+ }
+
+ void reset(const SampleAccumulator* other)
+ {
+ mNumSamples = 0;
+ mSum = 0;
+ mMin = std::numeric_limits<F64>::max();
+ mMax = std::numeric_limits<F64>::min();
+ mMean = other ? other->mLastValue : 0;
+ mVarianceSum = 0;
+ mLastSampleTimeStamp = LLTimer::getTotalSeconds();
+ mTotalSamplingTime = 0;
+ mLastValue = other ? other->mLastValue : 0;
+ mHasValue = other ? other->mHasValue : false;
+ }
+
+ void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
+ {
+ LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
+
+ if (mHasValue)
+ {
+ mSum += mLastValue * delta_time;
+ mTotalSamplingTime += delta_time;
+ }
+ mLastSampleTimeStamp = time_stamp;
+ }
+
+ F64 getSum() const { return mSum; }
+ F64 getMin() const { return mMin; }
+ F64 getMax() const { return mMax; }
+ F64 getLastValue() const { return mLastValue; }
+ F64 getMean() const { return mMean; }
+ F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mTotalSamplingTime); }
+ U32 getSampleCount() const { return mNumSamples; }
+
+ private:
+ F64 mSum,
+ mMin,
+ mMax,
+ mLastValue;
+
+ bool mHasValue;
+
+ F64 mMean,
+ mVarianceSum;
+
+ LLUnitImplicit<F64, LLUnits::Seconds> mLastSampleTimeStamp,
+ mTotalSamplingTime;
+
+ U32 mNumSamples;
+ };
+
+ class CountAccumulator
+ {
+ public:
+ typedef F64 value_t;
+ typedef F64 mean_t;
+
+ CountAccumulator()
+ : mSum(0),
+ mNumSamples(0)
+ {}
+
+ void add(F64 value)
+ {
+ mNumSamples++;
+ mSum += value;
+ }
+
+ void addSamples(const CountAccumulator& other, bool /*append*/)
+ {
+ mSum += other.mSum;
+ mNumSamples += other.mNumSamples;
+ }
+
+ void reset(const CountAccumulator* other)
+ {
+ mNumSamples = 0;
+ mSum = 0;
+ }
+
+ void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+
+ F64 getSum() const { return mSum; }
+
+ U32 getSampleCount() const { return mNumSamples; }
+
+ private:
+ F64 mSum;
+
+ U32 mNumSamples;
+ };
+
+ class TimeBlockAccumulator
+ {
+ public:
+ typedef LLUnit<F64, LLUnits::Seconds> value_t;
+ typedef LLUnit<F64, LLUnits::Seconds> mean_t;
+ typedef TimeBlockAccumulator self_t;
+
+ // fake classes that allows us to view different facets of underlying statistic
+ struct CallCountFacet
+ {
+ typedef U32 value_t;
+ typedef F32 mean_t;
+ };
+
+ struct SelfTimeFacet
+ {
+ typedef LLUnit<F64, LLUnits::Seconds> value_t;
+ typedef LLUnit<F64, LLUnits::Seconds> mean_t;
+ };
+
+ TimeBlockAccumulator();
+ void addSamples(const self_t& other, bool /*append*/);
+ void reset(const self_t* other);
+ void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+
+ //
+ // members
+ //
+ U64 mStartTotalTimeCounter,
+ mTotalTimeCounter,
+ mSelfTimeCounter;
+ U32 mCalls;
+ class TimeBlock* mParent; // last acknowledged parent of this time block
+ class TimeBlock* mLastCaller; // used to bootstrap tree construction
+ 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
+
+ };
+
+ class TimeBlock;
+ class TimeBlockTreeNode
+ {
+ public:
+ TimeBlockTreeNode();
+
+ void setParent(TimeBlock* parent);
+ TimeBlock* getParent() { return mParent; }
+
+ TimeBlock* mBlock;
+ TimeBlock* mParent;
+ std::vector<TimeBlock*> mChildren;
+ bool mCollapsed;
+ bool mNeedsSorting;
+ };
+
+ struct BlockTimerStackRecord
+ {
+ class BlockTimer* mActiveTimer;
+ class TimeBlock* mTimeBlock;
+ U64 mChildTime;
+ };
+
+ struct MemStatAccumulator
+ {
+ typedef MemStatAccumulator self_t;
+
+ // fake classes that allows us to view different facets of underlying statistic
+ struct AllocationCountFacet
+ {
+ typedef U32 value_t;
+ typedef F32 mean_t;
+ };
+
+ struct DeallocationCountFacet
+ {
+ typedef U32 value_t;
+ typedef F32 mean_t;
+ };
+
+ struct ChildMemFacet
+ {
+ typedef LLUnit<F64, LLUnits::Bytes> value_t;
+ typedef LLUnit<F64, LLUnits::Bytes> mean_t;
+ };
+
+ MemStatAccumulator()
+ : mAllocatedCount(0),
+ mDeallocatedCount(0)
+ {}
+
+ void addSamples(const MemStatAccumulator& other, bool append)
+ {
+ mSize.addSamples(other.mSize, append);
+ mChildSize.addSamples(other.mChildSize, append);
+ mAllocatedCount += other.mAllocatedCount;
+ mDeallocatedCount += other.mDeallocatedCount;
+ }
+
+ void reset(const MemStatAccumulator* other)
+ {
+ mSize.reset(other ? &other->mSize : NULL);
+ mChildSize.reset(other ? &other->mChildSize : NULL);
+ mAllocatedCount = 0;
+ mDeallocatedCount = 0;
+ }
+
+ void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
+ {
+ mSize.sync(time_stamp);
+ mChildSize.sync(time_stamp);
+ }
+
+ SampleAccumulator mSize,
+ mChildSize;
+ int mAllocatedCount,
+ mDeallocatedCount;
+ };
+
+ struct AccumulatorBufferGroup : public LLRefCount
+ {
+ AccumulatorBufferGroup();
+
+ void handOffTo(AccumulatorBufferGroup& other);
+ void makePrimary();
+ bool isPrimary() const;
+ static void clearPrimary();
+
+ void append(const AccumulatorBufferGroup& other);
+ void merge(const AccumulatorBufferGroup& other);
+ void reset(AccumulatorBufferGroup* other = NULL);
+ void sync();
+
+ AccumulatorBuffer<CountAccumulator> mCounts;
+ AccumulatorBuffer<SampleAccumulator> mSamples;
+ AccumulatorBuffer<EventAccumulator> mEvents;
+ AccumulatorBuffer<TimeBlockAccumulator> mStackTimers;
+ AccumulatorBuffer<MemStatAccumulator> mMemStats;
+ };
+}
+
+#endif // LL_LLTRACEACCUMULATORS_H
+
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index d34434f161..f1388e7935 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -33,85 +33,7 @@
namespace LLTrace
{
-
-
-///////////////////////////////////////////////////////////////////////
-// RecordingBuffers
-///////////////////////////////////////////////////////////////////////
-
-RecordingBuffers::RecordingBuffers()
-{}
-
-void RecordingBuffers::handOffTo(RecordingBuffers& other)
-{
- other.mCounts.reset(&mCounts);
- other.mSamples.reset(&mSamples);
- other.mEvents.reset(&mEvents);
- other.mStackTimers.reset(&mStackTimers);
- other.mMemStats.reset(&mMemStats);
-}
-
-void RecordingBuffers::makePrimary()
-{
- mCounts.makePrimary();
- mSamples.makePrimary();
- mEvents.makePrimary();
- mStackTimers.makePrimary();
- mMemStats.makePrimary();
-
- ThreadRecorder* thread_recorder = get_thread_recorder().get();
- AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
- // update stacktimer parent pointers
- for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++)
- {
- TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(i);
- if (tree_node)
- {
- timer_accumulator_buffer[i].mParent = tree_node->mParent;
- }
- }
-}
-
-bool RecordingBuffers::isPrimary() const
-{
- return mCounts.isPrimary();
-}
-
-void RecordingBuffers::append( const RecordingBuffers& other )
-{
- mCounts.addSamples(other.mCounts);
- mSamples.addSamples(other.mSamples);
- mEvents.addSamples(other.mEvents);
- mMemStats.addSamples(other.mMemStats);
- mStackTimers.addSamples(other.mStackTimers);
-}
-
-void RecordingBuffers::merge( const RecordingBuffers& other)
-{
- mCounts.addSamples(other.mCounts, false);
- mSamples.addSamples(other.mSamples, false);
- mEvents.addSamples(other.mEvents, false);
- mMemStats.addSamples(other.mMemStats, false);
- // for now, hold out timers from merge, need to be displayed per thread
- //mStackTimers.addSamples(other.mStackTimers, false);
-}
-
-void RecordingBuffers::reset(RecordingBuffers* other)
-{
- mCounts.reset(other ? &other->mCounts : NULL);
- mSamples.reset(other ? &other->mSamples : NULL);
- mEvents.reset(other ? &other->mEvents : NULL);
- mStackTimers.reset(other ? &other->mStackTimers : NULL);
- mMemStats.reset(other ? &other->mMemStats : NULL);
-}
-
-void RecordingBuffers::flush()
-{
- LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
-
- mSamples.flush(time_stamp);
-}
-
+
///////////////////////////////////////////////////////////////////////
// Recording
///////////////////////////////////////////////////////////////////////
@@ -119,7 +41,7 @@ void RecordingBuffers::flush()
Recording::Recording()
: mElapsedSeconds(0)
{
- mBuffers = new RecordingBuffers();
+ mBuffers = new AccumulatorBufferGroup();
}
Recording::Recording( const Recording& other )
@@ -132,17 +54,17 @@ Recording& Recording::operator = (const Recording& other)
// this will allow us to seamlessly start without affecting any data we've acquired from other
setPlayState(PAUSED);
- Recording& mutable_other = const_cast<Recording&>(other);
- mutable_other.update();
+ const_cast<Recording&>(other).update();
EPlayState other_play_state = other.getPlayState();
- mBuffers = mutable_other.mBuffers;
-
- LLStopWatchControlsMixin<Recording>::setPlayState(other_play_state);
+ mBuffers = other.mBuffers;
// above call will clear mElapsedSeconds as a side effect, so copy it here
mElapsedSeconds = other.mElapsedSeconds;
mSamplingTimer = other.mSamplingTimer;
+
+ setPlayState(other_play_state);
+
return *this;
}
@@ -151,7 +73,7 @@ Recording::~Recording()
{
if (isStarted() && LLTrace::get_thread_recorder().notNull())
{
- LLTrace::get_thread_recorder()->deactivate(this);
+ LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
}
}
@@ -159,8 +81,10 @@ void Recording::update()
{
if (isStarted())
{
- mBuffers.write()->flush();
- LLTrace::get_thread_recorder()->bringUpToDate(this);
+ mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+ AccumulatorBufferGroup* buffers = mBuffers.write();
+ LLTrace::get_thread_recorder()->bringUpToDate(buffers);
+
mSamplingTimer.reset();
}
}
@@ -176,14 +100,15 @@ void Recording::handleReset()
void Recording::handleStart()
{
mSamplingTimer.reset();
- LLTrace::get_thread_recorder()->activate(this);
+ mBuffers.setStayUnique(true);
+ LLTrace::get_thread_recorder()->activate(mBuffers.write());
}
void Recording::handleStop()
{
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
- mBuffers.write()->flush();
- LLTrace::get_thread_recorder()->deactivate(this);
+ LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
+ mBuffers.setStayUnique(false);
}
void Recording::handleSplitTo(Recording& other)
@@ -191,19 +116,14 @@ void Recording::handleSplitTo(Recording& other)
mBuffers.write()->handOffTo(*other.mBuffers.write());
}
-void Recording::appendRecording( const Recording& other )
+void Recording::appendRecording( Recording& other )
{
update();
+ other.update();
mBuffers.write()->append(*other.mBuffers);
mElapsedSeconds += other.mElapsedSeconds;
}
-void Recording::mergeRecording( const Recording& other)
-{
- update();
- mBuffers.write()->merge(*other.mBuffers);
-}
-
LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
{
const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
@@ -710,8 +630,6 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat,
void ExtendableRecording::extend()
{
- // stop recording to get latest data
- mPotentialRecording.update();
// push the data back to accepted recording
mAcceptedRecording.appendRecording(mPotentialRecording);
// flush data, so we can start from scratch
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index b839e85de0..7b0970ffdf 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -32,7 +32,7 @@
#include "llpointer.h"
#include "lltimer.h"
-#include "lltrace.h"
+#include "lltraceaccumulators.h"
class LLStopWatchControlsMixinCommon
{
@@ -81,6 +81,7 @@ class LLStopWatchControlsMixin
: public LLStopWatchControlsMixinCommon
{
public:
+
typedef LLStopWatchControlsMixin<DERIVED> self_t;
virtual void splitTo(DERIVED& other)
{
@@ -98,6 +99,11 @@ public:
static_cast<self_t&>(other).handleSplitTo(*static_cast<DERIVED*>(this));
}
private:
+ self_t& operator = (const self_t& other)
+ {
+ // don't do anything, derived class must implement logic
+ }
+
// atomically stop this object while starting the other
// no data can be missed in between stop and start
virtual void handleSplitTo(DERIVED& other) {};
@@ -106,25 +112,17 @@ private:
namespace LLTrace
{
- struct RecordingBuffers : public LLRefCount
- {
- RecordingBuffers();
-
- void handOffTo(RecordingBuffers& other);
- void makePrimary();
- bool isPrimary() const;
-
- void append(const RecordingBuffers& other);
- void merge(const RecordingBuffers& other);
- void reset(RecordingBuffers* other = NULL);
- void flush();
-
- AccumulatorBuffer<CountAccumulator> mCounts;
- AccumulatorBuffer<SampleAccumulator> mSamples;
- AccumulatorBuffer<EventAccumulator> mEvents;
- AccumulatorBuffer<TimeBlockAccumulator> mStackTimers;
- AccumulatorBuffer<MemStatAccumulator> mMemStats;
- };
+ template<typename T>
+ class TraceType;
+
+ template<typename T>
+ class CountStatHandle;
+
+ template<typename T>
+ class SampleStatHandle;
+
+ template<typename T>
+ class EventStatHandle;
class Recording
: public LLStopWatchControlsMixin<Recording>
@@ -138,10 +136,7 @@ namespace LLTrace
Recording& operator = (const Recording& other);
// accumulate data from subsequent, non-overlapping recording
- void appendRecording(const Recording& other);
-
- // gather data from recording, ignoring time relationship (for example, pulling data from slave threads)
- void mergeRecording(const Recording& other);
+ void appendRecording(Recording& other);
// grab latest recorded data
void update();
@@ -291,7 +286,7 @@ namespace LLTrace
LLTimer mSamplingTimer;
LLUnit<F64, LLUnits::Seconds> mElapsedSeconds;
- LLCopyOnWritePointer<RecordingBuffers> mBuffers;
+ LLCopyOnWritePointer<AccumulatorBufferGroup> mBuffers;
};
class LL_COMMON_API PeriodicRecording
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 54006f4e5b..7ac0e75154 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -31,25 +31,33 @@
namespace LLTrace
{
+static ThreadRecorder* sMasterThreadRecorder = NULL;
///////////////////////////////////////////////////////////////////////
// ThreadRecorder
///////////////////////////////////////////////////////////////////////
ThreadRecorder::ThreadRecorder()
+: mMasterRecorder(NULL)
{
+ init();
+}
+
+void ThreadRecorder::init()
+{
+ LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(&mBlockTimerStackRecord);
//NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies
set_thread_recorder(this);
TimeBlock& root_time_block = TimeBlock::getRootTimeBlock();
- ThreadTimerStack* timer_stack = ThreadTimerStack::getInstance();
+ BlockTimerStackRecord* timer_stack = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
timer_stack->mTimeBlock = &root_time_block;
timer_stack->mActiveTimer = NULL;
mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes];
- mThreadRecording.start();
+ activate(&mThreadRecordingBuffers);
// initialize time block parent pointers
for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances();
@@ -70,8 +78,21 @@ ThreadRecorder::ThreadRecorder()
TimeBlock::getRootTimeBlock().getPrimaryAccumulator()->mActiveCount = 1;
}
+
+ThreadRecorder::ThreadRecorder(ThreadRecorder& master)
+: mMasterRecorder(&master)
+{
+ init();
+ mMasterRecorder->addChildRecorder(this);
+}
+
+
ThreadRecorder::~ThreadRecorder()
{
+ LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL);
+
+ deactivate(&mThreadRecordingBuffers);
+
delete mRootTimer;
if (!mActiveRecordings.empty())
@@ -82,9 +103,14 @@ ThreadRecorder::~ThreadRecorder()
set_thread_recorder(NULL);
delete[] mTimeBlockTreeNodes;
+
+ if (mMasterRecorder)
+ {
+ mMasterRecorder->removeChildRecorder(this);
+ }
}
-TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode(S32 index)
+TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
{
if (0 <= index && index < mNumTimeBlockTreeNodes)
{
@@ -94,23 +120,25 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode(S32 index)
}
-void ThreadRecorder::activate( Recording* recording )
+void ThreadRecorder::activate( AccumulatorBufferGroup* recording )
{
ActiveRecording* active_recording = new ActiveRecording(recording);
if (!mActiveRecordings.empty())
{
- mActiveRecordings.back()->mPartialRecording.handOffTo(active_recording->mPartialRecording);
+ AccumulatorBufferGroup& prev_active_recording = mActiveRecordings.back()->mPartialRecording;
+ prev_active_recording.sync();
+ prev_active_recording.handOffTo(active_recording->mPartialRecording);
}
mActiveRecordings.push_back(active_recording);
mActiveRecordings.back()->mPartialRecording.makePrimary();
}
-ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringUpToDate( Recording* recording )
+ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )
{
if (mActiveRecordings.empty()) return mActiveRecordings.rend();
- mActiveRecordings.back()->mPartialRecording.flush();
+ mActiveRecordings.back()->mPartialRecording.sync();
TimeBlock::updateTimes();
active_recording_list_t::reverse_iterator it, end_it;
@@ -148,145 +176,125 @@ ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringU
return it;
}
-void ThreadRecorder::deactivate( Recording* recording )
+void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
{
active_recording_list_t::reverse_iterator it = bringUpToDate(recording);
if (it != mActiveRecordings.rend())
{
- // and if we've found the recording we wanted to update
- active_recording_list_t::reverse_iterator next_it = it;
- ++next_it;
- if (next_it != mActiveRecordings.rend())
- {
- (*next_it)->mPartialRecording.makePrimary();
- }
-
active_recording_list_t::iterator recording_to_remove = (++it).base();
+ bool was_primary = (*recording_to_remove)->mPartialRecording.isPrimary();
llassert((*recording_to_remove)->mTargetRecording == recording);
delete *recording_to_remove;
mActiveRecordings.erase(recording_to_remove);
+ if (was_primary)
+ {
+ if (mActiveRecordings.empty())
+ {
+ AccumulatorBufferGroup::clearPrimary();
+ }
+ else
+ {
+ mActiveRecordings.back()->mPartialRecording.makePrimary();
+ }
+ }
}
}
-ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target )
+ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target )
: mTargetRecording(target)
{
}
void ThreadRecorder::ActiveRecording::movePartialToTarget()
{
- mTargetRecording->mBuffers.write()->append(mPartialRecording);
+ mTargetRecording->append(mPartialRecording);
// reset based on self to keep history
mPartialRecording.reset(&mPartialRecording);
}
-///////////////////////////////////////////////////////////////////////
-// SlaveThreadRecorder
-///////////////////////////////////////////////////////////////////////
-
-SlaveThreadRecorder::SlaveThreadRecorder(MasterThreadRecorder& master)
-: mMasterRecorder(master)
-{
- mMasterRecorder.addSlaveThread(this);
+// called by child thread
+void ThreadRecorder::addChildRecorder( class ThreadRecorder* child )
+{ LLMutexLock lock(&mChildListMutex);
+ mChildThreadRecorders.push_back(child);
}
-SlaveThreadRecorder::~SlaveThreadRecorder()
-{
- mMasterRecorder.removeSlaveThread(this);
-}
+// called by child thread
+void ThreadRecorder::removeChildRecorder( class ThreadRecorder* child )
+{ LLMutexLock lock(&mChildListMutex);
-void SlaveThreadRecorder::pushToMaster()
+for (child_thread_recorder_list_t::iterator it = mChildThreadRecorders.begin(), end_it = mChildThreadRecorders.end();
+ it != end_it;
+ ++it)
{
- mThreadRecording.stop();
+ if ((*it) == child)
{
- LLMutexLock(mMasterRecorder.getSlaveListMutex());
- mSharedData.appendFrom(mThreadRecording);
+ mChildThreadRecorders.erase(it);
+ break;
}
- mThreadRecording.start();
-}
-
-void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source )
-{
- LLMutexLock lock(&mRecordingMutex);
- appendRecording(source);
}
-
-void SlaveThreadRecorder::SharedData::appendTo( Recording& sink )
-{
- LLMutexLock lock(&mRecordingMutex);
- sink.appendRecording(*this);
}
-void SlaveThreadRecorder::SharedData::mergeFrom( const RecordingBuffers& source )
+void ThreadRecorder::pushToParent()
{
- LLMutexLock lock(&mRecordingMutex);
- mBuffers.write()->merge(source);
+ { LLMutexLock lock(&mSharedRecordingMutex);
+ LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers);
+ mSharedRecordingBuffers.append(mThreadRecordingBuffers);
+ }
}
+
-void SlaveThreadRecorder::SharedData::mergeTo( RecordingBuffers& sink )
-{
- LLMutexLock lock(&mRecordingMutex);
- sink.merge(*mBuffers);
-}
-void SlaveThreadRecorder::SharedData::reset()
-{
- LLMutexLock lock(&mRecordingMutex);
- Recording::reset();
-}
+static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data");
-///////////////////////////////////////////////////////////////////////
-// MasterThreadRecorder
-///////////////////////////////////////////////////////////////////////
-
-static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_SLAVES("Pull slave trace data");
-void MasterThreadRecorder::pullFromSlaveThreads()
+void ThreadRecorder::pullFromChildren()
{
- LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_SLAVES);
+ LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_CHILDREN);
if (mActiveRecordings.empty()) return;
- LLMutexLock lock(&mSlaveListMutex);
+ { LLMutexLock lock(&mChildListMutex);
- RecordingBuffers& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
- for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
- it != end_it;
- ++it)
- {
- // ignore block timing info for now
- (*it)->mSharedData.mergeTo(target_recording_buffers);
- (*it)->mSharedData.reset();
+ AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
+ target_recording_buffers.sync();
+ for (child_thread_recorder_list_t::iterator it = mChildThreadRecorders.begin(), end_it = mChildThreadRecorders.end();
+ it != end_it;
+ ++it)
+ { LLMutexLock lock(&(*it)->mSharedRecordingMutex);
+
+ target_recording_buffers.merge((*it)->mSharedRecordingBuffers);
+ (*it)->mSharedRecordingBuffers.reset();
+ }
}
}
-void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child )
+
+void set_master_thread_recorder(ThreadRecorder* recorder)
{
- LLMutexLock lock(&mSlaveListMutex);
+ sMasterThreadRecorder = recorder;
+}
- mSlaveThreadRecorders.push_back(child);
+
+ThreadRecorder* get_master_thread_recorder()
+{
+ return sMasterThreadRecorder;
}
-void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
+LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
{
- LLMutexLock lock(&mSlaveListMutex);
+ static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
+ return s_thread_recorder;
+}
- for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
- it != end_it;
- ++it)
- {
- if ((*it) == child)
- {
- mSlaveThreadRecorders.erase(it);
- break;
- }
- }
+const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
+{
+ return get_thread_recorder_ptr();
}
-void MasterThreadRecorder::pushToMaster()
-{}
+void set_thread_recorder(ThreadRecorder* recorder)
+{
+ get_thread_recorder_ptr() = recorder;
+}
-MasterThreadRecorder::MasterThreadRecorder()
-{}
}
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index bf3701304f..535f855200 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -31,7 +31,8 @@
#include "llpreprocessor.h"
#include "llmutex.h"
-#include "lltracerecording.h"
+#include "lltraceaccumulators.h"
+#include "llthreadlocalstorage.h"
namespace LLTrace
{
@@ -42,85 +43,60 @@ namespace LLTrace
typedef std::vector<ActiveRecording*> active_recording_list_t;
public:
ThreadRecorder();
+ explicit ThreadRecorder(ThreadRecorder& master);
- virtual ~ThreadRecorder();
+ ~ThreadRecorder();
- void activate(Recording* recording);
- void deactivate(Recording* recording);
- active_recording_list_t::reverse_iterator bringUpToDate(Recording* recording);
+ void activate(AccumulatorBufferGroup* recording);
+ void deactivate(AccumulatorBufferGroup* recording);
+ active_recording_list_t::reverse_iterator bringUpToDate(AccumulatorBufferGroup* recording);
- virtual void pushToMaster() = 0;
+ void addChildRecorder(class ThreadRecorder* child);
+ void removeChildRecorder(class ThreadRecorder* child);
+
+ // call this periodically to gather stats data from child threads
+ void pullFromChildren();
+ void pushToParent();
TimeBlockTreeNode* getTimeBlockTreeNode(S32 index);
protected:
+ void init();
+
+ protected:
struct ActiveRecording
{
- ActiveRecording(Recording* target);
+ ActiveRecording(AccumulatorBufferGroup* target);
- Recording* mTargetRecording;
- RecordingBuffers mPartialRecording;
+ AccumulatorBufferGroup* mTargetRecording;
+ AccumulatorBufferGroup mPartialRecording;
void movePartialToTarget();
};
- Recording mThreadRecording;
-
- active_recording_list_t mActiveRecordings;
-
- class BlockTimer* mRootTimer;
- TimeBlockTreeNode* mTimeBlockTreeNodes;
- size_t mNumTimeBlockTreeNodes;
- };
-
- class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
- {
- public:
- MasterThreadRecorder();
-
- void addSlaveThread(class SlaveThreadRecorder* child);
- void removeSlaveThread(class SlaveThreadRecorder* child);
- /*virtual */ void pushToMaster();
+ AccumulatorBufferGroup mThreadRecordingBuffers;
- // call this periodically to gather stats data from slave threads
- void pullFromSlaveThreads();
+ BlockTimerStackRecord mBlockTimerStackRecord;
+ active_recording_list_t mActiveRecordings;
- LLMutex* getSlaveListMutex() { return &mSlaveListMutex; }
+ class BlockTimer* mRootTimer;
+ TimeBlockTreeNode* mTimeBlockTreeNodes;
+ size_t mNumTimeBlockTreeNodes;
+ typedef std::list<class ThreadRecorder*> child_thread_recorder_list_t;
+ child_thread_recorder_list_t mChildThreadRecorders; // list of child thread recorders associated with this master
+ LLMutex mChildListMutex; // protects access to child list
+ LLMutex mSharedRecordingMutex;
+ AccumulatorBufferGroup mSharedRecordingBuffers;
+ ThreadRecorder* mMasterRecorder;
- private:
-
- typedef std::list<class SlaveThreadRecorder*> slave_thread_recorder_list_t;
-
- slave_thread_recorder_list_t mSlaveThreadRecorders; // list of slave thread recorders associated with this master
- LLMutex mSlaveListMutex; // protects access to slave list
};
- class LL_COMMON_API SlaveThreadRecorder : public ThreadRecorder
- {
- public:
- SlaveThreadRecorder(MasterThreadRecorder& master);
- ~SlaveThreadRecorder();
-
- // call this periodically to gather stats data for master thread to consume
- /*virtual*/ void pushToMaster();
+ const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder();
+ void set_thread_recorder(ThreadRecorder*);
- MasterThreadRecorder* mMaster;
-
- class SharedData : public Recording
- {
- public:
- void appendFrom(const Recording& source);
- void appendTo(Recording& sink);
- void mergeFrom(const RecordingBuffers& source);
- void mergeTo(RecordingBuffers& sink);
- void reset();
- private:
- LLMutex mRecordingMutex;
- };
- SharedData mSharedData;
- MasterThreadRecorder& mMasterRecorder;
- };
+ void set_master_thread_recorder(ThreadRecorder*);
+ ThreadRecorder* get_master_thread_recorder();
}
#endif // LL_LLTRACETHREADRECORDER_H
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 2402cdbb95..c9bbed5574 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -75,17 +75,11 @@ struct LLUnit
}
template<typename NEW_UNIT_TYPE>
- STORAGE_TYPE getAs()
+ STORAGE_TYPE valueAs()
{
return LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(*this).value();
}
- template<typename NEW_UNIT_TYPE>
- STORAGE_TYPE setAs(STORAGE_TYPE val)
- {
- *this = LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(val);
- }
-
void operator += (storage_t value)
{
mValue += value;
@@ -181,6 +175,7 @@ LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ..
if (boost::is_same<T1, typename T1::base_unit_t>::value)
{
if (boost::is_same<T2, typename T2::base_unit_t>::value)
+
{
// T1 and T2 fully reduced and equal...just copy
out = (S2)in.value();
@@ -493,26 +488,45 @@ struct LLUnitInverseLinearOps
}
};
-#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \
-struct base_unit_name { typedef base_unit_name base_unit_t; static const char* getUnitLabel() { return unit_label; }}
-
-#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \
-struct unit_name \
-{ \
- typedef base_unit_name base_unit_t; \
- static const char* getUnitLabel() { return unit_label; } \
-}; \
- \
-template<typename S1, typename S2> \
-void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \
-{ \
- out = (S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation).mValue; \
-} \
- \
-template<typename S1, typename S2> \
-void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \
-{ \
- out = (S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation).mValue; \
+#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \
+struct base_unit_name \
+{ \
+ typedef base_unit_name base_unit_t; \
+ static const char* getUnitLabel() { return unit_label; } \
+ template<typename T> \
+ static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
+ template<typename STORAGE_T, typename UNIT_T> \
+ static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
+ { return LLUnit<STORAGE_T, base_unit_name>(value); } \
+}; \
+template<typename T> std::ostream& operator<<(std::ostream& s, const LLUnit<T, base_unit_name>& val) \
+{ s << val.value() << base_unit_name::getUnitLabel; return s; }
+
+
+#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \
+struct unit_name \
+{ \
+ typedef base_unit_name base_unit_t; \
+ static const char* getUnitLabel() { return unit_label; } \
+ template<typename T> \
+ static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); } \
+ template<typename STORAGE_T, typename UNIT_T> \
+ static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
+ { return LLUnit<STORAGE_T, unit_name>(value); } \
+}; \
+template<typename T> std::ostream& operator<<(std::ostream& s, const LLUnit<T, unit_name>& val) \
+{ s << val.value() << unit_name::getUnitLabel; return s; } \
+ \
+template<typename S1, typename S2> \
+void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \
+{ \
+ out = (S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation).mValue; \
+} \
+ \
+template<typename S1, typename S2> \
+void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \
+{ \
+ out = (S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation).mValue; \
}
//
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 50df2ebe55..8477e62db7 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -159,9 +159,8 @@ void LLImageBase::sanityCheck()
void LLImageBase::deleteData()
{
FREE_MEM(sPrivatePoolp, mData) ;
- memDisclaimAmount(mDataSize);
+ memDisclaimAmount(mDataSize) = 0;
mData = NULL;
- mDataSize = 0;
}
// virtual
@@ -225,9 +224,7 @@ U8* LLImageBase::reallocateData(S32 size)
FREE_MEM(sPrivatePoolp, mData) ;
}
mData = new_datap;
- memDisclaimAmount(mDataSize);
- mDataSize = size;
- memClaimAmount(mDataSize);
+ memClaimAmount(memDisclaimAmount(mDataSize) = size);
return mData;
}
@@ -1612,9 +1609,8 @@ static void avg4_colors2(const U8* a, const U8* b, const U8* c, const U8* d, U8*
void LLImageBase::setDataAndSize(U8 *data, S32 size)
{
ll_assert_aligned(data, 16);
- memDisclaimAmount(mDataSize);
- mData = data; mDataSize = size;
- memClaimAmount(mDataSize);
+ mData = data;
+ memClaimAmount(memDisclaimAmount(mDataSize) = size);
}
//static
diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp
index b6f2694742..aba7883974 100755
--- a/indra/llimage/tests/llimageworker_test.cpp
+++ b/indra/llimage/tests/llimageworker_test.cpp
@@ -115,17 +115,14 @@ namespace tut
{
// Instance to be tested
LLImageDecodeThread* mThread;
-
// Constructor and destructor of the test wrapper
imagedecodethread_test()
{
- LLTrace::init();
mThread = NULL;
}
~imagedecodethread_test()
{
delete mThread;
- LLTrace::cleanup();
}
};
@@ -143,7 +140,6 @@ namespace tut
imagerequest_test()
{
done = false;
- LLTrace::init();
mRequest = new LLImageDecodeThread::ImageRequest(0, 0,
LLQueuedThread::PRIORITY_NORMAL, 0, FALSE,
@@ -154,7 +150,6 @@ namespace tut
// We should delete the object *but*, because its destructor is protected, that cannot be
// done from outside an LLImageDecodeThread instance... So we leak memory here... It's fine...
//delete mRequest;
- LLTrace::cleanup();
}
};
diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp
index d3cc2733e6..fd88565de4 100755
--- a/indra/llui/llstatbar.cpp
+++ b/indra/llui/llstatbar.cpp
@@ -345,9 +345,9 @@ void LLStatBar::draw()
else if (mSampleFloatp)
{
//rate isn't defined for sample stats, so use mean
- begin = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale);
- end = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale) + 1;
- num_samples = recording.getSampleCount(*mEventFloatp);
+ begin = ((recording.getMean(*mSampleFloatp) - mMinBar) * value_scale);
+ end = ((recording.getMean(*mSampleFloatp) - mMinBar) * value_scale) + 1;
+ num_samples = recording.getSampleCount(*mSampleFloatp);
}
}
else
@@ -366,9 +366,9 @@ void LLStatBar::draw()
}
else if (mSampleFloatp)
{
- begin = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale);
- end = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale) + 1;
- num_samples = recording.getSampleCount(*mEventFloatp);
+ begin = ((recording.getMean(*mSampleFloatp) - mMinBar) * value_scale);
+ end = ((recording.getMean(*mSampleFloatp) - mMinBar) * value_scale) + 1;
+ num_samples = recording.getSampleCount(*mSampleFloatp);
}
}
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 733c9cc9df..e77f793a43 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1297,7 +1297,7 @@ bool LLAppViewer::mainLoop()
LLTrace::get_frame_recording().nextPeriod();
LLTrace::TimeBlock::logStats();
- LLTrace::getUIThreadRecorder().pullFromSlaveThreads();
+ LLTrace::get_master_thread_recorder()->pullFromChildren();
//clear call stack records
llclearcallstacks;
@@ -5617,6 +5617,6 @@ void LLAppViewer::metricsSend(bool enable_reporting)
// Reset even if we can't report. Rather than gather up a huge chunk of
// data, we'll keep to our sampling interval and retain the data
// resolution in time.
- gViewerAssetStats->reset();
+ gViewerAssetStats->restart();
}
diff --git a/indra/newview/llclassifiedstatsresponder.cpp b/indra/newview/llclassifiedstatsresponder.cpp
index e3cd83e174..1e1c9039fb 100755
--- a/indra/newview/llclassifiedstatsresponder.cpp
+++ b/indra/newview/llclassifiedstatsresponder.cpp
@@ -38,10 +38,8 @@
#include "message.h"
LLClassifiedStatsResponder::LLClassifiedStatsResponder(LLUUID classified_id)
-:
-mClassifiedID(classified_id)
-{
-}
+: mClassifiedID(classified_id)
+{}
/*virtual*/
void LLClassifiedStatsResponder::result(const LLSD& content)
@@ -53,12 +51,11 @@ void LLClassifiedStatsResponder::result(const LLSD& content)
S32 search_map = content["search_map_clicks"].asInteger();
S32 search_profile = content["search_profile_clicks"].asInteger();
- LLPanelClassifiedInfo::setClickThrough(
- mClassifiedID,
- teleport + search_teleport,
- map + search_map,
- profile + search_profile,
- true);
+ LLPanelClassifiedInfo::setClickThrough( mClassifiedID,
+ teleport + search_teleport,
+ map + search_map,
+ profile + search_profile,
+ true);
}
/*virtual*/
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index d3a97fde0e..d922659435 100755
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -430,18 +430,18 @@ void LLFastTimerView::draw()
}
void LLFastTimerView::onOpen(const LLSD& key)
- {
+{
setPauseState(false);
mRecording.reset();
mRecording.appendPeriodicRecording(LLTrace::get_frame_recording());
for(std::deque<TimerBarRow>::iterator it = mTimerBarRows.begin(), end_it = mTimerBarRows.end();
it != end_it;
- ++it)
- {
+ ++it)
+ {
delete []it->mBars;
it->mBars = NULL;
- }
- }
+ }
+}
void saveChart(const std::string& label, const char* suffix, LLImageRaw* scratch)
@@ -1101,7 +1101,7 @@ void LLFastTimerView::drawLineGraph()
j--)
{
LLTrace::Recording& recording = mRecording.getPrevRecording(j);
- LLUnit<F32, LLUnits::Seconds> time = llmax(recording.getSum(*idp), LLUnit<F64, LLUnits::Seconds>(0.000001));
+ LLUnit<F32, LLUnits::Seconds> time = llmax(recording.getSum(*idp), LLUnits::Seconds::fromValue(0.000001));
U32 calls = recording.getSum(idp->callCount());
if (is_hover_timer)
@@ -1126,7 +1126,7 @@ void LLFastTimerView::drawLineGraph()
}
gGL.vertex2f(x,y);
gGL.vertex2f(x,mGraphRect.mBottom);
-}
+ }
gGL.end();
if (mHoverID == idp)
@@ -1146,7 +1146,7 @@ void LLFastTimerView::drawLineGraph()
max_time = lerp(max_time.value(), cur_max.value(), LLSmoothInterpolation::getInterpolant(0.1f));
if (llabs((max_time - cur_max).value()) <= 1)
{
- max_time = llmax(LLUnit<F32, LLUnits::Microseconds>(1), LLUnit<F32, LLUnits::Microseconds>(cur_max));
+ max_time = llmax(LLUnits::Microseconds::fromValue(1.f), LLUnits::Microseconds::fromValue(cur_max));
}
max_calls = llround(lerp((F32)max_calls, (F32) cur_max_calls, LLSmoothInterpolation::getInterpolant(0.1f)));
@@ -1423,11 +1423,11 @@ void LLFastTimerView::updateTotalTime()
mTotalTimeDisplay = mRecording.getPeriodMax(FTM_FRAME, 20);
break;
default:
- mTotalTimeDisplay = LLUnit<F32, LLUnits::Milliseconds>(100);
+ mTotalTimeDisplay = LLUnits::Milliseconds::fromValue(100);
break;
}
- mTotalTimeDisplay = LLUnit<F32, LLUnits::Milliseconds>(llceil(mTotalTimeDisplay.getAs<LLUnits::Milliseconds>() / 20.f) * 20.f);
+ mTotalTimeDisplay = LLUnits::Milliseconds::fromValue(llceil(mTotalTimeDisplay.valueAs<LLUnits::Milliseconds>() / 20.f) * 20.f);
}
void LLFastTimerView::drawBars()
diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp
index ed9eeb9330..342b45863a 100644
--- a/indra/newview/llscenemonitor.cpp
+++ b/indra/newview/llscenemonitor.cpp
@@ -260,14 +260,7 @@ void LLSceneMonitor::capture()
static LLCachedControl<bool> monitor_enabled(gSavedSettings, "SceneLoadingMonitorEnabled");
static LLCachedControl<F32> scene_load_sample_time(gSavedSettings, "SceneLoadingMonitorSampleTime");
static LLFrameTimer timer;
-
- if (mEnabled
- && (mMonitorRecording.getSum(*LLViewerCamera::getVelocityStat()) > 0.1f
- || mMonitorRecording.getSum(*LLViewerCamera::getAngularVelocityStat()) > 0.05f))
- {
- reset();
- freezeScene();
- }
+ static bool force_capture = true;
bool enabled = monitor_enabled || mDebugViewerVisible;
if(mEnabled != enabled)
@@ -275,6 +268,7 @@ void LLSceneMonitor::capture()
if(mEnabled)
{
unfreezeScene();
+ force_capture = true;
}
else
{
@@ -285,11 +279,23 @@ void LLSceneMonitor::capture()
mEnabled = enabled;
}
- if(timer.getElapsedTimeF32() > scene_load_sample_time()
+ if (mEnabled
+ && (mMonitorRecording.getSum(*LLViewerCamera::getVelocityStat()) > 0.1f
+ || mMonitorRecording.getSum(*LLViewerCamera::getAngularVelocityStat()) > 0.05f))
+ {
+ reset();
+ freezeScene();
+ force_capture = true;
+ }
+
+ if((timer.getElapsedTimeF32() > scene_load_sample_time()
+ || force_capture)
&& mEnabled
&& LLGLSLShader::sNoFixedFunction
&& last_capture_time != gFrameCount)
{
+ force_capture = false;
+
mSceneLoadRecording.resume();
mMonitorRecording.resume();
@@ -479,12 +485,10 @@ void LLSceneMonitor::fetchQueryResult()
if(mDiffResult > diff_threshold())
{
mSceneLoadRecording.extend();
- llassert(mSceneLoadRecording.getAcceptedRecording().getLastRecording().getSum(LLStatViewer::FPS));
}
else
{
mSceneLoadRecording.getPotentialRecording().nextPeriod();
- llassert(mSceneLoadRecording.getPotentialRecording().getLastRecording().getSum(LLStatViewer::FPS));
}
}
}
@@ -620,7 +624,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name)
for (S32 frame = 1; frame <= frame_count; frame++)
{
- os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(*it).getAs<LLUnits::Kibibytes>();
+ os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(*it).valueAs<LLUnits::Kibibytes>();
}
os << '\n';
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index de8d549055..097ea7cc8d 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2054,6 +2054,7 @@ bool idle_startup()
const F32 wearables_time = wearables_timer.getElapsedTimeF32();
static LLCachedControl<F32> max_wearables_time(gSavedSettings, "ClothingLoadingDelay");
+ display_startup();
if (!gAgent.isGenderChosen() && isAgentAvatarValid())
{
// No point in waiting for clothing, we don't even
@@ -2067,50 +2068,39 @@ bool idle_startup()
LLNotificationsUtil::add("WelcomeChooseSex", LLSD(), LLSD(),
callback_choose_gender);
LLStartUp::setStartupState( STATE_CLEANUP );
- return TRUE;
}
-
- display_startup();
-
- if (wearables_time > max_wearables_time())
+ else if (wearables_time >= max_wearables_time())
{
LLNotificationsUtil::add("ClothingLoading");
record(LLStatViewer::LOADING_WEARABLES_LONG_DELAY, wearables_time);
LLStartUp::setStartupState( STATE_CLEANUP );
- return TRUE;
}
-
- if (gAgent.isFirstLogin())
+ else if (gAgent.isFirstLogin()
+ && isAgentAvatarValid()
+ && gAgentAvatarp->isFullyLoaded())
{
// wait for avatar to be completely loaded
- if (isAgentAvatarValid()
- && gAgentAvatarp->isFullyLoaded())
- {
- //llinfos << "avatar fully loaded" << llendl;
- LLStartUp::setStartupState( STATE_CLEANUP );
- return TRUE;
- }
+ //llinfos << "avatar fully loaded" << llendl;
+ LLStartUp::setStartupState( STATE_CLEANUP );
+ }
+ // OK to just get the wearables
+ else if (!gAgent.isFirstLogin() && gAgentWearables.areWearablesLoaded() )
+ {
+ // We have our clothing, proceed.
+ //llinfos << "wearables loaded" << llendl;
+ LLStartUp::setStartupState( STATE_CLEANUP );
}
else
{
- // OK to just get the wearables
- if ( gAgentWearables.areWearablesLoaded() )
- {
- // We have our clothing, proceed.
- //llinfos << "wearables loaded" << llendl;
- LLStartUp::setStartupState( STATE_CLEANUP );
- return TRUE;
- }
+ display_startup();
+ update_texture_fetch();
+ display_startup();
+ set_startup_status(0.9f + 0.1f * wearables_time / max_wearables_time(),
+ LLTrans::getString("LoginDownloadingClothing").c_str(),
+ gAgent.mMOTD.c_str());
+ display_startup();
}
-
- display_startup();
- update_texture_fetch();
- display_startup();
- set_startup_status(0.9f + 0.1f * wearables_time / max_wearables_time(),
- LLTrans::getString("LoginDownloadingClothing").c_str(),
- gAgent.mMOTD.c_str());
- display_startup();
- return TRUE;
+ //fall through this frame to STATE_CLEANUP
}
if (STATE_CLEANUP == LLStartUp::getStartupState())
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 4b9a950b98..0390649a1c 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -504,81 +504,85 @@ private:
static const char* sStateDescs[];
e_state mState;
void setState(e_state new_state);
- e_write_to_cache_state mWriteToCacheState;
- LLTextureFetch* mFetcher;
+
+ e_write_to_cache_state mWriteToCacheState;
+ LLTextureFetch* mFetcher;
LLPointer<LLImageFormatted> mFormattedImage;
- LLPointer<LLImageRaw> mRawImage;
- LLPointer<LLImageRaw> mAuxImage;
- FTType mFTType;
- LLUUID mID;
- LLHost mHost;
- std::string mUrl;
- U8 mType;
- F32 mImagePriority;
- U32 mWorkPriority;
- F32 mRequestedPriority;
- S32 mDesiredDiscard;
- S32 mSimRequestedDiscard;
- S32 mRequestedDiscard;
- S32 mLoadedDiscard;
- S32 mDecodedDiscard;
- LLFrameTimer mRequestedTimer;
- LLFrameTimer mFetchTimer;
- LLTimer mCacheReadTimer;
- F32 mCacheReadTime;
- LLTextureCache::handle_t mCacheReadHandle;
- LLTextureCache::handle_t mCacheWriteHandle;
- S32 mRequestedSize;
- S32 mRequestedOffset;
- S32 mDesiredSize;
- S32 mFileSize;
- S32 mCachedSize;
- e_request_state mSentRequest;
- handle_t mDecodeHandle;
- BOOL mLoaded;
- BOOL mDecoded;
- BOOL mWritten;
- BOOL mNeedsAux;
- BOOL mHaveAllData;
- BOOL mInLocalCache;
- BOOL mInCache;
- bool mCanUseHTTP ;
- bool mCanUseNET ; //can get from asset server.
- S32 mRetryAttempt;
- S32 mActiveCount;
- LLCore::HttpStatus mGetStatus;
- std::string mGetReason;
+ LLPointer<LLImageRaw> mRawImage,
+ mAuxImage;
+ FTType mFTType;
+ LLUUID mID;
+ LLHost mHost;
+ std::string mUrl;
+ U8 mType;
+ F32 mImagePriority;
+ U32 mWorkPriority;
+ F32 mRequestedPriority;
+ S32 mDesiredDiscard,
+ mSimRequestedDiscard,
+ mRequestedDiscard,
+ mLoadedDiscard,
+ mDecodedDiscard;
+ LLFrameTimer mRequestedTimer,
+ mFetchTimer;
+ LLTimer mCacheReadTimer;
+ F32 mCacheReadTime;
+ LLTextureCache::handle_t mCacheReadHandle,
+ mCacheWriteHandle;
+ S32 mRequestedSize,
+ mRequestedOffset,
+ mDesiredSize,
+ mFileSize,
+ mCachedSize;
+ e_request_state mSentRequest;
+ handle_t mDecodeHandle;
+ BOOL mLoaded;
+ BOOL mDecoded;
+ BOOL mWritten;
+ BOOL mNeedsAux;
+ BOOL mHaveAllData;
+ BOOL mInLocalCache;
+ BOOL mInCache;
+ bool mCanUseHTTP,
+ mCanUseNET ; //can get from asset server.
+ S32 mRetryAttempt;
+ S32 mActiveCount;
+ LLCore::HttpStatus mGetStatus;
+ std::string mGetReason;
// Work Data
- LLMutex mWorkMutex;
+ LLMutex mWorkMutex;
struct PacketData
{
- PacketData(U8* data, S32 size) { mData = data; mSize = size; }
+ PacketData(U8* data, S32 size)
+ : mData(data), mSize(size)
+ {}
~PacketData() { clearData(); }
void clearData() { delete[] mData; mData = NULL; }
- U8* mData;
- U32 mSize;
+
+ U8* mData;
+ U32 mSize;
};
- std::vector<PacketData*> mPackets;
- S32 mFirstPacket;
- S32 mLastPacket;
- U16 mTotalPackets;
- U8 mImageCodec;
+ std::vector<PacketData*> mPackets;
+ S32 mFirstPacket;
+ S32 mLastPacket;
+ U16 mTotalPackets;
+ U8 mImageCodec;
LLViewerAssetStats::duration_t mMetricsStartTime;
- LLCore::HttpHandle mHttpHandle; // Handle of any active request
- LLCore::BufferArray * mHttpBufferArray; // Refcounted pointer to response data
- int mHttpPolicyClass;
- bool mHttpActive; // Active request to http library
- unsigned int mHttpReplySize; // Actual received data size
- unsigned int mHttpReplyOffset; // Actual received data offset
- bool mHttpHasResource; // Counts against Fetcher's mHttpSemaphore
+ LLCore::HttpHandle mHttpHandle; // Handle of any active request
+ LLCore::BufferArray * mHttpBufferArray; // Refcounted pointer to response data
+ S32 mHttpPolicyClass;
+ bool mHttpActive; // Active request to http library
+ U32 mHttpReplySize, // Actual received data size
+ mHttpReplyOffset; // Actual received data offset
+ bool mHttpHasResource; // Counts against Fetcher's mHttpSemaphore
// State history
- U32 mCacheReadCount;
- U32 mCacheWriteCount;
- U32 mResourceWaitCount; // Requests entering WAIT_HTTP_RESOURCE2
+ U32 mCacheReadCount,
+ mCacheWriteCount,
+ mResourceWaitCount; // Requests entering WAIT_HTTP_RESOURCE2
};
//////////////////////////////////////////////////////////////////////////////
@@ -2390,7 +2394,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mFetcherLocked(FALSE)
{
mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
- mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold"));
+ mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), LLUnits::Bytes::fromValue(gSavedSettings.getU32("TextureLoggingThreshold")));
LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled");
if(LLTextureFetchDebugger::isEnabled())
@@ -3369,7 +3373,7 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1
if (log_to_viewer_log || log_to_sim)
{
- U64 timeNow = LLTimer::getTotalTime();
+ LLUnit<U64, LLUnits::Microseconds> timeNow = LLTimer::getTotalTime();
mTextureInfo.setRequestSize(id, worker->mFileSize);
mTextureInfo.setRequestCompleteTimeAndLog(id, timeNow);
}
diff --git a/indra/newview/lltextureinfo.cpp b/indra/newview/lltextureinfo.cpp
index adfdbc997e..3ae85d56da 100755
--- a/indra/newview/lltextureinfo.cpp
+++ b/indra/newview/lltextureinfo.cpp
@@ -29,26 +29,28 @@
#include "lltextureinfo.h"
#include "lltexturestats.h"
#include "llviewercontrol.h"
+#include "lltrace.h"
+
+static LLTrace::CountStatHandle<S32> sTextureDownloadsStarted("texture_downloads_started", "number of texture downloads initiated");
+static LLTrace::CountStatHandle<S32> sTextureDownloadsCompleted("texture_downloads_completed", "number of texture downloads completed");
+static LLTrace::CountStatHandle<LLUnit<S32, LLUnits::Bytes> > sTextureDataDownloaded("texture_data_downloaded", "amount of texture data downloaded");
+static LLTrace::CountStatHandle<LLUnit<U32, LLUnits::Milliseconds> > sTexureDownloadTime("texture_download_time", "amount of time spent fetching textures");
LLTextureInfo::LLTextureInfo() :
mLogTextureDownloadsToViewerLog(false),
mLogTextureDownloadsToSimulator(false),
- mTotalBytes(0),
- mTotalMilliseconds(0),
- mTextureDownloadsStarted(0),
- mTextureDownloadsCompleted(0),
mTextureDownloadProtocol("NONE"),
- mTextureLogThreshold(100 * 1024),
- mCurrentStatsBundleStartTime(0)
+ mTextureLogThreshold(LLUnits::Kibibytes::fromValue(100))
{
mTextures.clear();
+ mRecording.start();
}
-void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold)
+void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, LLUnit<U32, LLUnits::Bytes> textureLogThreshold)
{
mLogTextureDownloadsToViewerLog = writeToViewerLog;
mLogTextureDownloadsToSimulator = sendToSim;
- mTextureLogThreshold = textureLogThreshold;
+ mTextureLogThreshold = LLUnit<U32, LLUnits::Bytes>(textureLogThreshold);
}
LLTextureInfo::~LLTextureInfo()
@@ -94,7 +96,7 @@ void LLTextureInfo::setRequestStartTime(const LLUUID& id, U64 startTime)
addRequest(id);
}
mTextures[id]->mStartTime = startTime;
- mTextureDownloadsStarted++;
+ add(sTextureDownloadsStarted, 1);
}
void LLTextureInfo::setRequestSize(const LLUUID& id, U32 size)
@@ -124,16 +126,19 @@ void LLTextureInfo::setRequestType(const LLUUID& id, LLTextureInfoDetails::LLReq
mTextures[id]->mType = type;
}
-void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime)
+void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, LLUnit<U64, LLUnits::Microseconds> completeTime)
{
if (!has(id))
{
addRequest(id);
}
- mTextures[id]->mCompleteTime = completeTime;
+
+ LLTextureInfoDetails& details = *mTextures[id];
+
+ details.mCompleteTime = completeTime;
std::string protocol = "NONE";
- switch(mTextures[id]->mType)
+ switch(details.mType)
{
case LLTextureInfoDetails::REQUEST_TYPE_HTTP:
protocol = "HTTP";
@@ -150,24 +155,23 @@ void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeT
if (mLogTextureDownloadsToViewerLog)
{
- llinfos << "texture=" << id
- << " start=" << mTextures[id]->mStartTime
- << " end=" << mTextures[id]->mCompleteTime
- << " size=" << mTextures[id]->mSize
- << " offset=" << mTextures[id]->mOffset
- << " length_in_ms=" << (mTextures[id]->mCompleteTime - mTextures[id]->mStartTime) / 1000
- << " protocol=" << protocol
- << llendl;
+ llinfos << "texture=" << id
+ << " start=" << details.mStartTime
+ << " end=" << details.mCompleteTime
+ << " size=" << details.mSize
+ << " offset=" << details.mOffset
+ << " length=" << LLUnit<U32, LLUnits::Milliseconds>(details.mCompleteTime - details.mStartTime)
+ << " protocol=" << protocol
+ << llendl;
}
if(mLogTextureDownloadsToSimulator)
{
- S32 texture_stats_upload_threshold = mTextureLogThreshold;
- mTotalBytes += mTextures[id]->mSize;
- mTotalMilliseconds += mTextures[id]->mCompleteTime - mTextures[id]->mStartTime;
- mTextureDownloadsCompleted++;
+ add(sTextureDataDownloaded, details.mSize);
+ add(sTexureDownloadTime, details.mCompleteTime - details.mStartTime);
+ add(sTextureDownloadsCompleted, 1);
mTextureDownloadProtocol = protocol;
- if (mTotalBytes >= texture_stats_upload_threshold)
+ if (mRecording.getSum(sTextureDataDownloaded) >= mTextureLogThreshold)
{
LLSD texture_data;
std::stringstream startTime;
@@ -189,35 +193,33 @@ LLSD LLTextureInfo::getAverages()
{
LLSD averagedTextureData;
S32 averageDownloadRate;
- if(mTotalMilliseconds == 0)
+ LLUnit<U32, LLUnits::Milliseconds> download_time = mRecording.getSum(sTexureDownloadTime);
+ if(download_time == 0)
{
averageDownloadRate = 0;
}
else
{
- averageDownloadRate = (mTotalBytes * 8) / mTotalMilliseconds;
+ averageDownloadRate = mRecording.getSum(sTextureDataDownloaded).valueAs<LLUnits::Bits>() / download_time.valueAs<LLUnits::Seconds>();
}
- averagedTextureData["bits_per_second"] = averageDownloadRate;
- averagedTextureData["bytes_downloaded"] = mTotalBytes;
- averagedTextureData["texture_downloads_started"] = mTextureDownloadsStarted;
- averagedTextureData["texture_downloads_completed"] = mTextureDownloadsCompleted;
- averagedTextureData["transport"] = mTextureDownloadProtocol;
+ averagedTextureData["bits_per_second"] = averageDownloadRate;
+ averagedTextureData["bytes_downloaded"] = mRecording.getSum(sTextureDataDownloaded).valueAs<LLUnits::Bytes>();
+ averagedTextureData["texture_downloads_started"] = mRecording.getSum(sTextureDownloadsStarted);
+ averagedTextureData["texture_downloads_completed"] = mRecording.getSum(sTextureDownloadsCompleted);
+ averagedTextureData["transport"] = mTextureDownloadProtocol;
return averagedTextureData;
}
void LLTextureInfo::resetTextureStatistics()
{
- mTotalMilliseconds = 0;
- mTotalBytes = 0;
- mTextureDownloadsStarted = 0;
- mTextureDownloadsCompleted = 0;
+ mRecording.restart();
mTextureDownloadProtocol = "NONE";
mCurrentStatsBundleStartTime = LLTimer::getTotalTime();
}
-U32 LLTextureInfo::getRequestStartTime(const LLUUID& id)
+LLUnit<U32, LLUnits::Microseconds> LLTextureInfo::getRequestStartTime(const LLUUID& id)
{
if (!has(id))
{
@@ -230,7 +232,7 @@ U32 LLTextureInfo::getRequestStartTime(const LLUUID& id)
}
}
-U32 LLTextureInfo::getRequestSize(const LLUUID& id)
+LLUnit<U32, LLUnits::Bytes> LLTextureInfo::getRequestSize(const LLUUID& id)
{
if (!has(id))
{
@@ -269,7 +271,7 @@ LLTextureInfoDetails::LLRequestType LLTextureInfo::getRequestType(const LLUUID&
}
}
-U32 LLTextureInfo::getRequestCompleteTime(const LLUUID& id)
+LLUnit<U32, LLUnits::Microseconds> LLTextureInfo::getRequestCompleteTime(const LLUUID& id)
{
if (!has(id))
{
diff --git a/indra/newview/lltextureinfo.h b/indra/newview/lltextureinfo.h
index 2ccbcc5fd2..a861a12668 100755
--- a/indra/newview/lltextureinfo.h
+++ b/indra/newview/lltextureinfo.h
@@ -29,6 +29,7 @@
#include "lluuid.h"
#include "lltextureinfodetails.h"
+#include "lltracerecording.h"
#include <map>
class LLTextureInfo
@@ -37,18 +38,18 @@ public:
LLTextureInfo();
~LLTextureInfo();
- void setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold);
+ void setUpLogging(bool writeToViewerLog, bool sendToSim, LLUnit<U32, LLUnits::Bytes> textureLogThreshold);
bool has(const LLUUID& id);
void setRequestStartTime(const LLUUID& id, U64 startTime);
void setRequestSize(const LLUUID& id, U32 size);
void setRequestOffset(const LLUUID& id, U32 offset);
void setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type);
- void setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime);
- U32 getRequestStartTime(const LLUUID& id);
- U32 getRequestSize(const LLUUID& id);
+ void setRequestCompleteTimeAndLog(const LLUUID& id, LLUnit<U64, LLUnits::Microseconds> completeTime);
+ LLUnit<U32, LLUnits::Microseconds>getRequestStartTime(const LLUUID& id);
+ LLUnit<U32, LLUnits::Bytes> getRequestSize(const LLUUID& id);
U32 getRequestOffset(const LLUUID& id);
LLTextureInfoDetails::LLRequestType getRequestType(const LLUUID& id);
- U32 getRequestCompleteTime(const LLUUID& id);
+ LLUnit<U32, LLUnits::Microseconds> getRequestCompleteTime(const LLUUID& id);
void resetTextureStatistics();
U32 getTextureInfoMapSize();
LLSD getAverages();
@@ -56,19 +57,14 @@ public:
private:
void addRequest(const LLUUID& id);
- std::map<LLUUID, LLTextureInfoDetails *> mTextures;
-
- LLSD mAverages;
-
- bool mLogTextureDownloadsToViewerLog;
- bool mLogTextureDownloadsToSimulator;
- S32 mTotalBytes;
- S32 mTotalMilliseconds;
- S32 mTextureDownloadsStarted;
- S32 mTextureDownloadsCompleted;
- std::string mTextureDownloadProtocol;
- U32 mTextureLogThreshold; // in bytes
- U64 mCurrentStatsBundleStartTime;
+ std::map<LLUUID, LLTextureInfoDetails *> mTextures;
+ LLSD mAverages;
+ bool mLogTextureDownloadsToViewerLog,
+ mLogTextureDownloadsToSimulator;
+ std::string mTextureDownloadProtocol;
+ LLUnit<U32, LLUnits::Bytes> mTextureLogThreshold;
+ LLUnit<U64, LLUnits::Microseconds> mCurrentStatsBundleStartTime;
+ LLTrace::Recording mRecording;
};
#endif // LL_LLTEXTUREINFO_H
diff --git a/indra/newview/lltextureinfodetails.cpp b/indra/newview/lltextureinfodetails.cpp
index 0d750db3bf..cab16eb922 100755
--- a/indra/newview/lltextureinfodetails.cpp
+++ b/indra/newview/lltextureinfodetails.cpp
@@ -28,7 +28,9 @@
#include "lltextureinfodetails.h"
-LLTextureInfoDetails::LLTextureInfoDetails() : mStartTime(0), mCompleteTime(0), mSize(0), mType(REQUEST_TYPE_NONE), mOffset(0)
+LLTextureInfoDetails::LLTextureInfoDetails()
+: mType(REQUEST_TYPE_NONE),
+ mOffset(0)
{
}
diff --git a/indra/newview/lltextureinfodetails.h b/indra/newview/lltextureinfodetails.h
index 4a3cd29084..28e957a7df 100755
--- a/indra/newview/lltextureinfodetails.h
+++ b/indra/newview/lltextureinfodetails.h
@@ -28,10 +28,10 @@
#define LL_LLTEXTUREINFODETAILS_H
#include "lluuid.h"
+#include "llunit.h"
-class LLTextureInfoDetails
+struct LLTextureInfoDetails
{
-public:
enum LLRequestType
{
REQUEST_TYPE_NONE,
@@ -39,11 +39,11 @@ public:
REQUEST_TYPE_UDP
};
- U32 mStartTime;
- U32 mCompleteTime;
- U32 mOffset;
- U32 mSize;
- LLRequestType mType;
+ LLUnit<U32, LLUnits::Microseconds> mStartTime,
+ mCompleteTime;
+ U32 mOffset;
+ LLUnit<U32, LLUnits::Bytes> mSize;
+ LLRequestType mType;
LLTextureInfoDetails();
};
diff --git a/indra/newview/lltexturestats.cpp b/indra/newview/lltexturestats.cpp
index f820ae65df..52fe78abf3 100755
--- a/indra/newview/lltexturestats.cpp
+++ b/indra/newview/lltexturestats.cpp
@@ -48,8 +48,7 @@ void send_texture_stats_to_sim(const LLSD &texture_stats)
texture_stats_report["stats_data"] = texture_stats;
std::string texture_cap_url = gAgent.getRegion()->getCapability("TextureStats");
- LLTextureStatsUploader tsu;
llinfos << "uploading texture stats data to simulator" << llendl;
- tsu.uploadStatsToSimulator(texture_cap_url, texture_stats);
+ LLTextureStatsUploader::uploadStatsToSimulator(texture_cap_url, texture_stats);
}
diff --git a/indra/newview/lltexturestatsuploader.cpp b/indra/newview/lltexturestatsuploader.cpp
index 23ba09cb91..92ec63a113 100755
--- a/indra/newview/lltexturestatsuploader.cpp
+++ b/indra/newview/lltexturestatsuploader.cpp
@@ -30,14 +30,8 @@
#include "llhttpclient.h"
-LLTextureStatsUploader::LLTextureStatsUploader()
-{
-}
-
-LLTextureStatsUploader::~LLTextureStatsUploader()
-{
-}
+// static
void LLTextureStatsUploader::uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats)
{
if ( texture_cap_url != "" )
diff --git a/indra/newview/lltexturestatsuploader.h b/indra/newview/lltexturestatsuploader.h
index 6b02aeb845..ac268c2516 100755
--- a/indra/newview/lltexturestatsuploader.h
+++ b/indra/newview/lltexturestatsuploader.h
@@ -34,9 +34,7 @@
class LLTextureStatsUploader
{
public:
- LLTextureStatsUploader();
- ~LLTextureStatsUploader();
- void uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats);
+ static void uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats);
};
#endif // LL_LLTEXTURESTATSUPLOADER_H
diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
index 6ab2aefc34..80412c215f 100755
--- a/indra/newview/llviewerassetstats.cpp
+++ b/indra/newview/llviewerassetstats.cpp
@@ -314,9 +314,9 @@ void LLViewerAssetStats::handleStop()
}
void LLViewerAssetStats::handleReset()
- {
+{
reset();
- }
+}
void LLViewerAssetStats::reset()
@@ -328,6 +328,7 @@ void LLViewerAssetStats::reset()
if (mRegionHandle)
{
mCurRecording = &mRegionRecordings[mRegionHandle];
+ mCurRecording->setPlayState(getPlayState());
}
}
@@ -346,7 +347,7 @@ void LLViewerAssetStats::setRegion(region_handle_t region_handle)
if (region_handle)
{
mCurRecording = &mRegionRecordings[region_handle];
- mCurRecording->start();
+ mCurRecording->setPlayState(getPlayState());
}
mRegionHandle = region_handle;
@@ -493,19 +494,19 @@ void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output)
}
LLSD LLViewerAssetStats::asLLSD(bool compact_output)
- {
+{
LLParamSDParser parser;
LLSD sd;
AssetStats stats;
getStats(stats, compact_output);
LLInitParam::predicate_rule_t rule = LLInitParam::default_parse_rules();
if (!compact_output)
- {
+ {
rule.allow(LLInitParam::EMPTY);
- }
+ }
parser.writeSD(sd, stats, rule);
return sd;
- }
+}
// ------------------------------------------------------
// Global free-function definitions (LLViewerAssetStatsFF namespace)
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index ebc4f09edb..57a0195d23 100755
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -155,7 +155,7 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
setOriginAndLookAt(origin, up_direction, point_of_interest);
- mVelocityDir = center - last_position ;
+ mVelocityDir = origin - last_position ;
F32 dpos = mVelocityDir.normVec() ;
LLQuaternion rotation;
rotation.shortestArc(last_axis, getAtAxis());
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 1de8493749..ee5793fe6a 100755
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -106,6 +106,7 @@ LLFrameTimer gRecentMemoryTime;
void pre_show_depth_buffer();
void post_show_depth_buffer();
void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
+void swap();
void render_hud_attachments();
void render_ui_3d();
void render_ui_2d();
@@ -344,7 +345,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
// Bail out if we're in the startup state and don't want to try to
// render the world.
//
- if (LLStartUp::getStartupState() < STATE_STARTED)
+ if (LLStartUp::getStartupState() < STATE_WEARABLES_WAIT)
{
LLAppViewer::instance()->pingMainloopTimeout("Display:Startup");
display_startup();
@@ -553,6 +554,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
{
LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
render_ui();
+ swap();
}
//////////////////////////
@@ -1021,6 +1023,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
{
LLFastTimer t(FTM_RENDER_UI);
render_ui();
+ swap();
}
@@ -1244,8 +1247,6 @@ BOOL setup_hud_matrices(const LLRect& screen_region)
return TRUE;
}
-static LLFastTimer::DeclareTimer FTM_SWAP("Swap");
-
void render_ui(F32 zoom_factor, int subfield)
{
LLGLState::checkStates();
@@ -1322,10 +1323,16 @@ void render_ui(F32 zoom_factor, int subfield)
glh_set_current_modelview(saved_view);
gGL.popMatrix();
}
+}
+
+static LLFastTimer::DeclareTimer FTM_SWAP("Swap");
+
+void swap()
+{
+ LLFastTimer t(FTM_SWAP);
if (gDisplaySwapBuffers)
{
- LLFastTimer t(FTM_SWAP);
gViewerWindow->getWindow()->swapBuffers();
}
gDisplaySwapBuffers = TRUE;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 3d4c75cec3..244c150b29 100755
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -291,9 +291,9 @@ F32 gAveLandCompression = 0.f,
gWorstWaterCompression = 0.f;
LLUnit<U32, LLUnits::Bytes> gTotalWorldData = 0,
- gTotalObjectData = 0,
- gTotalTextureData = 0;
-U32 gSimPingCount = 0;
+ gTotalObjectData = 0,
+ gTotalTextureData = 0;
+U32 gSimPingCount = 0;
LLUnit<U32, LLUnits::Bits> gObjectData = 0;
F32 gAvgSimPing = 0.f;
LLUnit<U32, LLUnits::Bytes> gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0};
@@ -353,7 +353,7 @@ void update_statistics()
}
else
{
- sample(LLStatViewer::SIM_PING, LLUnit<F64, LLUnits::Seconds>(10));
+ sample(LLStatViewer::SIM_PING, LLUnits::Seconds::fromValue(10));
}
if (LLViewerStats::instance().getRecording().getSum(LLStatViewer::FPS))
@@ -403,7 +403,7 @@ void update_statistics()
static LLFrameTimer texture_stats_timer;
if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
{
- gTotalTextureData = LLUnit<F64, LLUnits::Bytes>(LLViewerStats::instance().getRecording().getSum(LLStatViewer::TEXTURE_KBIT));
+ gTotalTextureData = LLViewerStats::instance().getRecording().getSum(LLStatViewer::TEXTURE_KBIT);
texture_stats_timer.reset();
}
}
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index f077ae1fe1..0248298eb5 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -35,7 +35,6 @@
//---------------------------------------------------------------------------
// Cache entries
-class LLVOCacheEntry;
class LLCamera;
class LLVOCacheEntry : public LLViewerOctreeEntryData
diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp
index b9712e5e9c..bd42b59df2 100755
--- a/indra/newview/tests/llviewerassetstats_test.cpp
+++ b/indra/newview/tests/llviewerassetstats_test.cpp
@@ -35,6 +35,7 @@
#include "lluuid.h"
#include "llsdutil.h"
#include "llregionhandle.h"
+#include "lltracethreadrecorder.h"
#include "../llvoavatar.h"
namespace LLStatViewer
@@ -231,14 +232,15 @@ namespace tut
{
tst_viewerassetstats_index()
{
- LLTrace::init();
+ LLTrace::set_master_thread_recorder(&mThreadRecorder);
}
~tst_viewerassetstats_index()
{
- LLTrace::cleanup();
+ LLTrace::set_master_thread_recorder(NULL);
}
+ LLTrace::ThreadRecorder mThreadRecorder;
};
typedef test_group<tst_viewerassetstats_index> tst_viewerassetstats_index_t;
typedef tst_viewerassetstats_index_t::object tst_viewerassetstats_index_object_t;
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 28de88201c..10f71a2843 100755
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -41,6 +41,7 @@
#include "stringize.h"
#include "namedtempfile.h"
#include "lltrace.h"
+#include "lltracethreadrecorder.h"
#include "apr_pools.h"
#include "apr_getopt.h"
@@ -483,6 +484,8 @@ void wouldHaveCrashed(const std::string& message)
tut::fail("llerrs message: " + message);
}
+static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
+
int main(int argc, char **argv)
{
// The following line must be executed to initialize Google Mock
@@ -515,7 +518,11 @@ int main(int argc, char **argv)
ll_init_apr();
- LLTrace::init();
+ if (!sMasterThreadRecorder)
+ {
+ sMasterThreadRecorder = new LLTrace::ThreadRecorder();
+ LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
+ }
apr_getopt_t* os = NULL;
if(APR_SUCCESS != apr_getopt_init(&os, gAPRPoolp, argc, argv))
{