7#ifndef PXR_BASE_TF_MALLOC_TAG_H
8#define PXR_BASE_TF_MALLOC_TAG_H
11#include "pxr/base/tf/api.h"
26PXR_NAMESPACE_OPEN_SCOPE
44struct Tf_MallocPathNode;
56 struct _ImmortalName {
144 size_t maxPrintedNodes = 100000)
const;
153 const std::string &rootName)
const;
158 std::ostream &out)
const;
212 TF_API
static bool Initialize(std::string* errMsg =
nullptr);
230#ifdef PXR_ARCH_SUPPORT_MALLOC_HOOKS
231 return TfMallocTag::_initState
232 .load(std::memory_order_acquire) == _Initialized;
339 Auto& operator=(
const Auto &) =
delete;
364 template <
class Str,
class... Strs>
365 explicit Auto(Str &&name1, Strs &&... nameN)
372 (..., (_nTags += (TfMallocTag::_Begin(
373 _TagName(std::forward<Strs>(nameN)),
374 _threadData) ? 1 : 0)));
390 TfMallocTag::_End(_nTags, _threadData);
391 _threadData =
nullptr;
417 static constexpr bool _IsImmortalCharArray =
418 std::is_lvalue_reference_v<Str> &&
419 std::is_array_v<std::remove_reference_t<Str>> &&
421 std::remove_extent_t<std::remove_reference_t<Str>>>;
424 static auto _TagName(Str &&name) {
425 if constexpr (_IsImmortalCharArray<Str &&>) {
426 return _ImmortalName { name };
429 return _TagNameNotArray(std::forward<Str>(name));
437 return _ImmortalName { s.c_str() };
439 static char const *_TagNameNotArray(
char const *cstr) {
return cstr; }
440 static char const *_TagNameNotArray(std::string
const &str) {
449 _ThreadData* _threadData;
474 explicit StackState(Tf_MallocPathNode *top) : _top(top) {}
476 Tf_MallocPathNode *_top =
nullptr;
498 , _tls(state._top ? _Push() :
nullptr) {}
505 if (ARCH_UNLIKELY(_tls)) {
511 TF_API _ThreadData *_Push()
const;
512 TF_API
void _Pop()
const;
546 : _td(std::exchange(other._td,
nullptr))
547 , _scope(std::exchange(other._scope, _NotPaused)) {}
552 if (
this != &other) {
556 _td = std::exchange(other._td,
nullptr);
557 _scope = std::exchange(other._scope, _NotPaused);
594 return _scope != _NotPaused;
599 _NotPaused, _ThisThread, _AllThreads
603 explicit PauseControl(_Scope desired) {
604 if (desired != _NotPaused) {
610 void _Pause(_Scope desired);
615 _ThreadData *_td =
nullptr;
616 _Scope _scope = _NotPaused;
660 static void Push(
const std::string& name) {
665 static void Push(
const char* name) {
671 _Push(_ImmortalName { name.c_str() });
740#ifdef PXR_ARCH_SUPPORT_MALLOC_HOOKS
752 friend struct _TemporaryDisabler;
754 friend struct Tf_MallocGlobalData;
756 static inline _ThreadData *_Push(
char const *name) {
762 static inline _ThreadData *_Push(_ImmortalName name) {
769 TF_API
static _ThreadData *
770 _Begin(
char const *name, _ThreadData *threadData =
nullptr);
772 TF_API
static _ThreadData *
773 _Begin(_ImmortalName name, _ThreadData *threadData =
nullptr);
778 TF_API
static void _End(
int nTags, _ThreadData *threadData);
782 TF_API
static void _PopChecked();
784 TF_API
static StackState _GetCurrentStackState();
786 static void* _MallocWrapper(
size_t,
const void*);
787 static void* _ReallocWrapper(
void*,
size_t,
const void*);
788 static void* _MemalignWrapper(
size_t,
size_t,
const void*);
789 static void _FreeWrapper(
void*,
const void*);
793 friend class TfMallocTag::Tls;
794#ifdef PXR_ARCH_SUPPORT_MALLOC_HOOKS
795 TF_API
static std::atomic<_InitState> _initState;
837PXR_NAMESPACE_CLOSE_SCOPE
839#define TF_MALLOC_TAG_NEW(...) \
841 ARCH_ALWAYS_INLINE inline void* operator new(::std::size_t, void* ptr) { \
845 ARCH_ALWAYS_INLINE inline void* operator new(::std::size_t s) { \
846 PXR_NS::TfAutoMallocTag tag(__VA_ARGS__); \
847 return ::operator new(s, std::nothrow); \
850 ARCH_ALWAYS_INLINE inline void* operator new[](::std::size_t s) { \
851 PXR_NS::TfAutoMallocTag tag(__VA_ARGS__); \
852 return ::operator new[](s, std::nothrow); \
856 ARCH_ALWAYS_INLINE inline void operator delete(void* ptr, void* place) {} \
858 ARCH_ALWAYS_INLINE inline void operator delete(void* ptr, size_t) { \
859 ::operator delete(ptr, std::nothrow); \
862 ARCH_ALWAYS_INLINE inline void operator delete[] (void* ptr, size_t) { \
863 ::operator delete[](ptr, std::nothrow); \
An immutable, interned string whose character data is guaranteed to remain valid at a fixed address f...
Auto(Str &&name1, Strs &&... nameN)
Push one or more memory tags onto the local-call stack with names name1 ... nameN.
~Auto()
Pop a memory tag from the local-call stack.
void Release()
Pop the tag from the stack before it is destructed.
Debugging-oriented RAII object that pauses malloc tag collection for either the current thread or all...
void Unpause()
Resume collection. This PauseControl must currently be paused.
void PauseThisThread()
Pause collection on the current thread.
bool IsPaused() const
Return true if this PauseControl is currently paused.
PauseControl & operator=(PauseControl &&other) noexcept
Move-assign from other, adopting its pause state and leaving it unpaused.
~PauseControl()
Unpause if paused.
PauseControl(PauseControl &&other) noexcept
Move-construct from other, adopting its pause state and leaving it unpaused.
void PauseAllThreads()
Pause collection on all threads.
An object that represents a snapshot of a thread's TfMallocTag stack state.
Top-down memory tagging system.
static void Push(const char *name)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static void Push(TfEternalString name)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static TF_API void SetDebugMatchList(const std::string &matchList)
Sets the tags to trap in the debugger.
size_t numAllocations
The number of allocations (always one unless stack frames have been combined to create unique stacks)...
static StackState GetCurrentStackState()
Capture the current thread's TfMallocTag stack state and return it.
static TF_API std::vector< std::vector< uintptr_t > > GetCapturedMallocStacks()
Returns the captured malloc stack traces for allocations billed to the malloc tags passed to SetCaptu...
static TF_API void SetCapturedMallocStacksMatchList(const std::string &matchList)
Sets the tags to trace.
static void Push(const std::string &name)
Manually push a tag onto the stack.
std::vector< uintptr_t > stack
The stack frame pointers.
size_t size
The amount of allocated memory (accumulated over all allocations sharing this call stack).
static TF_API bool Initialize(std::string *errMsg=nullptr)
Initialize the memory tagging system.
static PauseControl PauseThisThread()
Return a PauseControl that immediately pauses collection for the calling thread.
static TF_API size_t GetTotalBytes()
Return total number of allocated bytes.
static TF_API void Shutdown()
Shutdown the memory tagging system.
static PauseControl DeferredPause()
Return a PauseControl in the unpaused state, for later manual control via PauseThisThread() or PauseA...
static bool IsInitialized()
Return true if the tagging system is active.
static void Pop()
Manually pop a tag from the stack.
static TF_API bool GetCallTree(CallTree *tree, bool skipRepeated=true)
Return a snapshot of memory usage.
static TF_API size_t GetMaxTotalBytes()
Return an estimate of the maximum total number of bytes that have ever been allocated at one time.
static PauseControl PauseAllThreads()
Return a PauseControl that immediately pauses collection for all threads.
static TF_API void Clear()
Clear all recorded allocation events, in-flight events from all threads, and reset the total bytes an...
static TF_API std::string GetPerfStats(bool includePerThread=false)
Return a report of diagnostic information related to the performance of the TfMallocTag tracking inte...
This struct is used to represent a call stack taken for an allocation that was billed under a specifi...
Stripped down version of diagnostic.h that doesn't define std::string.
Summary data structure for malloc statistics.
std::vector< PathNode > children
Children nodes.
TF_API std::string GetPrettyPrintString(PrintSetting setting=BOTH, size_t maxPrintedNodes=100000) const
Return the malloc report string.
size_t nAllocations
The number of allocations for this node.
std::string siteName
Tag name.
std::vector< CallStackInfo > capturedCallStacks
The captured malloc stacks.
size_t nBytes
Mem allocated including descendant nodes.
TF_API void Report(std::ostream &out) const
Generates a report to the ostream out.
size_t nBytesDirect
Mem allocated excluding descendant nodes.
std::string name
Tag name.
PrintSetting
Specify which parts of the report to print.
@ BOTH
Print both tree and call sites.
@ TREE
Print the full call tree.
@ CALLSITES
Print just the call sites > 0.1%.
PathNode root
Root node of the call-site hierarchy.
TF_API void Report(std::ostream &out, const std::string &rootName) const
Generates a report to the ostream out.
TF_API bool LoadReport(std::istream &in)
Load the contents of in into the root of the call tree.
std::vector< CallSite > callSites
All call sites.
Record of the bytes allocated under each different tag.
Node in the call tree structure.