summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorRichard Linden <none@none>2012-12-18 00:58:26 -0800
committerRichard Linden <none@none>2012-12-18 00:58:26 -0800
commit1f56e57008f5a50c9e75fc0b4512c483ac359a52 (patch)
tree6631b12beaf3cf64e093730e9c93df34b883472c /indra/llcommon
parent8c2e3bea71ea15b805a9e2a288744f10d195d803 (diff)
SH-3468 WIP add memory tracking base class
created memory tracking trace type instrumented a few classes with memory tracking
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/lltrace.h270
1 files changed, 266 insertions, 4 deletions
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d29d43a92c..d4fc93342d 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -424,9 +424,9 @@ namespace LLTrace
//
// members
//
- U64 mSelfTimeCounter,
- mTotalTimeCounter;
- U32 mCalls;
+ U64 mSelfTimeCounter,
+ mTotalTimeCounter;
+ U32 mCalls;
};
@@ -509,6 +509,268 @@ namespace LLTrace
trace_t::getPrimaryAccumulator().add(LLUnits::rawValue(converted_value));
}
};
-}
+struct MemStatAccumulator
+{
+ MemStatAccumulator()
+ : mSize(0),
+ mChildSize(0),
+ mAllocatedCount(0),
+ mDeallocatedCount(0)
+ {}
+
+ void addSamples(const MemStatAccumulator& other)
+ {
+ mSize += other.mSize;
+ mChildSize += other.mChildSize;
+ mAllocatedCount += other.mAllocatedCount;
+ mDeallocatedCount += other.mDeallocatedCount;
+ }
+
+ void reset(const MemStatAccumulator* other)
+ {
+ mSize = 0;
+ mChildSize = 0;
+ mAllocatedCount = 0;
+ mDeallocatedCount = 0;
+ }
+
+ size_t mSize,
+ mChildSize;
+ int mAllocatedCount,
+ mDeallocatedCount;
+};
+
+class MemStat : public TraceType<MemStatAccumulator>
+{
+public:
+ typedef TraceType<MemStatAccumulator> trace_t;
+ MemStat(const char* name)
+ : trace_t(name)
+ {}
+};
+
+// measures effective memory footprint of specified type
+// specialize to cover different types
+
+template<typename T>
+struct MemFootprint
+{
+ static size_t measure(const T& value)
+ {
+ return sizeof(T);
+ }
+
+ static size_t measure()
+ {
+ return sizeof(T);
+ }
+};
+
+template<typename T>
+struct MemFootprint<T*>
+{
+ static size_t measure(const T* value)
+ {
+ if (!value)
+ {
+ return 0;
+ }
+ return MemFootprint<T>::measure(*value);
+ }
+
+ static size_t measure()
+ {
+ return MemFootPrint<T>::measure();
+ }
+};
+
+template<typename T>
+struct MemFootprint<std::basic_string<T> >
+{
+ static size_t measure(const std::basic_string<T>& value)
+ {
+ return value.capacity() * sizeof(T);
+ }
+
+ static size_t measure()
+ {
+ return sizeof(std::basic_string<T>);
+ }
+};
+
+template<typename T>
+struct MemFootprint<std::vector<T> >
+{
+ static size_t measure(const std::vector<T>& value)
+ {
+ return value.capacity() * MemFootPrint<T>::measure();
+ }
+
+ static size_t measure()
+ {
+ return sizeof(std::vector<T>);
+ }
+};
+
+template<typename T>
+struct MemFootprint<std::list<T> >
+{
+ static size_t measure(const std::list<T>& value)
+ {
+ return value.size() * (MemFootPrint<T>::measure() + sizeof(void*) * 2);
+ }
+
+ static size_t measure()
+ {
+ return sizeof(std::list<T>);
+ }
+};
+
+template<typename T>
+class MemTrackable
+{
+ template<typename TRACKED, typename TRACKED_IS_TRACKER>
+ struct TrackMemImpl;
+
+ typedef MemTrackable<T> mem_trackable_t;
+
+public:
+ typedef void mem_trackable_tag_t;
+
+ ~MemTrackable()
+ {
+ memDisclaim(mMemFootprint);
+ }
+
+ void* operator new(size_t allocation_size)
+ {
+ // reserve 8 bytes for allocation size (and preserving 8 byte alignment of structs)
+ void* allocation = ::operator new(allocation_size + 8);
+ *(size_t*)allocation = allocation_size;
+ MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+ accumulator.mSize += allocation_size;
+ accumulator.mAllocatedCount++;
+ return (void*)((char*)allocation + 8);
+ }
+
+ void operator delete(void* ptr)
+ {
+ size_t* allocation_size = (size_t*)((char*)ptr - 8);
+ MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+ accumulator.mSize -= *allocation_size;
+ accumulator.mAllocatedCount--;
+ accumulator.mDeallocatedCount++;
+ ::delete((char*)ptr - 8);
+ }
+
+ void *operator new [](size_t size)
+ {
+ size_t* result = (size_t*)malloc(size + 8);
+ *result = size;
+ MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+ accumulator.mSize += size;
+ accumulator.mAllocatedCount++;
+ return (void*)((char*)result + 8);
+ }
+
+ void operator delete[](void* ptr)
+ {
+ size_t* allocation_size = (size_t*)((char*)ptr - 8);
+ MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+ accumulator.mSize -= *allocation_size;
+ accumulator.mAllocatedCount--;
+ accumulator.mDeallocatedCount++;
+ ::delete[]((char*)ptr - 8);
+ }
+
+ // claim memory associated with other objects/data as our own, adding to our calculated footprint
+ template<typename T>
+ T& memClaim(T& value)
+ {
+ TrackMemImpl<T>::claim(*this, value);
+ return value;
+ }
+
+ template<typename T>
+ const T& memClaim(const T& value)
+ {
+ TrackMemImpl<T>::claim(*this, value);
+ return value;
+ }
+
+
+ void memClaim(size_t size)
+ {
+ MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+ mMemFootprint += size;
+ accumulator.mSize += size;
+ }
+
+ // remove memory we had claimed from our calculated footprint
+ template<typename T>
+ T& memDisclaim(T& value)
+ {
+ TrackMemImpl<T>::disclaim(*this, value);
+ return value;
+ }
+
+ template<typename T>
+ const T& memDisclaim(const T& value)
+ {
+ TrackMemImpl<T>::disclaim(*this, value);
+ return value;
+ }
+
+ void memDisclaim(size_t size)
+ {
+ MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+ accumulator.mSize -= size;
+ mMemFootprint -= size;
+ }
+
+private:
+ size_t mMemFootprint;
+
+ template<typename TRACKED, typename TRACKED_IS_TRACKER = void>
+ struct TrackMemImpl
+ {
+ static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
+ {
+ MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+ size_t footprint = MemFootprint<TRACKED>::measure(tracked);
+ accumulator.mSize += footprint;
+ tracker.mMemFootprint += footprint;
+ }
+
+ static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
+ {
+ MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+ size_t footprint = MemFootprint<TRACKED>::measure(tracked);
+ accumulator.mSize -= footprint;
+ tracker.mMemFootprint -= footprint;
+ }
+ };
+
+ template<typename TRACKED>
+ struct TrackMemImpl<TRACKED, typename TRACKED::mem_trackable_tag_t>
+ {
+ static void claim(mem_trackable_t& tracker, TRACKED& tracked)
+ {
+ MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+ accumulator.mChildSize += MemFootprint<TRACKED>::measure(tracked);
+ }
+
+ static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
+ {
+ MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+ accumulator.mChildSize -= MemFootprint<TRACKED>::measure(tracked);
+ }
+ };
+ static MemStat sStat;
+};
+
+template<typename T> MemStat MemTrackable<T>::sStat(typeid(T).name());
+
+}
#endif // LL_LLTRACE_H