Loading...
Searching...
No Matches
mallocTag.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_TF_MALLOC_TAG_H
8#define PXR_BASE_TF_MALLOC_TAG_H
9
10#include "pxr/pxr.h"
11#include "pxr/base/tf/api.h"
12#include "pxr/base/arch/hints.h"
13
14#include <atomic>
15#include <cstdlib>
16#include <cstdint>
17#include <iosfwd>
18#include <string>
19#include <vector>
20
21PXR_NAMESPACE_OPEN_SCOPE
22
25
26struct Tf_MallocPathNode;
27
35public:
36 struct CallStackInfo;
37
44 struct CallTree {
64 struct PathNode {
65 size_t nBytes,
67 size_t nAllocations;
68 std::string siteName;
69 std::vector<PathNode>
71 };
72
81 struct CallSite {
82 std::string name;
83 size_t nBytes;
84 };
85
88 TREE = 0,
90 BOTH
91 };
92
93
96
117 TF_API
119 size_t maxPrintedNodes = 100000) const;
120
125 TF_API
126 void Report(
127 std::ostream &out,
128 const std::string &rootName) const;
129
131 TF_API
132 void Report(
133 std::ostream &out) const;
134
138 TF_API
140 std::istream &in);
141
143
144
146 std::vector<CallSite> callSites;
147
150
152 std::vector<CallStackInfo> capturedCallStacks;
153 };
154
159 {
161 std::vector<uintptr_t> stack;
162
165 size_t size;
166
170 };
171
183 TF_API static bool Initialize(std::string* errMsg);
184
189 static bool IsInitialized() {
190 return TfMallocTag::_isInitialized;
191 }
192
198 TF_API static size_t GetTotalBytes();
199
205 TF_API static size_t GetMaxTotalBytes();
206
219 TF_API static bool GetCallTree(CallTree* tree, bool skipRepeated = true);
220
221private:
222
223 struct _ThreadData;
224
225public:
226
250 class Auto {
251 public:
252 Auto(const Auto &) = delete;
253 Auto& operator=(const Auto &) = delete;
254
255 Auto(Auto &&) = delete;
256 Auto& operator=(Auto &&) = delete;
257
275 template <class Str, class... Strs>
276 explicit Auto(Str &&name1, Strs &&... nameN)
277 : _threadData(TfMallocTag::_Push(_CStr(std::forward<Str>(name1))))
278 , _nTags(_threadData ? 1 + sizeof...(Strs) : 0) {
279 if (_threadData) {
280 (..., TfMallocTag::_Begin(
281 _CStr(std::forward<Strs>(nameN)), _threadData));
282 }
283 }
284
295 inline void Release() {
296 if (_threadData) {
297 TfMallocTag::_End(_nTags, _threadData);
298 _threadData = nullptr;
299 }
300 }
301
307 inline ~Auto() {
308 Release();
309 }
310
311 private:
312
313 char const *_CStr(char const *cstr) const { return cstr; }
314 char const *_CStr(std::string const &str) const { return str.c_str(); }
315
316 _ThreadData* _threadData;
317 int _nTags;
318
319 friend class TfMallocTag;
320 };
321
322 // An historical compatibility: before Auto could accept only one argument,
323 // so Auto2 existed to handle two arguments. Now Auto can accept any number
324 // of arguments, so Auto2 is just an alias for Auto.
325 using Auto2 = Auto;
326
327 // fwd for friendship.
328 class StackOverride;
329
337 public:
338 StackState() = default;
339
340 private:
341 explicit StackState(Tf_MallocPathNode *top) : _top(top) {}
342
343 Tf_MallocPathNode *_top = nullptr;
344
345 friend class TfMallocTag;
346 friend class StackOverride;
347 };
348
362 public:
363 explicit StackOverride(StackState state)
364 : _state(state)
365 , _tls(state._top ? _Push() : nullptr) {}
366
367 // Noncopyable, nonmovable.
368 StackOverride(const StackOverride &) = delete;
369 StackOverride &operator=(const StackOverride &) = delete;
370
372 if (ARCH_UNLIKELY(_tls)) {
373 _Pop();
374 }
375 }
376
377 private:
378 TF_API _ThreadData *_Push() const;
379 TF_API void _Pop() const;
380
381 const StackState _state;
382 _ThreadData *_tls;
383
384 friend class TfMallocTag;
385 };
386
394 return ARCH_UNLIKELY(TfMallocTag::_isInitialized)
395 ? _GetCurrentStackState() : StackState {};
396 }
397
407 static void Push(const std::string& name) {
408 _Push(name.c_str());
409 }
410
412 static void Push(const char* name) {
413 _Push(name);
414 }
415
421 static void Pop() {
422 if (TfMallocTag::_isInitialized) {
423 _End();
424 }
425 }
426
444 TF_API static void SetDebugMatchList(const std::string& matchList);
445
467 TF_API static void
468 SetCapturedMallocStacksMatchList(const std::string& matchList);
469
475 TF_API static std::vector<std::vector<uintptr_t> > GetCapturedMallocStacks();
476
477private:
478 friend struct _TemporaryDisabler;
479
480 friend struct Tf_MallocGlobalData;
481
482 static bool _Initialize(std::string* errMsg);
483
484 static inline _ThreadData *_Push(char const *name) {
485 if (TfMallocTag::_isInitialized) {
486 return _Begin(name);
487 }
488 return nullptr;
489 }
490
491 TF_API static _ThreadData *_Begin(char const *name,
492 _ThreadData *threadData = nullptr);
493 TF_API static void _End(int nTags = 1, _ThreadData *threadData = nullptr);
494
495 TF_API static StackState _GetCurrentStackState();
496
497 static void* _MallocWrapper(size_t, const void*);
498 static void* _ReallocWrapper(void*, size_t, const void*);
499 static void* _MemalignWrapper(size_t, size_t, const void*);
500 static void _FreeWrapper(void*, const void*);
501
502 friend class TfMallocTag::Auto;
503 class Tls;
504 friend class TfMallocTag::Tls;
505 TF_API static std::atomic<bool> _isInitialized;
506};
507
510
513
547//
548PXR_NAMESPACE_CLOSE_SCOPE
549
550#define TF_MALLOC_TAG_NEW(name1, name2) \
551 /* this is for STL purposes */ \
552 ARCH_ALWAYS_INLINE inline void* operator new(::std::size_t, void* ptr) { \
553 return ptr; \
554 } \
555 \
556 ARCH_ALWAYS_INLINE inline void* operator new(::std::size_t s) { \
557 PXR_NS::TfAutoMallocTag tag(name1, name2); \
558 return malloc(s); \
559 } \
560 \
561 ARCH_ALWAYS_INLINE inline void* operator new[](::std::size_t s) { \
562 PXR_NS::TfAutoMallocTag tag(name1, name2); \
563 return malloc(s); \
564 } \
565 \
566 /* Required due to the placement-new override above. */ \
567 ARCH_ALWAYS_INLINE inline void operator delete(void* ptr, void* place) {} \
568 \
569 ARCH_ALWAYS_INLINE inline void operator delete(void* ptr, size_t) { \
570 free(ptr); \
571 } \
572 \
573 ARCH_ALWAYS_INLINE inline void operator delete[] (void* ptr, size_t) { \
574 free(ptr); \
575 } \
576
577#endif
Scoped (i.e.
Definition: mallocTag.h:250
Auto(Str &&name1, Strs &&... nameN)
Push one or more memory tags onto the local-call stack with names name1 ... nameN.
Definition: mallocTag.h:276
~Auto()
Pop a memory tag from the local-call stack.
Definition: mallocTag.h:307
void Release()
Pop the tag from the stack before it is destructed.
Definition: mallocTag.h:295
An object that represents a snapshot of a thread's TfMallocTag stack state.
Definition: mallocTag.h:336
Top-down memory tagging system.
Definition: mallocTag.h:34
static void Push(const char *name)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: mallocTag.h:412
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)...
Definition: mallocTag.h:169
static StackState GetCurrentStackState()
Capture the current thread's TfMallocTag stack state and return it.
Definition: mallocTag.h:393
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.
Definition: mallocTag.h:407
std::vector< uintptr_t > stack
The stack frame pointers.
Definition: mallocTag.h:161
size_t size
The amount of allocated memory (accumulated over all allocations sharing this call stack).
Definition: mallocTag.h:165
static TF_API size_t GetTotalBytes()
Return total number of allocated bytes.
static TF_API bool Initialize(std::string *errMsg)
Initialize the memory tagging system.
static bool IsInitialized()
Return true if the tagging system is active.
Definition: mallocTag.h:189
static void Pop()
Manually pop a tag from the stack.
Definition: mallocTag.h:421
static TF_API bool GetCallTree(CallTree *tree, bool skipRepeated=true)
Return a snapshot of memory usage.
static TF_API size_t GetMaxTotalBytes()
Return the maximum total number of bytes that have ever been allocated at one time.
This struct is used to represent a call stack taken for an allocation that was billed under a specifi...
Definition: mallocTag.h:159
Compiler hints.
STL namespace.
Summary data structure for malloc statistics.
Definition: mallocTag.h:44
std::vector< PathNode > children
Children nodes.
Definition: mallocTag.h:70
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.
Definition: mallocTag.h:67
std::string siteName
Tag name.
Definition: mallocTag.h:68
std::vector< CallStackInfo > capturedCallStacks
The captured malloc stacks.
Definition: mallocTag.h:152
size_t nBytes
Mem allocated including descendant nodes.
Definition: mallocTag.h:65
TF_API void Report(std::ostream &out) const
Generates a report to the ostream out.
size_t nBytesDirect
Mem allocated excluding descendant nodes.
Definition: mallocTag.h:66
std::string name
Tag name.
Definition: mallocTag.h:82
PrintSetting
Specify which parts of the report to print.
Definition: mallocTag.h:87
@ BOTH
Print both tree and call sites.
Definition: mallocTag.h:90
@ TREE
Print the full call tree.
Definition: mallocTag.h:88
@ CALLSITES
Print just the call sites > 0.1%.
Definition: mallocTag.h:89
PathNode root
Root node of the call-site hierarchy.
Definition: mallocTag.h:149
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.
Definition: mallocTag.h:146
Record of the bytes allocated under each different tag.
Definition: mallocTag.h:81
Node in the call tree structure.
Definition: mallocTag.h:64