diff options
Diffstat (limited to 'indra/llcommon/lltracethreadrecorder.cpp')
-rw-r--r-- | indra/llcommon/lltracethreadrecorder.cpp | 132 |
1 files changed, 102 insertions, 30 deletions
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index 02dc55771b..7b493a651e 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -26,6 +26,7 @@ #include "linden_common.h" #include "lltracethreadrecorder.h" +#include "llfasttimer.h" namespace LLTrace { @@ -37,22 +38,60 @@ namespace LLTrace ThreadRecorder::ThreadRecorder() { - get_thread_recorder() = this; - mFullRecording.start(); + //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(); + timer_stack->mTimeBlock = &root_time_block; + timer_stack->mActiveTimer = NULL; + + mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size(); + mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes]; + + mThreadRecording.start(); + + // initialize time block parent pointers + for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); + it != end_it; + ++it) + { + TimeBlock& time_block = *it; + TimeBlockTreeNode& tree_node = mTimeBlockTreeNodes[it->getIndex()]; + tree_node.mBlock = &time_block; + tree_node.mParent = &root_time_block; + + it->getPrimaryAccumulator()->mParent = &root_time_block; + } + + mRootTimer = new BlockTimer(root_time_block); + timer_stack->mActiveTimer = mRootTimer; + + TimeBlock::getRootTimeBlock().getPrimaryAccumulator()->mActiveCount = 1; } -ThreadRecorder::ThreadRecorder( const ThreadRecorder& other ) -: mFullRecording(other.mFullRecording) +ThreadRecorder::~ThreadRecorder() { - get_thread_recorder() = this; - mFullRecording.start(); + delete mRootTimer; + + while(mActiveRecordings.size()) + { + mActiveRecordings.front().mTargetRecording->stop(); + } + set_thread_recorder(NULL); + delete[] mTimeBlockTreeNodes; } -ThreadRecorder::~ThreadRecorder() +TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode(S32 index) { - get_thread_recorder() = NULL; + if (0 <= index && index < mNumTimeBlockTreeNodes) + { + return &mTimeBlockTreeNodes[index]; + } + return NULL; } + void ThreadRecorder::activate( Recording* recording ) { mActiveRecordings.push_front(ActiveRecording(recording)); @@ -73,7 +112,7 @@ std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Rec if (next_it != mActiveRecordings.end()) { // ...push our gathered data down to it - next_it->mBaseline.mergeRecording(it->mBaseline); + next_it->mBaseline.appendRecording(it->mBaseline); } // copy accumulated measurements into result buffer and clear accumulator (mBaseline) @@ -86,9 +125,21 @@ std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Rec } } + if (it == end_it) + { + llwarns << "Recording not active on this thread" << llendl; + } + return it; } +AccumulatorBuffer<CountAccumulator<F64> > gCountsFloat; +AccumulatorBuffer<MeasurementAccumulator<F64> > gMeasurementsFloat; +AccumulatorBuffer<CountAccumulator<S64> > gCounts; +AccumulatorBuffer<MeasurementAccumulator<S64> > gMeasurements; +AccumulatorBuffer<TimeBlockAccumulator> gStackTimers; +AccumulatorBuffer<MemStatAccumulator> gMemStats; + void ThreadRecorder::deactivate( Recording* recording ) { std::list<ActiveRecording>::iterator it = update(recording); @@ -113,9 +164,13 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target ) void ThreadRecorder::ActiveRecording::moveBaselineToTarget() { + mTargetRecording->mMeasurementsFloat.write()->addSamples(*mBaseline.mMeasurementsFloat); + mTargetRecording->mCountsFloat.write()->addSamples(*mBaseline.mCountsFloat); mTargetRecording->mMeasurements.write()->addSamples(*mBaseline.mMeasurements); mTargetRecording->mCounts.write()->addSamples(*mBaseline.mCounts); mTargetRecording->mStackTimers.write()->addSamples(*mBaseline.mStackTimers); + mBaseline.mMeasurementsFloat.write()->reset(); + mBaseline.mCountsFloat.write()->reset(); mBaseline.mMeasurements.write()->reset(); mBaseline.mCounts.write()->reset(); mBaseline.mStackTimers.write()->reset(); @@ -127,7 +182,6 @@ void ThreadRecorder::ActiveRecording::moveBaselineToTarget() /////////////////////////////////////////////////////////////////////// SlaveThreadRecorder::SlaveThreadRecorder() -: ThreadRecorder(getMasterThreadRecorder()) { getMasterThreadRecorder().addSlaveThread(this); } @@ -139,39 +193,65 @@ SlaveThreadRecorder::~SlaveThreadRecorder() void SlaveThreadRecorder::pushToMaster() { - mFullRecording.stop(); + mThreadRecording.stop(); { LLMutexLock(getMasterThreadRecorder().getSlaveListMutex()); - mSharedData.copyFrom(mFullRecording); + mSharedData.appendFrom(mThreadRecording); } - mFullRecording.start(); + mThreadRecording.start(); +} + +void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source ) +{ + LLMutexLock lock(&mRecordingMutex); + mRecording.appendRecording(source); } -void SlaveThreadRecorder::SharedData::copyFrom( const Recording& source ) +void SlaveThreadRecorder::SharedData::appendTo( Recording& sink ) { - LLMutexLock lock(&mRecorderMutex); - mRecorder.mergeRecording(source); + LLMutexLock lock(&mRecordingMutex); + sink.appendRecording(mRecording); } -void SlaveThreadRecorder::SharedData::copyTo( Recording& sink ) +void SlaveThreadRecorder::SharedData::mergeFrom( const Recording& source ) { - LLMutexLock lock(&mRecorderMutex); - sink.mergeRecording(mRecorder); + LLMutexLock lock(&mRecordingMutex); + mRecording.mergeRecording(source); } +void SlaveThreadRecorder::SharedData::mergeTo( Recording& sink ) +{ + LLMutexLock lock(&mRecordingMutex); + sink.mergeRecording(mRecording); +} + +void SlaveThreadRecorder::SharedData::reset() +{ + LLMutexLock lock(&mRecordingMutex); + mRecording.reset(); +} + + /////////////////////////////////////////////////////////////////////// // MasterThreadRecorder /////////////////////////////////////////////////////////////////////// +LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_SLAVES("Pull slave trace data"); void MasterThreadRecorder::pullFromSlaveThreads() { + LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_SLAVES); + if (mActiveRecordings.empty()) return; + LLMutexLock lock(&mSlaveListMutex); + Recording& target_recording = mActiveRecordings.front().mBaseline; for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end(); it != end_it; ++it) { - (*it)->mRecorder->mSharedData.copyTo((*it)->mSlaveRecording); + // ignore block timing info for now + (*it)->mSharedData.mergeTo(target_recording); + (*it)->mSharedData.reset(); } } @@ -179,7 +259,7 @@ void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child ) { LLMutexLock lock(&mSlaveListMutex); - mSlaveThreadRecorders.push_back(new SlaveThreadRecorderProxy(child)); + mSlaveThreadRecorders.push_back(child); } void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child ) @@ -190,7 +270,7 @@ void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child ) it != end_it; ++it) { - if ((*it)->mRecorder == child) + if ((*it) == child) { mSlaveThreadRecorders.erase(it); break; @@ -204,12 +284,4 @@ void MasterThreadRecorder::pushToMaster() MasterThreadRecorder::MasterThreadRecorder() {} -/////////////////////////////////////////////////////////////////////// -// MasterThreadRecorder::SlaveThreadTraceProxy -/////////////////////////////////////////////////////////////////////// - -MasterThreadRecorder::SlaveThreadRecorderProxy::SlaveThreadRecorderProxy( class SlaveThreadRecorder* recorder) -: mRecorder(recorder) -{} - } |