SH-3931 WIP Interesting: Add graphs to visualize scene load metrics

added ExtendablePeriodicRecording
and ability to append periodic recordings to each other
meow-7.2.2
Richard Linden 2013-04-21 23:10:03 -07:00
parent cc7d92147c
commit 62c8844414
3 changed files with 170 additions and 4 deletions

View File

@ -67,6 +67,7 @@ protected:
/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
/// If KEY is not provided, then instances are stored in a simple set
/// @NOTE: see explicit specialization below for default KEY==void case
/// @NOTE: this class is not thread-safe unless used as read-only
template<typename T, typename KEY = void>
class LLInstanceTracker : public LLInstanceTrackerBase
{
@ -120,13 +121,13 @@ public:
typedef boost::iterator_facade<key_iter, KEY, boost::forward_traversal_tag> super_t;
key_iter(typename InstanceMap::iterator it)
: mIterator(it)
: mIterator(it)
{
getStatic().incrementDepth();
}
key_iter(const key_iter& other)
: mIterator(other.mIterator)
: mIterator(other.mIterator)
{
getStatic().incrementDepth();
}
@ -171,7 +172,10 @@ public:
return instance_iter(getMap_().end());
}
static S32 instanceCount() { return getMap_().size(); }
static S32 instanceCount()
{
return getMap_().size();
}
static key_iter beginKeys()
{

View File

@ -396,6 +396,76 @@ void PeriodicRecording::nextPeriod()
}
}
void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
{
if (other.mRecordingPeriods.size() < 2) return;
EPlayState play_state = getPlayState();
pause();
EPlayState other_play_state = other.getPlayState();
other.pause();
if (mAutoResize)
{
// copy everything after current period of other recording to end of buffer
// this will only apply if other recording is using a fixed circular buffer
if (other.mCurPeriod < other.mRecordingPeriods.size() - 1)
{
std::copy( other.mRecordingPeriods.begin() + other.mCurPeriod + 1,
other.mRecordingPeriods.end(),
std::back_inserter(mRecordingPeriods));
}
// copy everything from beginning of other recording's buffer up to, but not including
// current period
std::copy( other.mRecordingPeriods.begin(),
other.mRecordingPeriods.begin() + other.mCurPeriod,
std::back_inserter(mRecordingPeriods));
mCurPeriod = mRecordingPeriods.size() - 1;
}
else
{
size_t num_to_copy = llmin( mRecordingPeriods.size(), other.mRecordingPeriods.size() );
std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin()
+ ( (other.mCurPeriod + 1) // cur period
+ (other.mRecordingPeriods.size() - num_to_copy) // minus room for copy
% other.mRecordingPeriods.size());
std::vector<Recording>::iterator dest_it = mRecordingPeriods.begin() + ((mCurPeriod + 1) % mRecordingPeriods.size());
for(S32 i = 0; i < num_to_copy; i++)
{
*dest_it = *src_it;
if (++src_it == other.mRecordingPeriods.end())
{
src_it = other.mRecordingPeriods.begin();
}
if (++dest_it == mRecordingPeriods.end())
{
dest_it = mRecordingPeriods.begin();
}
}
mCurPeriod = (mCurPeriod + num_to_copy) % mRecordingPeriods.size();
}
// if copying from periodic recording that wasn't active advance our period to the next available one
// otherwise continue recording on top of the last period of data received from the other recording
if (other_play_state != STARTED)
{
nextPeriod();
}
setPlayState(play_state);
other.setPlayState(other_play_state);
}
void PeriodicRecording::start()
{
getCurRecording().start();
@ -503,6 +573,72 @@ void ExtendableRecording::splitFrom(ExtendableRecording& other)
mPotentialRecording.splitFrom(other.mPotentialRecording);
}
///////////////////////////////////////////////////////////////////////
// ExtendablePeriodicRecording
///////////////////////////////////////////////////////////////////////
void ExtendablePeriodicRecording::extend()
{
// stop recording to get latest data
mPotentialRecording.stop();
// push the data back to accepted recording
mAcceptedRecording.appendPeriodicRecording(mPotentialRecording);
// flush data, so we can start from scratch
mPotentialRecording.reset();
// go back to play state we were in initially
mPotentialRecording.setPlayState(getPlayState());
}
void ExtendablePeriodicRecording::start()
{
LLStopWatchControlsMixin<ExtendablePeriodicRecording>::start();
mPotentialRecording.start();
}
void ExtendablePeriodicRecording::stop()
{
LLStopWatchControlsMixin<ExtendablePeriodicRecording>::stop();
mPotentialRecording.stop();
}
void ExtendablePeriodicRecording::pause()
{
LLStopWatchControlsMixin<ExtendablePeriodicRecording>::pause();
mPotentialRecording.pause();
}
void ExtendablePeriodicRecording::resume()
{
LLStopWatchControlsMixin<ExtendablePeriodicRecording>::resume();
mPotentialRecording.resume();
}
void ExtendablePeriodicRecording::restart()
{
LLStopWatchControlsMixin<ExtendablePeriodicRecording>::restart();
mAcceptedRecording.reset();
mPotentialRecording.restart();
}
void ExtendablePeriodicRecording::reset()
{
LLStopWatchControlsMixin<ExtendablePeriodicRecording>::reset();
mAcceptedRecording.reset();
mPotentialRecording.reset();
}
void ExtendablePeriodicRecording::splitTo(ExtendablePeriodicRecording& other)
{
LLStopWatchControlsMixin<ExtendablePeriodicRecording>::splitTo(other);
mPotentialRecording.splitTo(other.mPotentialRecording);
}
void ExtendablePeriodicRecording::splitFrom(ExtendablePeriodicRecording& other)
{
LLStopWatchControlsMixin<ExtendablePeriodicRecording>::splitFrom(other);
mPotentialRecording.splitFrom(other.mPotentialRecording);
}
PeriodicRecording& get_frame_recording()
{
static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(1000, PeriodicRecording::STARTED));

View File

@ -254,6 +254,8 @@ namespace LLTrace
void nextPeriod();
U32 getNumPeriods() { return mRecordingPeriods.size(); }
void appendPeriodicRecording(PeriodicRecording& other);
Recording& getLastRecording()
{
U32 num_periods = mRecordingPeriods.size();
@ -424,6 +426,7 @@ namespace LLTrace
void extend();
Recording& getAcceptedRecording() { return mAcceptedRecording; }
const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
// implementation for LLStopWatchControlsMixin
/*virtual*/ void start();
@ -435,11 +438,34 @@ namespace LLTrace
/*virtual*/ void splitTo(ExtendableRecording& other);
/*virtual*/ void splitFrom(ExtendableRecording& other);
const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
private:
Recording mAcceptedRecording;
Recording mPotentialRecording;
};
class ExtendablePeriodicRecording
: public LLStopWatchControlsMixin<ExtendablePeriodicRecording>
{
public:
void extend();
PeriodicRecording& getAcceptedRecording() { return mAcceptedRecording; }
const PeriodicRecording& getAcceptedRecording() const {return mAcceptedRecording;}
// implementation for LLStopWatchControlsMixin
/*virtual*/ void start();
/*virtual*/ void stop();
/*virtual*/ void pause();
/*virtual*/ void resume();
/*virtual*/ void restart();
/*virtual*/ void reset();
/*virtual*/ void splitTo(ExtendablePeriodicRecording& other);
/*virtual*/ void splitFrom(ExtendablePeriodicRecording& other);
private:
PeriodicRecording mAcceptedRecording;
PeriodicRecording mPotentialRecording;
};
}
#endif // LL_LLTRACERECORDING_H