summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/llapr.h2
-rw-r--r--indra/llcommon/lltrace.cpp112
-rw-r--r--indra/llcommon/lltrace.h127
-rw-r--r--indra/llcommon/lltracesampler.cpp103
-rw-r--r--indra/llcommon/lltracesampler.h91
6 files changed, 275 insertions, 162 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index f78751601c..e10dbb3e4d 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -101,6 +101,7 @@ set(llcommon_SOURCE_FILES
llthreadsafequeue.cpp
lltimer.cpp
lltrace.cpp
+ lltracesampler.cpp
lluri.cpp
lluuid.cpp
llworkerthread.cpp
@@ -243,6 +244,7 @@ set(llcommon_HEADER_FILES
llthreadsafequeue.h
lltimer.h
lltrace.h
+ lltracesampler.h
lltreeiterators.h
lltypeinfolookup.h
lluri.h
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 830e0a33fa..4e704998c2 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -39,6 +39,8 @@
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
+ #undef min
+ #undef max
#endif
#include <boost/noncopyable.hpp>
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 2da4363b1d..e487e450a9 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -26,6 +26,7 @@
#include "linden_common.h"
#include "lltrace.h"
+#include "lltracesampler.h"
#include "llthread.h"
namespace LLTrace
@@ -56,77 +57,6 @@ MasterThreadTrace& getMasterThreadTrace()
}
///////////////////////////////////////////////////////////////////////
-// Sampler
-///////////////////////////////////////////////////////////////////////
-
-Sampler::Sampler(ThreadTrace* thread_trace)
-: mElapsedSeconds(0),
- mIsStarted(false),
- mThreadTrace(thread_trace)
-{
-}
-
-Sampler::~Sampler()
-{
-}
-
-void Sampler::start()
-{
- reset();
- resume();
-}
-
-void Sampler::reset()
-{
- mF32Stats.reset();
- mS32Stats.reset();
- mStackTimers.reset();
-
- mElapsedSeconds = 0.0;
- mSamplingTimer.reset();
-}
-
-void Sampler::resume()
-{
- if (!mIsStarted)
- {
- mSamplingTimer.reset();
- getThreadTrace()->activate(this);
- mIsStarted = true;
- }
-}
-
-void Sampler::stop()
-{
- if (mIsStarted)
- {
- mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
- getThreadTrace()->deactivate(this);
- mIsStarted = false;
- }
-}
-
-ThreadTrace* Sampler::getThreadTrace()
-{
- return mThreadTrace;
-}
-
-void Sampler::makePrimary()
-{
- mF32Stats.makePrimary();
- mS32Stats.makePrimary();
- mStackTimers.makePrimary();
-}
-
-void Sampler::mergeFrom( const Sampler* other )
-{
- mF32Stats.mergeFrom(other->mF32Stats);
- mS32Stats.mergeFrom(other->mS32Stats);
- mStackTimers.mergeFrom(other->mStackTimers);
-}
-
-
-///////////////////////////////////////////////////////////////////////
// MasterThreadTrace
///////////////////////////////////////////////////////////////////////
@@ -148,6 +78,11 @@ ThreadTrace::~ThreadTrace()
delete mPrimarySampler;
}
+Sampler* ThreadTrace::getPrimarySampler()
+{
+ return mPrimarySampler;
+}
+
void ThreadTrace::activate( Sampler* sampler )
{
flushPrimary();
@@ -205,6 +140,34 @@ void SlaveThreadTrace::pushToMaster()
mSharedData.copyFrom(mPrimarySampler);
}
+void SlaveThreadTrace::SharedData::copyFrom( Sampler* source )
+{
+ LLMutexLock lock(&mSamplerMutex);
+ {
+ mSampler->mergeFrom(source);
+ }
+}
+
+void SlaveThreadTrace::SharedData::copyTo( Sampler* sink )
+{
+ LLMutexLock lock(&mSamplerMutex);
+ {
+ sink->mergeFrom(mSampler);
+ }
+}
+
+SlaveThreadTrace::SharedData::~SharedData()
+{
+ delete mSampler;
+}
+
+SlaveThreadTrace::SharedData::SharedData( Sampler* sampler ) : mSampler(sampler)
+{}
+
+
+
+
+
///////////////////////////////////////////////////////////////////////
// MasterThreadTrace
///////////////////////////////////////////////////////////////////////
@@ -217,7 +180,7 @@ void MasterThreadTrace::pullFromSlaveThreads()
it != end_it;
++it)
{
- it->mSlaveTrace->mSharedData.copyTo(it->mSamplerStorage);
+ (*it)->mSlaveTrace->mSharedData.copyTo((*it)->mSamplerStorage);
}
}
@@ -225,7 +188,7 @@ void MasterThreadTrace::addSlaveThread( class SlaveThreadTrace* child )
{
LLMutexLock lock(&mSlaveListMutex);
- mSlaveThreadTraces.push_back(SlaveThreadTraceProxy(child, createSampler()));
+ mSlaveThreadTraces.push_back(new SlaveThreadTraceProxy(child, createSampler()));
}
void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
@@ -236,7 +199,7 @@ void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
it != end_it;
++it)
{
- if (it->mSlaveTrace == child)
+ if ((*it)->mSlaveTrace == child)
{
mSlaveThreadTraces.erase(it);
break;
@@ -266,5 +229,4 @@ MasterThreadTrace::SlaveThreadTraceProxy::~SlaveThreadTraceProxy()
delete mSamplerStorage;
}
-
}
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index a443735e69..c6f920b5e4 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -43,14 +43,16 @@
namespace LLTrace
{
+ class Sampler;
+
void init();
void cleanup();
- class MasterThreadTrace& getMasterThreadTrace();
+ class LL_COMMON_API MasterThreadTrace& getMasterThreadTrace();
// one per thread per type
template<typename ACCUMULATOR>
- class AccumulatorBuffer
+ class LL_COMMON_API AccumulatorBuffer
{
static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
private:
@@ -64,6 +66,8 @@ namespace LLTrace
public:
+ // copying an accumulator buffer does not copy the actual contents, but simply initializes the buffer size
+ // to be identical to the other buffer
AccumulatorBuffer(const AccumulatorBuffer& other = getDefaultBuffer())
: mStorageSize(other.mStorageSize),
mStorage(new ACCUMULATOR[other.mStorageSize]),
@@ -150,28 +154,30 @@ namespace LLTrace
template<typename ACCUMULATOR> LLThreadLocalPtr<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
template<typename ACCUMULATOR>
- class Trace
+ class LL_COMMON_API TraceType
{
public:
- Trace(const std::string& name)
+ TraceType(const std::string& name)
: mName(name)
{
mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot();
}
- LL_FORCE_INLINE ACCUMULATOR& getAccumulator()
+ LL_FORCE_INLINE ACCUMULATOR& getPrimaryAccumulator()
{
return AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage()[mAccumulatorIndex];
}
- private:
+ ACCUMULATOR& getAccumulator(AccumulatorBuffer<ACCUMULATOR>& buffer) { return buffer[mAccumulatorIndex]; }
+
+ protected:
std::string mName;
size_t mAccumulatorIndex;
};
template<typename T>
- class StatAccumulator
+ class LL_COMMON_API StatAccumulator
{
public:
StatAccumulator()
@@ -217,6 +223,11 @@ namespace LLTrace
mMax = 0;
}
+ T getSum() { return mSum; }
+ T getMin() { return mMin; }
+ T getMax() { return mMax; }
+ T getMean() { return mSum / (T)mNumSamples; }
+
private:
T mSum,
mMin,
@@ -226,20 +237,23 @@ namespace LLTrace
};
template <typename T>
- class Stat : public Trace<StatAccumulator<T> >
+ class LL_COMMON_API Stat
+ : public TraceType<StatAccumulator<T> >,
+ public LLInstanceTracker<Stat<T>, std::string>
{
public:
Stat(const std::string& name)
- : Trace(name)
+ : TraceType(name),
+ LLInstanceTracker(name)
{}
void sample(T value)
{
- getAccumulator().sample(value);
+ getPrimaryAccumulator().sample(value);
}
};
- struct TimerAccumulator
+ struct LL_COMMON_API TimerAccumulator
{
U32 mTotalTimeCounter,
mChildTimeCounter,
@@ -267,11 +281,11 @@ namespace LLTrace
};
- class BlockTimer : public Trace<TimerAccumulator>
+ class LL_COMMON_API BlockTimer : public TraceType<TimerAccumulator>
{
public:
BlockTimer(const char* name)
- : Trace(name)
+ : TraceType(name)
{}
struct Recorder
@@ -287,7 +301,7 @@ namespace LLTrace
: mLastRecorder(sCurRecorder)
{
mStartTime = getCPUClockCount32();
- TimerAccumulator* accumulator = &block_timer.getAccumulator(); // get per-thread accumulator
+ TimerAccumulator* accumulator = &block_timer.getPrimaryAccumulator(); // get per-thread accumulator
accumulator->mActiveCount++;
accumulator->mCalls++;
accumulator->mMoveUpTree |= (accumulator->mParent->mActiveCount == 0);
@@ -353,44 +367,7 @@ namespace LLTrace
static Recorder::StackEntry sCurRecorder;
};
- class Sampler
- {
- public:
- ~Sampler();
-
- void makePrimary();
-
- void start();
- void stop();
- void resume();
-
- void mergeFrom(const Sampler* other);
-
- void reset();
-
- bool isStarted() { return mIsStarted; }
-
- private:
- friend class ThreadTrace;
- Sampler(class ThreadTrace* thread_trace);
-
- // no copy
- Sampler(const Sampler& other) {}
- // returns data for current thread
- class ThreadTrace* getThreadTrace();
-
- AccumulatorBuffer<StatAccumulator<F32> > mF32Stats;
- AccumulatorBuffer<StatAccumulator<S32> > mS32Stats;
-
- AccumulatorBuffer<TimerAccumulator> mStackTimers;
-
- bool mIsStarted;
- LLTimer mSamplingTimer;
- F64 mElapsedSeconds;
- ThreadTrace* mThreadTrace;
- };
-
- class ThreadTrace
+ class LL_COMMON_API ThreadTrace
{
public:
ThreadTrace();
@@ -406,13 +383,13 @@ namespace LLTrace
virtual void pushToMaster() = 0;
- Sampler* getPrimarySampler() { return mPrimarySampler; }
+ Sampler* getPrimarySampler();
protected:
Sampler* mPrimarySampler;
std::list<Sampler*> mActiveSamplers;
};
- class MasterThreadTrace : public ThreadTrace
+ class LL_COMMON_API MasterThreadTrace : public ThreadTrace
{
public:
MasterThreadTrace();
@@ -433,14 +410,17 @@ namespace LLTrace
~SlaveThreadTraceProxy();
class SlaveThreadTrace* mSlaveTrace;
Sampler* mSamplerStorage;
+ private:
+ //no need to copy these and then have to duplicate the storage
+ SlaveThreadTraceProxy(const SlaveThreadTraceProxy& other) {}
};
- typedef std::list<SlaveThreadTraceProxy> slave_thread_trace_list_t;
+ typedef std::list<SlaveThreadTraceProxy*> slave_thread_trace_list_t;
slave_thread_trace_list_t mSlaveThreadTraces;
LLMutex mSlaveListMutex;
};
- class SlaveThreadTrace : public ThreadTrace
+ class LL_COMMON_API SlaveThreadTrace : public ThreadTrace
{
public:
SlaveThreadTrace();
@@ -457,31 +437,12 @@ namespace LLTrace
{
public:
explicit
- SharedData(Sampler* sampler)
- : mSampler(sampler)
- {
- }
+ SharedData(Sampler* sampler);
- ~SharedData()
- {
- delete mSampler;
- }
+ ~SharedData();
- void copyFrom(Sampler* source)
- {
- LLMutexLock lock(&mSamplerMutex);
- {
- mSampler->mergeFrom(source);
- }
- }
-
- void copyTo(Sampler* sink)
- {
- LLMutexLock lock(&mSamplerMutex);
- {
- sink->mergeFrom(mSampler);
- }
- }
+ void copyFrom(Sampler* source);
+ void copyTo(Sampler* sink);
private:
// add a cache line's worth of unused space to avoid any potential of false sharing
LLMutex mSamplerMutex;
@@ -489,14 +450,6 @@ namespace LLTrace
};
SharedData mSharedData;
};
-
- class TimeInterval
- {
- public:
- void start() {}
- void stop() {}
- void resume() {}
- };
}
#endif // LL_LLTRACE_H
diff --git a/indra/llcommon/lltracesampler.cpp b/indra/llcommon/lltracesampler.cpp
new file mode 100644
index 0000000000..0cf01d7a3a
--- /dev/null
+++ b/indra/llcommon/lltracesampler.cpp
@@ -0,0 +1,103 @@
+/**
+ * @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 "lltracesampler.h"
+
+namespace LLTrace
+{
+
+///////////////////////////////////////////////////////////////////////
+// Sampler
+///////////////////////////////////////////////////////////////////////
+
+Sampler::Sampler(ThreadTrace* thread_trace)
+: mElapsedSeconds(0),
+ mIsStarted(false),
+ mThreadTrace(thread_trace)
+{
+}
+
+Sampler::~Sampler()
+{
+}
+
+void Sampler::start()
+{
+ reset();
+ resume();
+}
+
+void Sampler::reset()
+{
+ mF32Stats.reset();
+ mS32Stats.reset();
+ mStackTimers.reset();
+
+ mElapsedSeconds = 0.0;
+ mSamplingTimer.reset();
+}
+
+void Sampler::resume()
+{
+ if (!mIsStarted)
+ {
+ mSamplingTimer.reset();
+ getThreadTrace()->activate(this);
+ mIsStarted = true;
+ }
+}
+
+void Sampler::stop()
+{
+ if (mIsStarted)
+ {
+ mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+ getThreadTrace()->deactivate(this);
+ mIsStarted = false;
+ }
+}
+
+ThreadTrace* Sampler::getThreadTrace()
+{
+ return mThreadTrace;
+}
+
+void Sampler::makePrimary()
+{
+ mF32Stats.makePrimary();
+ mS32Stats.makePrimary();
+ mStackTimers.makePrimary();
+}
+
+void Sampler::mergeFrom( const Sampler* other )
+{
+ mF32Stats.mergeFrom(other->mF32Stats);
+ mS32Stats.mergeFrom(other->mS32Stats);
+ mStackTimers.mergeFrom(other->mStackTimers);
+}
+
+}
diff --git a/indra/llcommon/lltracesampler.h b/indra/llcommon/lltracesampler.h
new file mode 100644
index 0000000000..d1ca7fc9bb
--- /dev/null
+++ b/indra/llcommon/lltracesampler.h
@@ -0,0 +1,91 @@
+/**
+ * @file lltracesampler.h
+ * @brief Sampling object for collecting runtime statistics originating from lltrace.
+ *
+ * $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_LLTRACESAMPLER_H
+#define LL_LLTRACESAMPLER_H
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+
+#include "lltrace.h"
+
+namespace LLTrace
+{
+ class LL_COMMON_API Sampler
+ {
+ public:
+ ~Sampler();
+
+ void makePrimary();
+
+ void start();
+ void stop();
+ void resume();
+
+ void mergeFrom(const Sampler* other);
+
+ void reset();
+
+ bool isStarted() { return mIsStarted; }
+
+ F32 getSum(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getSum(); }
+ F32 getMin(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getMin(); }
+ F32 getMax(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getMax(); }
+ F32 getMean(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getMean(); }
+
+ S32 getSum(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getSum(); }
+ S32 getMin(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getMin(); }
+ S32 getMax(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getMax(); }
+ S32 getMean(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getMean(); }
+
+ F64 getSampleTime() { return mElapsedSeconds; }
+
+ private:
+ friend class ThreadTrace;
+ Sampler(class ThreadTrace* thread_trace);
+
+ // no copy
+ Sampler(const Sampler& other) {}
+ // returns data for current thread
+ class ThreadTrace* getThreadTrace();
+
+ //TODO: take snapshot at sampler start so we can simplify updates
+ //AccumulatorBuffer<StatAccumulator<F32> > mF32StatsStart;
+ //AccumulatorBuffer<StatAccumulator<S32> > mS32StatsStart;
+ //AccumulatorBuffer<TimerAccumulator> mStackTimersStart;
+
+ AccumulatorBuffer<StatAccumulator<F32> > mF32Stats;
+ AccumulatorBuffer<StatAccumulator<S32> > mS32Stats;
+ AccumulatorBuffer<TimerAccumulator> mStackTimers;
+
+ bool mIsStarted;
+ LLTimer mSamplingTimer;
+ F64 mElapsedSeconds;
+ ThreadTrace* mThreadTrace;
+ };
+}
+
+#endif // LL_LLTRACESAMPLER_H