summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorRichard Linden <none@none>2013-05-30 20:15:48 -0700
committerRichard Linden <none@none>2013-05-30 20:15:48 -0700
commite50e6004082223fdc0bfd78bc697d48a7f45b379 (patch)
tree2676d850955685c4a434e98d06257b65d8d508e7 /indra/llcommon
parentae6763f7fcfbe52ea1b04c25603ac2305beafb9d (diff)
SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
reverted SlaveThreadRecorder update gating moved processTimes() outside of Recording, so it is called only once per frame refined sample merge logic so that multi-threaded samples do not stomp on linear history of a stat
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llfasttimer.cpp40
-rw-r--r--indra/llcommon/lltrace.h27
-rw-r--r--indra/llcommon/lltracerecording.cpp17
-rw-r--r--indra/llcommon/lltracethreadrecorder.cpp25
-rw-r--r--indra/llcommon/lltracethreadrecorder.h9
5 files changed, 57 insertions, 61 deletions
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 5dc5fdd5be..3fdd33959d 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -180,6 +180,7 @@ TimeBlockTreeNode& TimeBlock::getTreeNode() const
static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times");
+// not thread safe, so only call on main thread
//static
void TimeBlock::processTimes()
{
@@ -195,8 +196,8 @@ void TimeBlock::processTimes()
TimeBlock& timer = *it;
if (&timer == &TimeBlock::getRootTimeBlock()) continue;
- // bootstrap tree construction by attaching to last timer to be on stack
- // when this timer was called
+ // bootstrap tree construction by attaching to last timer to be on stack
+ // when this timer was called
if (timer.getParent() == &TimeBlock::getRootTimeBlock())
{
TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
@@ -233,30 +234,30 @@ void TimeBlock::processTimes()
TimeBlockAccumulator* accumulator = timerp->getPrimaryAccumulator();
if (accumulator->mMoveUpTree)
- {
+ {
// since ancestors have already been visited, re-parenting won't affect tree traversal
- //step up tree, bringing our descendants with us
- LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
- " to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL;
- timerp->setParent(timerp->getParent()->getParent());
- accumulator->mParent = timerp->getParent();
- accumulator->mMoveUpTree = false;
-
- // don't bubble up any ancestors until descendants are done bubbling up
- // as ancestors may call this timer only on certain paths, so we want to resolve
- // child-most block locations before their parents
- it.skipAncestors();
+ //step up tree, bringing our descendants with us
+ LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
+ " to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL;
+ timerp->setParent(timerp->getParent()->getParent());
+ accumulator->mParent = timerp->getParent();
+ accumulator->mMoveUpTree = false;
+
+ // don't bubble up any ancestors until descendants are done bubbling up
+ // as ancestors may call this timer only on certain paths, so we want to resolve
+ // child-most block locations before their parents
+ it.skipAncestors();
+ }
}
}
-}
// walk up stack of active timers and accumulate current time while leaving timing structures active
BlockTimerStackRecord* stack_record = ThreadTimerStack::getInstance();
BlockTimer* cur_timer = stack_record->mActiveTimer;
TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
- // root defined by parent pointing to self
- while(cur_timer && cur_timer->mParentTimerData.mActiveTimer != cur_timer)
+ 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 - cur_timer->mBlockStartTotalTimeCounter);
@@ -413,8 +414,11 @@ TimeBlockAccumulator::TimeBlockAccumulator()
mParent(NULL)
{}
-void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
+void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, bool append )
{
+ // we can't merge two unrelated time block samples, as that will screw with the nested timings
+ // due to the call hierarchy of each thread
+ llassert(append);
mTotalTimeCounter += other.mTotalTimeCounter - other.mStartTotalTimeCounter;
mSelfTimeCounter += other.mSelfTimeCounter;
mCalls += other.mCalls;
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 00bab536ff..6dfe9e4b4e 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -121,12 +121,12 @@ public:
return mStorage[index];
}
- void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other)
+ 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]);
+ mStorage[i].addSamples(other.mStorage[i], append);
}
}
@@ -310,7 +310,7 @@ public:
mLastValue = value;
}
- void addSamples(const self_t& other)
+ void addSamples(const self_t& other, bool append)
{
if (other.mNumSamples)
{
@@ -350,7 +350,7 @@ public:
F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
mNumSamples += other.mNumSamples;
mMean = mMean * weight + other.mMean * (1.f - weight);
- mLastValue = other.mLastValue;
+ if (append) mLastValue = other.mLastValue;
}
}
@@ -434,7 +434,7 @@ public:
mHasValue = true;
}
- void addSamples(const self_t& other)
+ void addSamples(const self_t& other, bool append)
{
if (other.mTotalSamplingTime)
{
@@ -476,9 +476,12 @@ public:
mNumSamples += other.mNumSamples;
mTotalSamplingTime += other.mTotalSamplingTime;
mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
- mLastValue = other.mLastValue;
- mLastSampleTimeStamp = other.mLastSampleTimeStamp;
- mHasValue |= other.mHasValue;
+ if (append)
+ {
+ mLastValue = other.mLastValue;
+ mLastSampleTimeStamp = other.mLastSampleTimeStamp;
+ mHasValue |= other.mHasValue;
+ }
}
}
@@ -551,7 +554,7 @@ public:
mSum += value;
}
- void addSamples(const CountAccumulator<T>& other)
+ void addSamples(const CountAccumulator<T>& other, bool /*append*/)
{
mSum += other.mSum;
mNumSamples += other.mNumSamples;
@@ -596,7 +599,7 @@ public:
};
TimeBlockAccumulator();
- void addSamples(const self_t& other);
+ void addSamples(const self_t& other, bool /*append*/);
void reset(const self_t* other);
void flush() {}
@@ -716,6 +719,8 @@ void add(CountStatHandle<T>& count, VALUE_T value)
struct MemStatAccumulator
{
+ typedef MemStatAccumulator self_t;
+
MemStatAccumulator()
: mSize(0),
mChildSize(0),
@@ -723,7 +728,7 @@ struct MemStatAccumulator
mDeallocatedCount(0)
{}
- void addSamples(const MemStatAccumulator& other)
+ void addSamples(const MemStatAccumulator& other, bool /*append*/)
{
mSize += other.mSize;
mChildSize += other.mChildSize;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 86cdca3e10..3994e4f521 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -97,13 +97,15 @@ void RecordingBuffers::append( const RecordingBuffers& other )
void RecordingBuffers::merge( const RecordingBuffers& other)
{
- mCountsFloat.addSamples(other.mCountsFloat);
- mCounts.addSamples(other.mCounts);
- mSamplesFloat.addSamples(other.mSamplesFloat);
- mSamples.addSamples(other.mSamples);
- mEventsFloat.addSamples(other.mEventsFloat);
- mEvents.addSamples(other.mEvents);
- mMemStats.addSamples(other.mMemStats);
+ mCountsFloat.addSamples(other.mCountsFloat, false);
+ mCounts.addSamples(other.mCounts, false);
+ mSamplesFloat.addSamples(other.mSamplesFloat, false);
+ mSamples.addSamples(other.mSamples, false);
+ mEventsFloat.addSamples(other.mEventsFloat, 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)
@@ -190,7 +192,6 @@ void Recording::handleStop()
{
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
mBuffers.write()->flush();
- LLTrace::TimeBlock::processTimes();
LLTrace::get_thread_recorder()->deactivate(this);
}
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 89b5df1f94..75c7cb2ff1 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -202,21 +202,14 @@ SlaveThreadRecorder::~SlaveThreadRecorder()
mMasterRecorder.removeSlaveThread(this);
}
-bool SlaveThreadRecorder::pushToMaster()
+void SlaveThreadRecorder::pushToMaster()
{
- if (mPushCount != mMasterRecorder.getPullCount())
+ mThreadRecording.stop();
{
- mThreadRecording.stop();
- {
- LLMutexLock(mMasterRecorder.getSlaveListMutex());
- mSharedData.appendFrom(mThreadRecording);
- }
- mThreadRecording.start();
-
- mPushCount = mMasterRecorder.getPullCount();
- return true;
+ LLMutexLock(mMasterRecorder.getSlaveListMutex());
+ mSharedData.appendFrom(mThreadRecording);
}
- return false;
+ mThreadRecording.start();
}
void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source )
@@ -271,8 +264,6 @@ void MasterThreadRecorder::pullFromSlaveThreads()
(*it)->mSharedData.mergeTo(target_recording_buffers);
(*it)->mSharedData.reset();
}
-
- mPullCount++;
}
void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child )
@@ -298,10 +289,8 @@ void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
}
}
-bool MasterThreadRecorder::pushToMaster()
-{
- return false;
-}
+void MasterThreadRecorder::pushToMaster()
+{}
MasterThreadRecorder::MasterThreadRecorder()
{}
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index a044757e62..bf3701304f 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -49,7 +49,7 @@ namespace LLTrace
void deactivate(Recording* recording);
active_recording_list_t::reverse_iterator bringUpToDate(Recording* recording);
- virtual bool pushToMaster() = 0;
+ virtual void pushToMaster() = 0;
TimeBlockTreeNode* getTimeBlockTreeNode(S32 index);
@@ -80,14 +80,13 @@ namespace LLTrace
void addSlaveThread(class SlaveThreadRecorder* child);
void removeSlaveThread(class SlaveThreadRecorder* child);
- /*virtual */ bool pushToMaster();
+ /*virtual */ void pushToMaster();
// call this periodically to gather stats data from slave threads
void pullFromSlaveThreads();
LLMutex* getSlaveListMutex() { return &mSlaveListMutex; }
- U32 getPullCount() { return mPullCount; }
private:
@@ -95,7 +94,6 @@ namespace LLTrace
slave_thread_recorder_list_t mSlaveThreadRecorders; // list of slave thread recorders associated with this master
LLMutex mSlaveListMutex; // protects access to slave list
- LLAtomicU32 mPullCount; // number of times data has been pulled from slaves
};
class LL_COMMON_API SlaveThreadRecorder : public ThreadRecorder
@@ -105,7 +103,7 @@ namespace LLTrace
~SlaveThreadRecorder();
// call this periodically to gather stats data for master thread to consume
- /*virtual*/ bool pushToMaster();
+ /*virtual*/ void pushToMaster();
MasterThreadRecorder* mMaster;
@@ -122,7 +120,6 @@ namespace LLTrace
};
SharedData mSharedData;
MasterThreadRecorder& mMasterRecorder;
- U32 mPushCount;
};
}